Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
后端镜像
Tabby
提交
b3f15e27
T
Tabby
项目概览
后端镜像
/
Tabby
通知
33
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
Tabby
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b3f15e27
编写于
10月 26, 2018
作者:
E
Eugene Pankov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
process completion notifications
上级
822e068b
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
147 addition
and
50 deletion
+147
-50
terminus-core/src/components/baseTab.component.ts
terminus-core/src/components/baseTab.component.ts
+12
-0
terminus-core/src/components/tabHeader.component.ts
terminus-core/src/components/tabHeader.component.ts
+76
-48
terminus-core/src/services/app.service.ts
terminus-core/src/services/app.service.ts
+45
-0
terminus-core/src/services/electron.service.ts
terminus-core/src/services/electron.service.ts
+3
-1
terminus-terminal/src/components/terminalTab.component.ts
terminus-terminal/src/components/terminalTab.component.ts
+11
-1
未找到文件。
terminus-core/src/components/baseTab.component.ts
浏览文件 @
b3f15e27
import
{
Observable
,
Subject
}
from
'
rxjs
'
import
{
ViewRef
}
from
'
@angular/core
'
export
interface
BaseTabProcess
{
name
:
string
}
export
abstract
class
BaseTabComponent
{
private
static
lastTabID
=
0
id
:
number
...
...
@@ -14,6 +18,7 @@ export abstract class BaseTabComponent {
protected
blurred
=
new
Subject
<
void
>
()
protected
progress
=
new
Subject
<
number
>
()
protected
activity
=
new
Subject
<
boolean
>
()
protected
destroyed
=
new
Subject
<
void
>
()
private
progressClearTimeout
:
number
...
...
@@ -22,6 +27,7 @@ export abstract class BaseTabComponent {
get
titleChange$
():
Observable
<
string
>
{
return
this
.
titleChange
}
get
progress$
():
Observable
<
number
>
{
return
this
.
progress
}
get
activity$
():
Observable
<
boolean
>
{
return
this
.
activity
}
get
destroyed$
():
Observable
<
void
>
{
return
this
.
destroyed
}
constructor
()
{
this
.
id
=
BaseTabComponent
.
lastTabID
++
...
...
@@ -66,6 +72,10 @@ export abstract class BaseTabComponent {
return
null
}
async
getCurrentProcess
():
Promise
<
BaseTabProcess
>
{
return
null
}
async
canClose
():
Promise
<
boolean
>
{
return
true
}
...
...
@@ -83,5 +93,7 @@ export abstract class BaseTabComponent {
this
.
blurred
.
complete
()
this
.
titleChange
.
complete
()
this
.
progress
.
complete
()
this
.
destroyed
.
next
()
this
.
destroyed
.
complete
()
}
}
terminus-core/src/components/tabHeader.component.ts
浏览文件 @
b3f15e27
...
...
@@ -20,87 +20,115 @@ export class TabHeaderComponent {
@
Input
()
progress
:
number
@
ViewChild
(
'
handle
'
)
handle
:
ElementRef
private
co
ntextMenu
:
any
private
co
mpletionNotificationEnabled
=
false
constructor
(
zone
:
NgZone
,
electron
:
ElectronService
,
public
app
:
AppService
,
private
electron
:
ElectronService
,
private
zone
:
NgZone
,
private
hostApp
:
HostAppService
,
private
ngbModal
:
NgbModal
,
private
parentDraggable
:
SortableComponent
,
)
{
this
.
contextMenu
=
electron
.
remote
.
Menu
.
buildFromTemplate
([
)
{
}
ngOnInit
()
{
if
(
this
.
hostApp
.
platform
===
Platform
.
macOS
)
{
this
.
parentDraggable
.
setDragHandle
(
this
.
handle
.
nativeElement
)
}
this
.
tab
.
progress$
.
subscribe
(
progress
=>
{
this
.
progress
=
progress
})
}
@
HostListener
(
'
dblclick
'
)
onDoubleClick
():
void
{
let
modal
=
this
.
ngbModal
.
open
(
RenameTabModalComponent
)
modal
.
componentInstance
.
value
=
this
.
tab
.
customTitle
||
this
.
tab
.
title
modal
.
result
.
then
(
result
=>
{
this
.
tab
.
setTitle
(
result
)
this
.
tab
.
customTitle
=
result
}).
catch
(()
=>
null
)
}
@
HostListener
(
'
auxclick
'
,
[
'
$event
'
])
async
onAuxClick
(
$event
:
MouseEvent
)
{
if
(
$event
.
which
===
2
)
{
this
.
app
.
closeTab
(
this
.
tab
,
true
)
}
if
(
$event
.
which
===
3
)
{
event
.
preventDefault
()
let
contextMenu
=
this
.
electron
.
remote
.
Menu
.
buildFromTemplate
([
{
label
:
'
Close
'
,
click
:
()
=>
{
zone
.
run
(()
=>
{
app
.
closeTab
(
this
.
tab
,
true
)
click
:
()
=>
this
.
zone
.
run
(()
=>
{
this
.
app
.
closeTab
(
this
.
tab
,
true
)
})
}
},
{
label
:
'
Close other tabs
'
,
click
:
()
=>
{
zone
.
run
(()
=>
{
for
(
let
tab
of
app
.
tabs
.
filter
(
x
=>
x
!==
this
.
tab
))
{
app
.
closeTab
(
tab
,
true
)
click
:
()
=>
this
.
zone
.
run
(()
=>
{
for
(
let
tab
of
this
.
app
.
tabs
.
filter
(
x
=>
x
!==
this
.
tab
))
{
this
.
app
.
closeTab
(
tab
,
true
)
}
})
}
},
{
label
:
'
Close tabs to the right
'
,
click
:
()
=>
{
zone
.
run
(()
=>
{
for
(
let
tab
of
app
.
tabs
.
slice
(
app
.
tabs
.
indexOf
(
this
.
tab
)
+
1
))
{
app
.
closeTab
(
tab
,
true
)
click
:
()
=>
this
.
zone
.
run
(()
=>
{
for
(
let
tab
of
this
.
app
.
tabs
.
slice
(
this
.
app
.
tabs
.
indexOf
(
this
.
tab
)
+
1
))
{
this
.
app
.
closeTab
(
tab
,
true
)
}
})
}
},
{
label
:
'
Close tabs to the left
'
,
click
:
()
=>
{
zone
.
run
(()
=>
{
for
(
let
tab
of
app
.
tabs
.
slice
(
0
,
app
.
tabs
.
indexOf
(
this
.
tab
)))
{
app
.
closeTab
(
tab
,
true
)
click
:
()
=>
this
.
zone
.
run
(()
=>
{
for
(
let
tab
of
this
.
app
.
tabs
.
slice
(
0
,
this
.
app
.
tabs
.
indexOf
(
this
.
tab
)))
{
this
.
app
.
closeTab
(
tab
,
true
)
}
})
}
},
])
}
ngOnInit
()
{
if
(
this
.
hostApp
.
platform
===
Platform
.
macOS
)
{
this
.
parentDraggable
.
setDragHandle
(
this
.
handle
.
nativeElement
)
}
this
.
tab
.
progress$
.
subscribe
(
progress
=>
{
this
.
progress
=
progress
let
process
=
await
this
.
tab
.
getCurrentProcess
()
if
(
process
)
{
contextMenu
.
append
(
new
this
.
electron
.
MenuItem
({
id
:
'
sep
'
,
type
:
'
separator
'
,
}))
contextMenu
.
append
(
new
this
.
electron
.
MenuItem
({
id
:
'
process-name
'
,
enabled
:
false
,
label
:
'
Current process:
'
+
process
.
name
,
}))
contextMenu
.
append
(
new
this
.
electron
.
MenuItem
({
id
:
'
completion
'
,
label
:
'
Notify when done
'
,
type
:
'
checkbox
'
,
checked
:
this
.
completionNotificationEnabled
,
click
:
()
=>
this
.
zone
.
run
(()
=>
{
this
.
completionNotificationEnabled
=
!
this
.
completionNotificationEnabled
if
(
this
.
completionNotificationEnabled
)
{
this
.
app
.
observeTabCompletion
(
this
.
tab
).
subscribe
(()
=>
{
new
Notification
(
'
Process completed
'
,
{
body
:
process
.
name
,
}).
addEventListener
(
'
click
'
,
()
=>
{
this
.
app
.
selectTab
(
this
.
tab
)
})
this
.
completionNotificationEnabled
=
false
})
}
else
{
this
.
app
.
stopObservingTabCompletion
(
this
.
tab
)
}
@
HostListener
(
'
dblclick
'
)
onDoubleClick
():
void
{
let
modal
=
this
.
ngbModal
.
open
(
RenameTabModalComponent
)
modal
.
componentInstance
.
value
=
this
.
tab
.
customTitle
||
this
.
tab
.
title
modal
.
result
.
then
(
result
=>
{
this
.
tab
.
setTitle
(
result
)
this
.
tab
.
customTitle
=
result
}).
catch
(()
=>
null
)
})
}))
}
@
HostListener
(
'
auxclick
'
,
[
'
$event
'
])
onAuxClick
(
$event
:
MouseEvent
):
void
{
if
(
$event
.
which
===
2
)
{
this
.
app
.
closeTab
(
this
.
tab
,
true
)
}
if
(
$event
.
which
===
3
)
{
this
.
contextMenu
.
popup
({
contextMenu
.
popup
({
x
:
$event
.
pageX
,
y
:
$event
.
pageY
,
async
:
true
,
})
event
.
preventDefault
()
}
}
}
terminus-core/src/services/app.service.ts
浏览文件 @
b3f15e27
import
{
Observable
,
Subject
,
AsyncSubject
}
from
'
rxjs
'
import
{
takeUntil
}
from
'
rxjs/operators
'
import
{
Injectable
,
ComponentFactoryResolver
,
Injector
}
from
'
@angular/core
'
import
{
BaseTabComponent
}
from
'
../components/baseTab.component
'
import
{
Logger
,
LogService
}
from
'
./log.service
'
...
...
@@ -7,6 +8,33 @@ import { HostAppService } from './hostApp.service'
export
declare
type
TabComponentType
=
new
(...
args
:
any
[])
=>
BaseTabComponent
class
CompletionObserver
{
get
done$
():
Observable
<
void
>
{
return
this
.
done
}
get
destroyed$
():
Observable
<
void
>
{
return
this
.
destroyed
}
private
done
=
new
AsyncSubject
<
void
>
()
private
destroyed
=
new
AsyncSubject
<
void
>
()
private
interval
:
number
constructor
(
private
tab
:
BaseTabComponent
)
{
this
.
interval
=
setInterval
(()
=>
this
.
tick
(),
1000
)
this
.
tab
.
destroyed$
.
pipe
(
takeUntil
(
this
.
destroyed$
)).
subscribe
(()
=>
this
.
stop
())
}
async
tick
()
{
if
(
!
(
await
this
.
tab
.
getCurrentProcess
()))
{
this
.
done
.
next
(
null
)
this
.
stop
()
}
}
stop
()
{
clearInterval
(
this
.
interval
)
this
.
destroyed
.
next
(
null
)
this
.
destroyed
.
complete
()
this
.
done
.
complete
()
}
}
@
Injectable
()
export
class
AppService
{
tabs
:
BaseTabComponent
[]
=
[]
...
...
@@ -20,6 +48,8 @@ export class AppService {
private
tabClosed
=
new
Subject
<
BaseTabComponent
>
()
private
ready
=
new
AsyncSubject
<
void
>
()
private
completionObservers
=
new
Map
<
BaseTabComponent
,
CompletionObserver
>
()
get
activeTabChange$
():
Observable
<
BaseTabComponent
>
{
return
this
.
activeTabChange
}
get
tabOpened$
():
Observable
<
BaseTabComponent
>
{
return
this
.
tabOpened
}
get
tabsChanged$
():
Observable
<
void
>
{
return
this
.
tabsChanged
}
...
...
@@ -133,4 +163,19 @@ export class AppService {
this
.
ready
.
complete
()
this
.
hostApp
.
emitReady
()
}
observeTabCompletion
(
tab
:
BaseTabComponent
):
Observable
<
void
>
{
if
(
!
this
.
completionObservers
.
has
(
tab
))
{
let
observer
=
new
CompletionObserver
(
tab
)
observer
.
destroyed$
.
subscribe
(()
=>
{
this
.
stopObservingTabCompletion
(
tab
)
})
this
.
completionObservers
.
set
(
tab
,
observer
)
}
return
this
.
completionObservers
.
get
(
tab
).
done$
}
stopObservingTabCompletion
(
tab
:
BaseTabComponent
)
{
this
.
completionObservers
.
delete
(
tab
)
}
}
terminus-core/src/services/electron.service.ts
浏览文件 @
b3f15e27
import
{
Injectable
}
from
'
@angular/core
'
import
{
TouchBar
,
BrowserWindow
,
Menu
}
from
'
electron
'
import
{
TouchBar
,
BrowserWindow
,
Menu
,
MenuItem
}
from
'
electron
'
@
Injectable
()
export
class
ElectronService
{
...
...
@@ -15,6 +15,7 @@ export class ElectronService {
TouchBar
:
typeof
TouchBar
BrowserWindow
:
typeof
BrowserWindow
Menu
:
typeof
Menu
MenuItem
:
typeof
MenuItem
private
electron
:
any
constructor
()
{
...
...
@@ -31,6 +32,7 @@ export class ElectronService {
this
.
TouchBar
=
this
.
remote
.
TouchBar
this
.
BrowserWindow
=
this
.
remote
.
BrowserWindow
this
.
Menu
=
this
.
remote
.
Menu
this
.
MenuItem
=
this
.
remote
.
MenuItem
}
remoteRequire
(
name
:
string
):
any
{
...
...
terminus-terminal/src/components/terminalTab.component.ts
浏览文件 @
b3f15e27
...
...
@@ -2,7 +2,7 @@ import { Observable, Subject, Subscription } from 'rxjs'
import
{
first
}
from
'
rxjs/operators
'
import
{
ToastrService
}
from
'
ngx-toastr
'
import
{
Component
,
NgZone
,
Inject
,
Optional
,
ViewChild
,
HostBinding
,
Input
}
from
'
@angular/core
'
import
{
AppService
,
ConfigService
,
BaseTabComponent
,
ElectronService
,
HostAppService
,
HotkeysService
,
Platform
}
from
'
terminus-core
'
import
{
AppService
,
ConfigService
,
BaseTabComponent
,
BaseTabProcess
,
ElectronService
,
HostAppService
,
HotkeysService
,
Platform
}
from
'
terminus-core
'
import
{
IShell
}
from
'
../api
'
import
{
Session
,
SessionsService
}
from
'
../services/sessions.service
'
...
...
@@ -347,6 +347,16 @@ export class TerminalTabComponent extends BaseTabComponent {
this
.
frontend
.
setZoom
(
this
.
zoom
)
}
async
getCurrentProcess
():
Promise
<
BaseTabProcess
>
{
let
children
=
await
this
.
session
.
getChildProcesses
()
if
(
!
children
.
length
)
{
return
null
}
return
{
name
:
children
[
0
].
command
}
}
ngOnDestroy
()
{
this
.
frontend
.
detach
(
this
.
content
.
nativeElement
)
this
.
detachTermContainerHandlers
()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录