mirror of
https://github.com/Eugeny/tabby.git
synced 2025-10-05 14:34:54 +00:00
project rename
This commit is contained in:
12
tabby-core/src/api/cli.ts
Normal file
12
tabby-core/src/api/cli.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface CLIEvent {
|
||||
argv: any
|
||||
cwd: string
|
||||
secondInstance: boolean
|
||||
}
|
||||
|
||||
export abstract class CLIHandler {
|
||||
priority: number
|
||||
firstMatchOnly: boolean
|
||||
|
||||
abstract handle (event: CLIEvent): Promise<boolean>
|
||||
}
|
37
tabby-core/src/api/configProvider.ts
Normal file
37
tabby-core/src/api/configProvider.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Extend to add your own config options
|
||||
*/
|
||||
export abstract class ConfigProvider {
|
||||
/**
|
||||
* Default values, e.g.
|
||||
*
|
||||
* ```ts
|
||||
* defaults = {
|
||||
* myPlugin: {
|
||||
* foo: 1
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
defaults: any = {}
|
||||
|
||||
/**
|
||||
* [[Platform]] specific defaults, e.g.
|
||||
*
|
||||
* ```ts
|
||||
* platformDefaults = {
|
||||
* [Platform.Windows]: {
|
||||
* myPlugin: {
|
||||
* bar: true
|
||||
* }
|
||||
* },
|
||||
* [Platform.macOS]: {
|
||||
* myPlugin: {
|
||||
* bar: false
|
||||
* }
|
||||
* },
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
platformDefaults: Record<string, any> = {}
|
||||
}
|
13
tabby-core/src/api/fileProvider.ts
Normal file
13
tabby-core/src/api/fileProvider.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export abstract class FileProvider {
|
||||
name: string
|
||||
|
||||
async isAvailable (): Promise<boolean> {
|
||||
return true
|
||||
}
|
||||
|
||||
abstract selectAndStoreFile (description: string): Promise<string>
|
||||
abstract retrieveFile (key: string): Promise<Buffer>
|
||||
}
|
53
tabby-core/src/api/hostApp.ts
Normal file
53
tabby-core/src/api/hostApp.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
import { Injector } from '@angular/core'
|
||||
import { Logger, LogService } from '../services/log.service'
|
||||
|
||||
export enum Platform {
|
||||
Linux = 'Linux',
|
||||
macOS = 'macOS',
|
||||
Windows = 'Windows',
|
||||
Web = 'Web',
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides interaction with the main process
|
||||
*/
|
||||
export abstract class HostAppService {
|
||||
abstract get platform (): Platform
|
||||
abstract get configPlatform (): Platform
|
||||
|
||||
protected settingsUIRequest = new Subject<void>()
|
||||
protected configChangeBroadcast = new Subject<void>()
|
||||
protected logger: Logger
|
||||
|
||||
/**
|
||||
* Fired when Preferences is selected in the macOS menu
|
||||
*/
|
||||
get settingsUIRequest$ (): Observable<void> { return this.settingsUIRequest }
|
||||
|
||||
/**
|
||||
* Fired when another window modified the config file
|
||||
*/
|
||||
get configChangeBroadcast$ (): Observable<void> { return this.configChangeBroadcast }
|
||||
|
||||
constructor (
|
||||
injector: Injector,
|
||||
) {
|
||||
this.logger = injector.get(LogService).create('hostApp')
|
||||
}
|
||||
|
||||
abstract newWindow (): void
|
||||
|
||||
/**
|
||||
* Notifies other windows of config file changes
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
broadcastConfigChange (_configStore: Record<string, any>): void { }
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
emitReady (): void { }
|
||||
|
||||
abstract relaunch (): void
|
||||
|
||||
abstract quit (): void
|
||||
}
|
36
tabby-core/src/api/hostWindow.ts
Normal file
36
tabby-core/src/api/hostWindow.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
|
||||
export abstract class HostWindowService {
|
||||
|
||||
/**
|
||||
* Fired once the window is visible
|
||||
*/
|
||||
get windowShown$ (): Observable<void> { return this.windowShown }
|
||||
|
||||
/**
|
||||
* Fired when the window close button is pressed
|
||||
*/
|
||||
get windowCloseRequest$ (): Observable<void> { return this.windowCloseRequest }
|
||||
get windowMoved$ (): Observable<void> { return this.windowMoved }
|
||||
get windowFocused$ (): Observable<void> { return this.windowFocused }
|
||||
|
||||
protected windowShown = new Subject<void>()
|
||||
protected windowCloseRequest = new Subject<void>()
|
||||
protected windowMoved = new Subject<void>()
|
||||
protected windowFocused = new Subject<void>()
|
||||
|
||||
abstract readonly isFullscreen: boolean
|
||||
abstract reload (): void
|
||||
abstract setTitle (title?: string): void
|
||||
abstract toggleFullscreen (): void
|
||||
abstract minimize (): void
|
||||
abstract isMaximized (): boolean
|
||||
abstract toggleMaximize (): void
|
||||
abstract close (): void
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
openDevTools (): void { }
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
bringToFront (): void { }
|
||||
}
|
12
tabby-core/src/api/hotkeyProvider.ts
Normal file
12
tabby-core/src/api/hotkeyProvider.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface HotkeyDescription {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend to provide your own hotkeys. A corresponding [[ConfigProvider]]
|
||||
* must also provide the `hotkeys.foo` config options with the default values
|
||||
*/
|
||||
export abstract class HotkeyProvider {
|
||||
abstract provide (): Promise<HotkeyDescription[]>
|
||||
}
|
33
tabby-core/src/api/index.ts
Normal file
33
tabby-core/src/api/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
export { BaseComponent, SubscriptionContainer } from '../components/base.component'
|
||||
export { BaseTabComponent, BaseTabProcess } from '../components/baseTab.component'
|
||||
export { TabHeaderComponent } from '../components/tabHeader.component'
|
||||
export { SplitTabComponent, SplitContainer } from '../components/splitTab.component'
|
||||
export { TabRecoveryProvider, RecoveredTab, RecoveryToken } from './tabRecovery'
|
||||
export { ToolbarButtonProvider, ToolbarButton } from './toolbarButtonProvider'
|
||||
export { ConfigProvider } from './configProvider'
|
||||
export { HotkeyProvider, HotkeyDescription } from './hotkeyProvider'
|
||||
export { Theme } from './theme'
|
||||
export { TabContextMenuItemProvider } from './tabContextMenuProvider'
|
||||
export { SelectorOption } from './selector'
|
||||
export { CLIHandler, CLIEvent } from './cli'
|
||||
export { PlatformService, ClipboardContent, MessageBoxResult, MessageBoxOptions, FileDownload, FileUpload, FileTransfer, HTMLFileUpload, FileUploadOptions } from './platform'
|
||||
export { MenuItemOptions } from './menu'
|
||||
export { BootstrapData, PluginInfo, BOOTSTRAP_DATA } from './mainProcess'
|
||||
export { HostWindowService } from './hostWindow'
|
||||
export { HostAppService, Platform } from './hostApp'
|
||||
export { FileProvider } from './fileProvider'
|
||||
|
||||
export { AppService } from '../services/app.service'
|
||||
export { ConfigService } from '../services/config.service'
|
||||
export { DockingService, Screen } from '../services/docking.service'
|
||||
export { Logger, ConsoleLogger, LogService } from '../services/log.service'
|
||||
export { HomeBaseService } from '../services/homeBase.service'
|
||||
export { HotkeysService } from '../services/hotkeys.service'
|
||||
export { NotificationsService } from '../services/notifications.service'
|
||||
export { ThemesService } from '../services/themes.service'
|
||||
export { SelectorService } from '../services/selector.service'
|
||||
export { TabsService } from '../services/tabs.service'
|
||||
export { UpdaterService } from '../services/updater.service'
|
||||
export { VaultService, Vault, VaultSecret, VAULT_SECRET_TYPE_FILE } from '../services/vault.service'
|
||||
export { FileProvidersService } from '../services/fileProviders.service'
|
||||
export * from '../utils'
|
22
tabby-core/src/api/mainProcess.ts
Normal file
22
tabby-core/src/api/mainProcess.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export const BOOTSTRAP_DATA = 'BOOTSTRAP_DATA'
|
||||
|
||||
export interface PluginInfo {
|
||||
name: string
|
||||
description: string
|
||||
packageName: string
|
||||
isBuiltin: boolean
|
||||
version: string
|
||||
author: string
|
||||
homepage?: string
|
||||
path?: string
|
||||
info?: any
|
||||
}
|
||||
|
||||
export interface BootstrapData {
|
||||
config: Record<string, any>
|
||||
executable: string
|
||||
isFirstWindow: boolean
|
||||
windowID: number
|
||||
installedPlugins: PluginInfo[]
|
||||
userPluginsPath: string
|
||||
}
|
9
tabby-core/src/api/menu.ts
Normal file
9
tabby-core/src/api/menu.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export interface MenuItemOptions {
|
||||
type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio')
|
||||
label?: string
|
||||
sublabel?: string
|
||||
enabled?: boolean
|
||||
checked?: boolean
|
||||
submenu?: MenuItemOptions[]
|
||||
click?: () => void
|
||||
}
|
210
tabby-core/src/api/platform.ts
Normal file
210
tabby-core/src/api/platform.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
import { MenuItemOptions } from './menu'
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
export interface ClipboardContent {
|
||||
text: string
|
||||
html?: string
|
||||
}
|
||||
|
||||
export interface MessageBoxOptions {
|
||||
type: 'warning'|'error'
|
||||
message: string
|
||||
detail?: string
|
||||
buttons: string[]
|
||||
defaultId?: number
|
||||
}
|
||||
|
||||
export interface MessageBoxResult {
|
||||
response: number
|
||||
}
|
||||
|
||||
export abstract class FileTransfer {
|
||||
abstract getName (): string
|
||||
abstract getSize (): number
|
||||
abstract close (): void
|
||||
|
||||
getSpeed (): number {
|
||||
return this.lastChunkSpeed
|
||||
}
|
||||
|
||||
getCompletedBytes (): number {
|
||||
return this.completedBytes
|
||||
}
|
||||
|
||||
isComplete (): boolean {
|
||||
return this.completedBytes >= this.getSize()
|
||||
}
|
||||
|
||||
isCancelled (): boolean {
|
||||
return this.cancelled
|
||||
}
|
||||
|
||||
cancel (): void {
|
||||
this.cancelled = true
|
||||
this.close()
|
||||
}
|
||||
|
||||
protected increaseProgress (bytes: number): void {
|
||||
this.completedBytes += bytes
|
||||
this.lastChunkSpeed = bytes * 1000 / (Date.now() - this.lastChunkStartTime)
|
||||
this.lastChunkStartTime = Date.now()
|
||||
}
|
||||
|
||||
private completedBytes = 0
|
||||
private lastChunkStartTime = Date.now()
|
||||
private lastChunkSpeed = 0
|
||||
private cancelled = false
|
||||
}
|
||||
|
||||
export abstract class FileDownload extends FileTransfer {
|
||||
abstract write (buffer: Buffer): Promise<void>
|
||||
}
|
||||
|
||||
export abstract class FileUpload extends FileTransfer {
|
||||
abstract read (): Promise<Buffer>
|
||||
|
||||
async readAll (): Promise<Buffer> {
|
||||
const buffers: Buffer[] = []
|
||||
while (true) {
|
||||
const buf = await this.read()
|
||||
if (!buf.length) {
|
||||
break
|
||||
}
|
||||
buffers.push(Buffer.from(buf))
|
||||
}
|
||||
return Buffer.concat(buffers)
|
||||
}
|
||||
}
|
||||
|
||||
export interface FileUploadOptions {
|
||||
multiple: boolean
|
||||
}
|
||||
|
||||
export abstract class PlatformService {
|
||||
supportsWindowControls = false
|
||||
|
||||
get fileTransferStarted$ (): Observable<FileTransfer> { return this.fileTransferStarted }
|
||||
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
|
||||
|
||||
protected fileTransferStarted = new Subject<FileTransfer>()
|
||||
protected displayMetricsChanged = new Subject<void>()
|
||||
|
||||
abstract readClipboard (): string
|
||||
abstract setClipboard (content: ClipboardContent): void
|
||||
abstract loadConfig (): Promise<string>
|
||||
abstract saveConfig (content: string): Promise<void>
|
||||
|
||||
abstract startDownload (name: string, size: number): Promise<FileDownload|null>
|
||||
abstract startUpload (options?: FileUploadOptions): Promise<FileUpload[]>
|
||||
|
||||
startUploadFromDragEvent (event: DragEvent, multiple = false): FileUpload[] {
|
||||
const result: FileUpload[] = []
|
||||
if (!event.dataTransfer) {
|
||||
return []
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||
for (let i = 0; i < event.dataTransfer.files.length; i++) {
|
||||
const file = event.dataTransfer.files[i]
|
||||
const transfer = new HTMLFileUpload(file)
|
||||
this.fileTransferStarted.next(transfer)
|
||||
result.push(transfer)
|
||||
if (!multiple) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
getConfigPath (): string|null {
|
||||
return null
|
||||
}
|
||||
|
||||
showItemInFolder (path: string): void {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
async isProcessRunning (name: string): Promise<boolean> {
|
||||
return false
|
||||
}
|
||||
|
||||
async installPlugin (name: string, version: string): Promise<void> {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
async uninstallPlugin (name: string): Promise<void> {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
getWinSCPPath (): string|null {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
exec (app: string, argv: string[]): void {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
isShellIntegrationSupported (): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
async isShellIntegrationInstalled (): Promise<boolean> {
|
||||
return false
|
||||
}
|
||||
|
||||
async installShellIntegration (): Promise<void> {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
async uninstallShellIntegration (): Promise<void> {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
openPath (path: string): void {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
abstract getOSRelease (): string
|
||||
abstract getAppVersion (): string
|
||||
abstract openExternal (url: string): void
|
||||
abstract listFonts (): Promise<string[]>
|
||||
abstract setErrorHandler (handler: (_: any) => void): void
|
||||
abstract popupContextMenu (menu: MenuItemOptions[], event?: MouseEvent): void
|
||||
abstract showMessageBox (options: MessageBoxOptions): Promise<MessageBoxResult>
|
||||
abstract quit (): void
|
||||
}
|
||||
|
||||
export class HTMLFileUpload extends FileUpload {
|
||||
private stream: ReadableStream
|
||||
private reader: ReadableStreamDefaultReader
|
||||
|
||||
constructor (private file: File) {
|
||||
super()
|
||||
this.stream = this.file.stream()
|
||||
this.reader = this.stream.getReader()
|
||||
}
|
||||
|
||||
getName (): string {
|
||||
return this.file.name
|
||||
}
|
||||
|
||||
getSize (): number {
|
||||
return this.file.size
|
||||
}
|
||||
|
||||
async read (): Promise<Buffer> {
|
||||
const result: any = await this.reader.read()
|
||||
if (result.done || !result.value) {
|
||||
return Buffer.from('')
|
||||
}
|
||||
const chunk = Buffer.from(result.value)
|
||||
this.increaseProgress(chunk.length)
|
||||
return chunk
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
bringToFront (): void { }
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
close (): void { }
|
||||
}
|
8
tabby-core/src/api/selector.ts
Normal file
8
tabby-core/src/api/selector.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface SelectorOption<T> {
|
||||
name: string
|
||||
description?: string
|
||||
result?: T
|
||||
icon?: string
|
||||
freeInputPattern?: string
|
||||
callback?: (string?) => void
|
||||
}
|
12
tabby-core/src/api/tabContextMenuProvider.ts
Normal file
12
tabby-core/src/api/tabContextMenuProvider.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { BaseTabComponent } from '../components/baseTab.component'
|
||||
import { TabHeaderComponent } from '../components/tabHeader.component'
|
||||
import { MenuItemOptions } from './menu'
|
||||
|
||||
/**
|
||||
* Extend to add items to the tab header's context menu
|
||||
*/
|
||||
export abstract class TabContextMenuItemProvider {
|
||||
weight = 0
|
||||
|
||||
abstract getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemOptions[]>
|
||||
}
|
61
tabby-core/src/api/tabRecovery.ts
Normal file
61
tabby-core/src/api/tabRecovery.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import deepClone from 'clone-deep'
|
||||
import { TabComponentType } from '../services/tabs.service'
|
||||
|
||||
export interface RecoveredTab {
|
||||
/**
|
||||
* Component type to be instantiated
|
||||
*/
|
||||
type: TabComponentType
|
||||
|
||||
/**
|
||||
* Component instance inputs
|
||||
*/
|
||||
options?: any
|
||||
}
|
||||
|
||||
export interface RecoveryToken {
|
||||
[_: string]: any
|
||||
type: string
|
||||
tabColor?: string|null
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend to enable recovery for your custom tab.
|
||||
* This works in conjunction with [[getRecoveryToken()]]
|
||||
*
|
||||
* Tabby will try to find any [[TabRecoveryProvider]] that is able to process
|
||||
* the recovery token previously returned by [[getRecoveryToken]].
|
||||
*
|
||||
* Recommended token format:
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* type: 'my-tab-type',
|
||||
* foo: 'bar',
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export abstract class TabRecoveryProvider {
|
||||
/**
|
||||
* @param recoveryToken a recovery token found in the saved tabs list
|
||||
* @returns [[boolean]] whether this [[TabRecoveryProvider]] can recover a tab from this token
|
||||
*/
|
||||
|
||||
abstract applicableTo (recoveryToken: RecoveryToken): Promise<boolean>
|
||||
/**
|
||||
* @param recoveryToken a recovery token found in the saved tabs list
|
||||
* @returns [[RecoveredTab]] descriptor containing tab type and component inputs
|
||||
* or `null` if this token is from a different tab type or is not supported
|
||||
*/
|
||||
abstract recover (recoveryToken: RecoveryToken): Promise<RecoveredTab>
|
||||
|
||||
/**
|
||||
* @param recoveryToken a recovery token found in the saved tabs list
|
||||
* @returns [[RecoveryToken]] a new recovery token to create the duplicate tab from
|
||||
*
|
||||
* The default implementation just returns a deep copy of the original token
|
||||
*/
|
||||
duplicate (recoveryToken: RecoveryToken): RecoveryToken {
|
||||
return deepClone(recoveryToken)
|
||||
}
|
||||
}
|
16
tabby-core/src/api/theme.ts
Normal file
16
tabby-core/src/api/theme.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Extend to add a custom CSS theme
|
||||
*/
|
||||
export abstract class Theme {
|
||||
name: string
|
||||
|
||||
/**
|
||||
* Complete CSS stylesheet
|
||||
*/
|
||||
css: string
|
||||
|
||||
terminalBackground: string
|
||||
|
||||
macOSWindowButtonsInsetX?: number
|
||||
macOSWindowButtonsInsetY?: number
|
||||
}
|
37
tabby-core/src/api/toolbarButtonProvider.ts
Normal file
37
tabby-core/src/api/toolbarButtonProvider.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* See [[ToolbarButtonProvider]]
|
||||
*/
|
||||
export interface ToolbarButton {
|
||||
/**
|
||||
* Raw SVG icon code
|
||||
*/
|
||||
icon?: string
|
||||
|
||||
title: string
|
||||
|
||||
/**
|
||||
* Optional Touch Bar icon ID
|
||||
*/
|
||||
touchBarNSImage?: string
|
||||
|
||||
/**
|
||||
* Optional Touch Bar button label
|
||||
*/
|
||||
touchBarTitle?: string
|
||||
|
||||
weight?: number
|
||||
|
||||
click?: () => void
|
||||
|
||||
submenu?: () => Promise<ToolbarButton[]>
|
||||
|
||||
/** @hidden */
|
||||
submenuItems?: ToolbarButton[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend to add buttons to the toolbar
|
||||
*/
|
||||
export abstract class ToolbarButtonProvider {
|
||||
abstract provide (): ToolbarButton[]
|
||||
}
|
Reference in New Issue
Block a user