mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-05 02:50:00 +00:00
moved menu zone handling into terminus-electron
This commit is contained in:
parent
cdf97f3b31
commit
96ce42461d
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import { Injectable, NgZone } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { Subscription } from 'rxjs'
|
import { Subscription } from 'rxjs'
|
||||||
import { AppService } from './services/app.service'
|
import { AppService } from './services/app.service'
|
||||||
import { BaseTabComponent } from './components/baseTab.component'
|
import { BaseTabComponent } from './components/baseTab.component'
|
||||||
@ -15,7 +15,6 @@ export class TabManagementContextMenu extends TabContextMenuItemProvider {
|
|||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private app: AppService,
|
private app: AppService,
|
||||||
private zone: NgZone,
|
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
@ -24,13 +23,13 @@ export class TabManagementContextMenu extends TabContextMenuItemProvider {
|
|||||||
let items: MenuItemOptions[] = [
|
let items: MenuItemOptions[] = [
|
||||||
{
|
{
|
||||||
label: 'Close',
|
label: 'Close',
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
if (this.app.tabs.includes(tab)) {
|
if (this.app.tabs.includes(tab)) {
|
||||||
this.app.closeTab(tab, true)
|
this.app.closeTab(tab, true)
|
||||||
} else {
|
} else {
|
||||||
tab.destroy()
|
tab.destroy()
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
if (tabHeader) {
|
if (tabHeader) {
|
||||||
@ -38,27 +37,27 @@ export class TabManagementContextMenu extends TabContextMenuItemProvider {
|
|||||||
...items,
|
...items,
|
||||||
{
|
{
|
||||||
label: 'Close other tabs',
|
label: 'Close other tabs',
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
for (const t of this.app.tabs.filter(x => x !== tab)) {
|
for (const t of this.app.tabs.filter(x => x !== tab)) {
|
||||||
this.app.closeTab(t, true)
|
this.app.closeTab(t, true)
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Close tabs to the right',
|
label: 'Close tabs to the right',
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
for (const t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
|
for (const t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
|
||||||
this.app.closeTab(t, true)
|
this.app.closeTab(t, true)
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Close tabs to the left',
|
label: 'Close tabs to the left',
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
for (const t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
|
for (const t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
|
||||||
this.app.closeTab(t, true)
|
this.app.closeTab(t, true)
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
@ -73,9 +72,9 @@ export class TabManagementContextMenu extends TabContextMenuItemProvider {
|
|||||||
l: 'Left',
|
l: 'Left',
|
||||||
t: 'Up',
|
t: 'Up',
|
||||||
}[dir],
|
}[dir],
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
(tab.parent as SplitTabComponent).splitTab(tab, dir)
|
(tab.parent as SplitTabComponent).splitTab(tab, dir)
|
||||||
}),
|
},
|
||||||
})) as MenuItemOptions[],
|
})) as MenuItemOptions[],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -100,7 +99,6 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
|||||||
weight = -1
|
weight = -1
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private zone: NgZone,
|
|
||||||
private app: AppService,
|
private app: AppService,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
@ -113,11 +111,11 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
|||||||
...items,
|
...items,
|
||||||
{
|
{
|
||||||
label: 'Rename',
|
label: 'Rename',
|
||||||
click: () => this.zone.run(() => tabHeader.showRenameTabModal()),
|
click: () => tabHeader.showRenameTabModal(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Duplicate',
|
label: 'Duplicate',
|
||||||
click: () => this.zone.run(() => this.app.duplicateTab(tab)),
|
click: () => this.app.duplicateTab(tab),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Color',
|
label: 'Color',
|
||||||
@ -126,9 +124,9 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
|||||||
label: color.name,
|
label: color.name,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
checked: tab.color === color.value,
|
checked: tab.color === color.value,
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
tab.color = color.value
|
tab.color = color.value
|
||||||
}),
|
},
|
||||||
})) as MenuItemOptions[],
|
})) as MenuItemOptions[],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -142,7 +140,6 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
|||||||
export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
||||||
constructor (
|
constructor (
|
||||||
private app: AppService,
|
private app: AppService,
|
||||||
private zone: NgZone,
|
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
@ -162,7 +159,7 @@ export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
|||||||
label: 'Notify when done',
|
label: 'Notify when done',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
checked: extTab.__completionNotificationEnabled,
|
checked: extTab.__completionNotificationEnabled,
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
extTab.__completionNotificationEnabled = !extTab.__completionNotificationEnabled
|
extTab.__completionNotificationEnabled = !extTab.__completionNotificationEnabled
|
||||||
|
|
||||||
if (extTab.__completionNotificationEnabled) {
|
if (extTab.__completionNotificationEnabled) {
|
||||||
@ -177,14 +174,14 @@ export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
|||||||
} else {
|
} else {
|
||||||
this.app.stopObservingTabCompletion(tab)
|
this.app.stopObservingTabCompletion(tab)
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
items.push({
|
items.push({
|
||||||
label: 'Notify on activity',
|
label: 'Notify on activity',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
checked: !!extTab.__outputNotificationSubscription,
|
checked: !!extTab.__outputNotificationSubscription,
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
if (extTab.__outputNotificationSubscription) {
|
if (extTab.__outputNotificationSubscription) {
|
||||||
extTab.__outputNotificationSubscription.unsubscribe()
|
extTab.__outputNotificationSubscription.unsubscribe()
|
||||||
extTab.__outputNotificationSubscription = null
|
extTab.__outputNotificationSubscription = null
|
||||||
@ -201,7 +198,7 @@ export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
})
|
})
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
@ -147,9 +147,19 @@ export class ElectronPlatformService extends PlatformService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
popupContextMenu (menu: MenuItemOptions[], _event?: MouseEvent): void {
|
popupContextMenu (menu: MenuItemOptions[], _event?: MouseEvent): void {
|
||||||
this.electron.Menu.buildFromTemplate(menu.map(item => ({
|
this.electron.Menu.buildFromTemplate(menu.map(item => this.rewrapMenuItemOptions(item))).popup({})
|
||||||
...item,
|
}
|
||||||
}))).popup({})
|
|
||||||
|
rewrapMenuItemOptions (menu: MenuItemOptions): MenuItemOptions {
|
||||||
|
return {
|
||||||
|
...menu,
|
||||||
|
click: () => {
|
||||||
|
this.zone.run(() => {
|
||||||
|
menu.click?.()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submenu: menu.submenu ? menu.submenu.map(x => this.rewrapMenuItemOptions(x)) : undefined,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async showMessageBox (options: MessageBoxOptions): Promise<MessageBoxResult> {
|
async showMessageBox (options: MessageBoxOptions): Promise<MessageBoxResult> {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Injectable, NgZone } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { ConfigService, BaseTabComponent, TabContextMenuItemProvider, TabHeaderComponent, SplitTabComponent, NotificationsService, MenuItemOptions } from 'terminus-core'
|
import { ConfigService, BaseTabComponent, TabContextMenuItemProvider, TabHeaderComponent, SplitTabComponent, NotificationsService, MenuItemOptions } from 'terminus-core'
|
||||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||||
import { UACService } from './services/uac.service'
|
import { UACService } from './services/uac.service'
|
||||||
@ -9,7 +9,6 @@ import { TerminalService } from './services/terminal.service'
|
|||||||
export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
||||||
constructor (
|
constructor (
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
private zone: NgZone,
|
|
||||||
private notifications: NotificationsService,
|
private notifications: NotificationsService,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
@ -22,7 +21,7 @@ export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
|||||||
const items: MenuItemOptions[] = [
|
const items: MenuItemOptions[] = [
|
||||||
{
|
{
|
||||||
label: 'Save as profile',
|
label: 'Save as profile',
|
||||||
click: () => this.zone.run(async () => {
|
click: async () => {
|
||||||
const profile = {
|
const profile = {
|
||||||
sessionOptions: {
|
sessionOptions: {
|
||||||
...tab.sessionOptions,
|
...tab.sessionOptions,
|
||||||
@ -36,7 +35,7 @@ export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
|||||||
]
|
]
|
||||||
this.config.save()
|
this.config.save()
|
||||||
this.notifications.info('Saved')
|
this.notifications.info('Saved')
|
||||||
}),
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -51,7 +50,6 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
|
|||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
public config: ConfigService,
|
public config: ConfigService,
|
||||||
private zone: NgZone,
|
|
||||||
private terminalService: TerminalService,
|
private terminalService: TerminalService,
|
||||||
private uac: UACService,
|
private uac: UACService,
|
||||||
) {
|
) {
|
||||||
@ -64,21 +62,21 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
|
|||||||
const items: MenuItemOptions[] = [
|
const items: MenuItemOptions[] = [
|
||||||
{
|
{
|
||||||
label: 'New terminal',
|
label: 'New terminal',
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
this.terminalService.openTabWithOptions((tab as any).sessionOptions)
|
this.terminalService.openTabWithOptions((tab as any).sessionOptions)
|
||||||
}),
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'New with profile',
|
label: 'New with profile',
|
||||||
submenu: profiles.map(profile => ({
|
submenu: profiles.map(profile => ({
|
||||||
label: profile.name,
|
label: profile.name,
|
||||||
click: () => this.zone.run(async () => {
|
click: async () => {
|
||||||
let workingDirectory = this.config.store.terminal.workingDirectory
|
let workingDirectory = this.config.store.terminal.workingDirectory
|
||||||
if (this.config.store.terminal.alwaysUseWorkingDirectory !== true && tab instanceof TerminalTabComponent) {
|
if (this.config.store.terminal.alwaysUseWorkingDirectory !== true && tab instanceof TerminalTabComponent) {
|
||||||
workingDirectory = await tab.session?.getWorkingDirectory()
|
workingDirectory = await tab.session?.getWorkingDirectory()
|
||||||
}
|
}
|
||||||
await this.terminalService.openTab(profile, workingDirectory)
|
await this.terminalService.openTab(profile, workingDirectory)
|
||||||
}),
|
},
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -88,12 +86,12 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
|
|||||||
label: 'New admin tab',
|
label: 'New admin tab',
|
||||||
submenu: profiles.map(profile => ({
|
submenu: profiles.map(profile => ({
|
||||||
label: profile.name,
|
label: profile.name,
|
||||||
click: () => this.zone.run(async () => {
|
click: () => {
|
||||||
this.terminalService.openTabWithOptions({
|
this.terminalService.openTabWithOptions({
|
||||||
...profile.sessionOptions,
|
...profile.sessionOptions,
|
||||||
runAsAdministrator: true,
|
runAsAdministrator: true,
|
||||||
})
|
})
|
||||||
}),
|
},
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -101,28 +99,28 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
|
|||||||
if (tab instanceof TerminalTabComponent && tabHeader && this.uac.isAvailable) {
|
if (tab instanceof TerminalTabComponent && tabHeader && this.uac.isAvailable) {
|
||||||
items.push({
|
items.push({
|
||||||
label: 'Duplicate as administrator',
|
label: 'Duplicate as administrator',
|
||||||
click: () => this.zone.run(async () => {
|
click: () => {
|
||||||
this.terminalService.openTabWithOptions({
|
this.terminalService.openTabWithOptions({
|
||||||
...tab.sessionOptions,
|
...tab.sessionOptions,
|
||||||
runAsAdministrator: true,
|
runAsAdministrator: true,
|
||||||
})
|
})
|
||||||
}),
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab instanceof TerminalTabComponent && tab.parent instanceof SplitTabComponent && tab.parent.getAllTabs().length > 1) {
|
if (tab instanceof TerminalTabComponent && tab.parent instanceof SplitTabComponent && tab.parent.getAllTabs().length > 1) {
|
||||||
items.push({
|
items.push({
|
||||||
label: 'Focus all panes',
|
label: 'Focus all panes',
|
||||||
click: () => this.zone.run(() => {
|
click: () => {
|
||||||
tab.focusAllPanes()
|
tab.focusAllPanes()
|
||||||
}),
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab instanceof TerminalTabComponent && tab.session?.supportsWorkingDirectory()) {
|
if (tab instanceof TerminalTabComponent && tab.session?.supportsWorkingDirectory()) {
|
||||||
items.push({
|
items.push({
|
||||||
label: 'Copy current path',
|
label: 'Copy current path',
|
||||||
click: () => this.zone.run(() => tab.copyCurrentPath()),
|
click: () => tab.copyCurrentPath(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,16 +20,18 @@ export class WinSCPContextMenu extends TabContextMenuItemProvider {
|
|||||||
if (!(tab instanceof SSHTabComponent) || !tab.connection) {
|
if (!(tab instanceof SSHTabComponent) || !tab.connection) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
if (this.hostApp.platform !== Platform.Windows || !this.ssh.getWinSCPPath()) {
|
const items = [{
|
||||||
return []
|
label: 'Open SFTP panel',
|
||||||
}
|
click: () => tab.openSFTP(),
|
||||||
return [
|
}]
|
||||||
{
|
if (this.hostApp.platform === Platform.Windows && this.ssh.getWinSCPPath()) {
|
||||||
|
items.push({
|
||||||
label: 'Launch WinSCP',
|
label: 'Launch WinSCP',
|
||||||
click: (): void => {
|
click: (): void => {
|
||||||
this.ssh.launchWinSCP(tab.session!)
|
this.ssh.launchWinSCP(tab.session!)
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
]
|
}
|
||||||
|
return items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Injectable, NgZone, Optional, Inject } from '@angular/core'
|
import { Injectable, Optional, Inject } from '@angular/core'
|
||||||
import { BaseTabComponent, TabContextMenuItemProvider, TabHeaderComponent, NotificationsService, MenuItemOptions } from 'terminus-core'
|
import { BaseTabComponent, TabContextMenuItemProvider, TabHeaderComponent, NotificationsService, MenuItemOptions } from 'terminus-core'
|
||||||
import { BaseTerminalTabComponent } from './api/baseTerminalTab.component'
|
import { BaseTerminalTabComponent } from './api/baseTerminalTab.component'
|
||||||
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
|
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
|
||||||
@ -9,7 +9,6 @@ export class CopyPasteContextMenu extends TabContextMenuItemProvider {
|
|||||||
weight = -10
|
weight = -10
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private zone: NgZone,
|
|
||||||
private notifications: NotificationsService,
|
private notifications: NotificationsService,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
@ -24,19 +23,15 @@ export class CopyPasteContextMenu extends TabContextMenuItemProvider {
|
|||||||
{
|
{
|
||||||
label: 'Copy',
|
label: 'Copy',
|
||||||
click: (): void => {
|
click: (): void => {
|
||||||
this.zone.run(() => {
|
setTimeout(() => {
|
||||||
setTimeout(() => {
|
tab.frontend?.copySelection()
|
||||||
tab.frontend?.copySelection()
|
this.notifications.notice('Copied')
|
||||||
this.notifications.notice('Copied')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Paste',
|
label: 'Paste',
|
||||||
click: (): void => {
|
click: () => tab.paste(),
|
||||||
this.zone.run(() => tab.paste())
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user