mirror of
https://github.com/Eugeny/tabby.git
synced 2025-09-17 22:04:35 +00:00
strongly typed partial profiles wip
This commit is contained in:
@@ -16,7 +16,7 @@ export { BootstrapData, PluginInfo, BOOTSTRAP_DATA } from './mainProcess'
|
||||
export { HostWindowService } from './hostWindow'
|
||||
export { HostAppService, Platform } from './hostApp'
|
||||
export { FileProvider } from './fileProvider'
|
||||
export { ProfileProvider, Profile, ProfileSettingsComponent } from './profileProvider'
|
||||
export { ProfileProvider, Profile, PartialProfile, ProfileSettingsComponent } from './profileProvider'
|
||||
export { PromptModalComponent } from '../components/promptModal.component'
|
||||
|
||||
export { AppService } from '../services/app.service'
|
||||
|
@@ -1,45 +1,56 @@
|
||||
/* eslint-disable @typescript-eslint/no-type-alias */
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
import { BaseTabComponent } from '../components/baseTab.component'
|
||||
import { NewTabParameters } from '../services/tabs.service'
|
||||
|
||||
export interface Profile {
|
||||
id?: string
|
||||
id: string
|
||||
type: string
|
||||
name: string
|
||||
group?: string
|
||||
options: Record<string, any>
|
||||
options: any
|
||||
|
||||
icon?: string
|
||||
color?: string
|
||||
disableDynamicTitle?: boolean
|
||||
disableDynamicTitle: boolean
|
||||
|
||||
weight?: number
|
||||
isBuiltin?: boolean
|
||||
isTemplate?: boolean
|
||||
weight: number
|
||||
isBuiltin: boolean
|
||||
isTemplate: boolean
|
||||
}
|
||||
|
||||
export interface ProfileSettingsComponent {
|
||||
profile: Profile
|
||||
export type PartialProfile<T extends Profile> = Omit<Omit<Omit<{
|
||||
[K in keyof T]?: T[K]
|
||||
}, 'options'>, 'type'>, 'name'> & {
|
||||
type: string
|
||||
name: string
|
||||
options?: {
|
||||
[K in keyof T['options']]?: T['options'][K]
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProfileSettingsComponent<P extends Profile> {
|
||||
profile: P
|
||||
save?: () => void
|
||||
}
|
||||
|
||||
export abstract class ProfileProvider {
|
||||
export abstract class ProfileProvider<P extends Profile> {
|
||||
id: string
|
||||
name: string
|
||||
supportsQuickConnect = false
|
||||
settingsComponent?: new (...args: any[]) => ProfileSettingsComponent
|
||||
settingsComponent?: new (...args: any[]) => ProfileSettingsComponent<P>
|
||||
configDefaults = {}
|
||||
|
||||
abstract getBuiltinProfiles (): Promise<Profile[]>
|
||||
abstract getBuiltinProfiles (): Promise<PartialProfile<P>[]>
|
||||
|
||||
abstract getNewTabParameters (profile: Profile): Promise<NewTabParameters<BaseTabComponent>>
|
||||
abstract getNewTabParameters (profile: PartialProfile<P>): Promise<NewTabParameters<BaseTabComponent>>
|
||||
|
||||
abstract getDescription (profile: Profile): string
|
||||
abstract getDescription (profile: PartialProfile<P>): string
|
||||
|
||||
quickConnect (query: string): Profile|null {
|
||||
quickConnect (query: string): PartialProfile<P>|null {
|
||||
return null
|
||||
}
|
||||
|
||||
deleteProfile (profile: Profile): void { }
|
||||
deleteProfile (profile: P): void { }
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'
|
||||
|
||||
import { ToolbarButton, ToolbarButtonProvider } from './api/toolbarButtonProvider'
|
||||
import { HostAppService, Platform } from './api/hostApp'
|
||||
import { Profile } from './api/profileProvider'
|
||||
import { PartialProfile, Profile } from './api/profileProvider'
|
||||
import { ConfigService } from './services/config.service'
|
||||
import { HotkeysService } from './services/hotkeys.service'
|
||||
import { ProfilesService } from './services/profiles.service'
|
||||
@@ -32,7 +32,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
||||
}
|
||||
}
|
||||
|
||||
async launchProfile (profile: Profile) {
|
||||
async launchProfile (profile: PartialProfile<Profile>) {
|
||||
await this.profilesService.openNewTabForProfile(profile)
|
||||
|
||||
let recentProfiles = this.config.store.recentProfiles
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import slugify from 'slugify'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ConfigService, NewTabParameters, Profile, ProfileProvider } from './api'
|
||||
import { ConfigService, NewTabParameters, PartialProfile, Profile, ProfileProvider } from './api'
|
||||
import { SplitTabComponent, SplitTabRecoveryProvider } from './components/splitTab.component'
|
||||
|
||||
export interface SplitLayoutProfileOptions {
|
||||
@@ -13,7 +13,7 @@ export interface SplitLayoutProfile extends Profile {
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class SplitLayoutProfilesService extends ProfileProvider {
|
||||
export class SplitLayoutProfilesService extends ProfileProvider<SplitLayoutProfile> {
|
||||
id = 'split-layout'
|
||||
name = 'Saved layout'
|
||||
configDefaults = {
|
||||
@@ -29,7 +29,7 @@ export class SplitLayoutProfilesService extends ProfileProvider {
|
||||
super()
|
||||
}
|
||||
|
||||
async getBuiltinProfiles (): Promise<Profile[]> {
|
||||
async getBuiltinProfiles (): Promise<PartialProfile<SplitLayoutProfile>[]> {
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export class SplitLayoutProfilesService extends ProfileProvider {
|
||||
|
||||
async createProfile (tab: SplitTabComponent, name: string): Promise<void> {
|
||||
const token = await tab.getRecoveryToken()
|
||||
const profile: SplitLayoutProfile = {
|
||||
const profile: PartialProfile<SplitLayoutProfile> = {
|
||||
id: `${this.id}:custom:${slugify(name)}:${uuidv4()}`,
|
||||
type: this.id,
|
||||
name,
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { Injectable, Inject } from '@angular/core'
|
||||
import { NewTabParameters } from './tabs.service'
|
||||
import { BaseTabComponent } from '../components/baseTab.component'
|
||||
import { Profile, ProfileProvider } from '../api/profileProvider'
|
||||
import { SelectorOption } from '../api/selector'
|
||||
import { PartialProfile, Profile, ProfileProvider } from '../api/profileProvider'
|
||||
;import { SelectorOption } from '../api/selector'
|
||||
import { AppService } from './app.service'
|
||||
import { configMerge, ConfigProxy, ConfigService } from './config.service'
|
||||
import { NotificationsService } from './notifications.service'
|
||||
@@ -29,15 +29,18 @@ export class ProfilesService {
|
||||
private config: ConfigService,
|
||||
private notifications: NotificationsService,
|
||||
private selector: SelectorService,
|
||||
@Inject(ProfileProvider) private profileProviders: ProfileProvider[],
|
||||
@Inject(ProfileProvider) private profileProviders: ProfileProvider<Profile>[],
|
||||
) { }
|
||||
|
||||
async openNewTabForProfile (profile: Profile): Promise<BaseTabComponent|null> {
|
||||
async openNewTabForProfile <P extends Profile> (profile: PartialProfile<P>): Promise<BaseTabComponent|null> {
|
||||
const params = await this.newTabParametersForProfile(profile)
|
||||
if (params) {
|
||||
const tab = this.app.openNewTab(params)
|
||||
;(this.app.getParentTab(tab) ?? tab).color = profile.color ?? null
|
||||
tab.setTitle(profile.name)
|
||||
|
||||
if (profile.name) {
|
||||
tab.setTitle(profile.name)
|
||||
}
|
||||
if (profile.disableDynamicTitle) {
|
||||
tab['enableDynamicTitle'] = false
|
||||
}
|
||||
@@ -46,16 +49,16 @@ export class ProfilesService {
|
||||
return null
|
||||
}
|
||||
|
||||
async newTabParametersForProfile (profile: Profile): Promise<NewTabParameters<BaseTabComponent>|null> {
|
||||
profile = this.getConfigProxyForProfile(profile)
|
||||
return this.providerForProfile(profile)?.getNewTabParameters(profile) ?? null
|
||||
async newTabParametersForProfile <P extends Profile> (profile: PartialProfile<P>): Promise<NewTabParameters<BaseTabComponent>|null> {
|
||||
const fullProfile = this.getConfigProxyForProfile(profile)
|
||||
return this.providerForProfile(fullProfile)?.getNewTabParameters(fullProfile) ?? null
|
||||
}
|
||||
|
||||
getProviders (): ProfileProvider[] {
|
||||
getProviders (): ProfileProvider<Profile>[] {
|
||||
return [...this.profileProviders]
|
||||
}
|
||||
|
||||
async getProfiles (): Promise<Profile[]> {
|
||||
async getProfiles (): Promise<PartialProfile<Profile>[]> {
|
||||
const lists = await Promise.all(this.config.enabledServices(this.profileProviders).map(x => x.getBuiltinProfiles()))
|
||||
let list = lists.reduce((a, b) => a.concat(b), [])
|
||||
list = [
|
||||
@@ -68,28 +71,29 @@ export class ProfilesService {
|
||||
return list
|
||||
}
|
||||
|
||||
providerForProfile (profile: Profile): ProfileProvider|null {
|
||||
return this.profileProviders.find(x => x.id === profile.type) ?? null
|
||||
providerForProfile <T extends Profile> (profile: PartialProfile<T>): ProfileProvider<T>|null {
|
||||
const provider = this.profileProviders.find(x => x.id === profile.type) ?? null
|
||||
return provider as unknown as ProfileProvider<T>|null
|
||||
}
|
||||
|
||||
getDescription (profile: Profile): string|null {
|
||||
getDescription <P extends Profile> (profile: PartialProfile<P>): string|null {
|
||||
profile = this.getConfigProxyForProfile(profile)
|
||||
return this.providerForProfile(profile)?.getDescription(profile) ?? null
|
||||
}
|
||||
|
||||
selectorOptionForProfile <T> (profile: Profile): SelectorOption<T> {
|
||||
profile = this.getConfigProxyForProfile(profile)
|
||||
selectorOptionForProfile <P extends Profile, T> (profile: PartialProfile<P>): SelectorOption<T> {
|
||||
const fullProfile = this.getConfigProxyForProfile(profile)
|
||||
return {
|
||||
icon: profile.icon,
|
||||
name: profile.group ? `${profile.group} / ${profile.name}` : profile.name,
|
||||
description: this.providerForProfile(profile)?.getDescription(profile),
|
||||
name: profile.group ? `${fullProfile.group} / ${fullProfile.name}` : fullProfile.name,
|
||||
description: this.providerForProfile(fullProfile)?.getDescription(fullProfile),
|
||||
}
|
||||
}
|
||||
|
||||
showProfileSelector (): Promise<Profile|null> {
|
||||
return new Promise<Profile|null>(async (resolve, reject) => {
|
||||
showProfileSelector (): Promise<PartialProfile<Profile>|null> {
|
||||
return new Promise<PartialProfile<Profile>|null>(async (resolve, reject) => {
|
||||
try {
|
||||
const recentProfiles: Profile[] = this.config.store.recentProfiles
|
||||
const recentProfiles: PartialProfile<Profile>[] = this.config.store.recentProfiles
|
||||
|
||||
let options: SelectorOption<void>[] = recentProfiles.map(p => ({
|
||||
...this.selectorOptionForProfile(p),
|
||||
@@ -159,7 +163,7 @@ export class ProfilesService {
|
||||
})
|
||||
}
|
||||
|
||||
async quickConnect (query: string): Promise<Profile|null> {
|
||||
async quickConnect (query: string): Promise<PartialProfile<Profile>|null> {
|
||||
for (const provider of this.getProviders()) {
|
||||
if (provider.supportsQuickConnect) {
|
||||
const profile = provider.quickConnect(query)
|
||||
@@ -172,9 +176,9 @@ export class ProfilesService {
|
||||
return null
|
||||
}
|
||||
|
||||
getConfigProxyForProfile (profile: Profile): Profile {
|
||||
getConfigProxyForProfile <T extends Profile> (profile: PartialProfile<T>): T {
|
||||
const provider = this.providerForProfile(profile)
|
||||
const defaults = configMerge(this.profileDefaults, provider?.configDefaults ?? {})
|
||||
return new ConfigProxy(profile, defaults) as unknown as Profile
|
||||
return new ConfigProxy(profile, defaults) as unknown as T
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user