bootstrap 5 WIP (#7891)

New standard theme that follows your chosen terminal colors, Bootstrap 5 & Angular 15 upgrade
This commit is contained in:
Eugene
2023-02-26 20:42:31 +01:00
committed by GitHub
parent 7a8108b20d
commit 1e5cfd1d4b
215 changed files with 2982 additions and 2447 deletions

View File

@@ -17,9 +17,9 @@
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
"@types/marked": "^4.0.2",
"marked": "^4.0.8",
"ngx-infinite-scroll": "^10.0.1"
"@types/marked": "^4.0.8",
"marked": "^4.2.12",
"ngx-infinite-scroll": "^15"
},
"peerDependencies": {
"@angular/animations": "^9.1.9",

View File

@@ -14,9 +14,11 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
[(ngModel)]='config.store.configSync.host',
(keydown.enter)='config.save()',
)
.input-group-append(*ngIf='config.store.configSync.host')
button.btn.btn-secondary((click)='openSyncHost()')
i.fas.fa-external-link-alt
button.btn.btn-secondary(
*ngIf='config.store.configSync.host',
(click)='openSyncHost()'
)
i.fas.fa-external-link-alt
.form-line
.header
@@ -29,16 +31,15 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
[(ngModel)]='config.store.configSync.token',
(keydown.enter)='config.save(); testConnection()'
)
.input-group-append(*ngIf='config.store.configSync.token')
.input-group-text
i.fas.fa-fw.fa-circle-notch.fa-spin.text-warning(*ngIf='connectionSuccessful === null')
i.fas.fa-fw.fa-check.text-success(*ngIf='connectionSuccessful')
i.fas.fa-fw.fa-exclamation-triangle.text-danger(*ngIf='connectionSuccessful === false')
.input-group-text(*ngIf='config.store.configSync.token')
i.fas.fa-fw.fa-circle-notch.fa-spin.text-warning(*ngIf='connectionSuccessful === null')
i.fas.fa-fw.fa-check.text-success(*ngIf='connectionSuccessful')
i.fas.fa-fw.fa-exclamation-triangle.text-danger(*ngIf='connectionSuccessful === false')
ng-container(*ngIf='config.store.configSync.token')
.alert.alert-danger(*ngIf='connectionSuccessful === false')
i.fas.fa-exclamation-triangle
span.ml-2(translate='Connection failed: {error}', [translateParams]='{error: connectionError}')
span.ms-2(translate='Connection failed: {error}', [translateParams]='{error: connectionError}')
ng-container(*ngIf='connectionSuccessful')
.form-line
@@ -47,49 +48,49 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
div(*ngIf='configs === null')
i.fas.fa-fw.fa-circle-notch.fa-spin
span.ml-2(translate) Loading configs...
span.ms-2(translate) Loading configs...
ng-container(*ngIf='configs !== null')
.list-group-light
.list-group.list-group-light
.list-group-item.d-flex.align-items-center(
*ngFor='let cfg of configs',
[class.active]='isActiveConfig(cfg)',
)
i.fas.fa-fw.text-success([class.fa-check]='isActiveConfig(cfg)')
i.fas.fa-fw.fa-file
.ml-2.d-flex.flex-column.align-items-start
.ms-2.d-flex.flex-column.align-items-start
div {{cfg.name}}
small.text-muted(
translate='Modified on {date}',
[translateParams]='{date: cfg.modified_at|date:"medium"}'
)
.mr-auto
button.btn.btn-link.ml-1(
.me-auto
button.btn.btn-link.ms-1(
(click)='uploadAndSync(cfg)',
[class.hover-reveal]='!isActiveConfig(cfg)'
)
i.fas.fa-arrow-up
span.ml-2(*ngIf='isActiveConfig(cfg)', translate) Upload
span.ml-2(*ngIf='!isActiveConfig(cfg)', translate) Replace
button.btn.btn-link.ml-1(
span.ms-2(*ngIf='isActiveConfig(cfg)', translate) Upload
span.ms-2(*ngIf='!isActiveConfig(cfg)', translate) Replace
button.btn.btn-link.ms-1(
(click)='downloadAndSync(cfg)',
[class.hover-reveal]='!isActiveConfig(cfg)'
)
i.fas.fa-arrow-down
span.ml-2(translate) Download
button.btn.btn-link.ml-1(
span.ms-2(translate) Download
button.btn.btn-link.ms-1(
(click)='delete(cfg)',
[class.hover-reveal]='!isActiveConfig(cfg)'
)
i.fas.fa-trash
span.ml-2(translate) Delete
span.ms-2(translate) Delete
a.list-group-item.list-group-item-action.d-flex.align-items-center(
href='#',
(click)='uploadAsNew()'
)
i.fas.fa-fw
i.fas.fa-fw.fa-cloud-upload-alt
.ml-2(translate) Upload as a new config
.ms-2(translate) Upload as a new config
ng-container(*ngIf='hasMatchingRemoteConfig()')
.form-line

View File

@@ -8,7 +8,7 @@ import { Config, ConfigSyncService } from '../services/configSync.service'
/** @hidden */
@Component({
selector: 'config-sync-settings-tab',
template: require('./configSyncSettingsTab.component.pug'),
templateUrl:'./configSyncSettingsTab.component.pug',
})
export class ConfigSyncSettingsTabComponent extends BaseComponent {
connectionSuccessful: boolean|null = null

View File

@@ -10,7 +10,7 @@
.modal-body
.row
.col-12.col-lg-4
.form-group(*ngIf='!defaultsMode')
.mb-3(*ngIf='!defaultsMode')
label(translate) Name
input.form-control(
type='text',
@@ -18,7 +18,7 @@
[(ngModel)]='profile.name',
)
.form-group(*ngIf='!defaultsMode')
.mb-3(*ngIf='!defaultsMode')
label(translate) Group
input.form-control(
type='text',
@@ -28,7 +28,7 @@
[ngbTypeahead]='groupTypeahead',
)
.form-group(*ngIf='!defaultsMode')
.mb-3(*ngIf='!defaultsMode')
label(translate) Icon
.input-group
input.form-control(
@@ -38,16 +38,15 @@
[ngbTypeahead]='iconSearch',
[resultTemplate]='rt'
)
.input-group-append
.input-group-text
profile-icon(
[icon]='profile.icon',
[color]='profile.color'
)
.input-group-text
profile-icon(
[icon]='profile.icon',
[color]='profile.color'
)
ng-template(#rt,let-r='result',let-t='term')
i([class]='"fa-fw " + r')
ngb-highlight.ml-2([result]='r', [term]='t')
ngb-highlight.ms-2([result]='r', [term]='t')
.form-line
.header

View File

@@ -13,7 +13,7 @@ const iconsClassList = Object.keys(iconsData).map(
/** @hidden */
@Component({
template: require('./editProfileModal.component.pug'),
templateUrl:'./editProfileModal.component.pug',
})
export class EditProfileModalComponent<P extends Profile> {
@Input() profile: P & ConfigProxy

View File

@@ -8,8 +8,8 @@ const INPUT_TIMEOUT = 1000
/** @hidden */
@Component({
selector: 'hotkey-input-modal',
template: require('./hotkeyInputModal.component.pug'),
styles: [require('./hotkeyInputModal.component.scss')],
templateUrl:'./hotkeyInputModal.component.pug',
styleUrls: ['./hotkeyInputModal.component.scss'],
animations: [
trigger('animateKey', [
transition(':enter', [

View File

@@ -1,18 +1,17 @@
h3.mb-3(translate) Hotkeys
.input-group.mb-4
.input-group-prepend
.input-group-text
i.fas.fa-fw.fa-search
.input-group-text
i.fas.fa-fw.fa-search
input.form-control(type='search', [placeholder]='"Search hotkeys"|translate', [(ngModel)]='hotkeyFilter')
.form-group.hotkeys-table
.mb-3.hotkeys-table
ng-container(*ngFor='let hotkey of hotkeyDescriptions')
.row.align-items-center(*ngIf='!hotkeyFilter || hotkeyFilterFn(hotkey, hotkeyFilter)')
.col-8.py-2
span {{hotkey.name|translate}}
span.ml-2.text-muted ({{hotkey.id}})
.col-4.pr-5
span.ms-2.text-muted ({{hotkey.id}})
.col-4.pe-5
multi-hotkey-input(
[hotkeys]='getHotkeys(hotkey.id) || []',
(hotkeysChange)='setHotkeys(hotkey.id, $event)'

View File

@@ -14,7 +14,7 @@ _('Search hotkeys')
/** @hidden */
@Component({
selector: 'hotkey-settings-tab',
template: require('./hotkeySettingsTab.component.pug'),
templateUrl:'./hotkeySettingsTab.component.pug',
})
export class HotkeySettingsTabComponent {
hotkeyFilter = ''

View File

@@ -1,6 +1,6 @@
.item(*ngFor='let hotkey of hotkeys')
.body((click)='editItem(hotkey)')
.stroke(*ngFor='let stroke of hotkey.strokes')
.stroke(*ngFor='let stroke of castAny(hotkey.strokes)')
span(*ngIf='!hotkey.isDuplicate') {{stroke}}
span.duplicate(*ngIf='hotkey.isDuplicate') {{stroke}}
.remove((click)='removeItem(hotkey)') &times;

View File

@@ -7,8 +7,8 @@ import deepEqual from 'deep-equal'
/** @hidden */
@Component({
selector: 'multi-hotkey-input',
template: require('./multiHotkeyInput.component.pug'),
styles: [require('./multiHotkeyInput.component.scss')],
templateUrl:'./multiHotkeyInput.component.pug',
styleUrls: ['./multiHotkeyInput.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MultiHotkeyInputComponent {
@@ -45,4 +45,7 @@ export class MultiHotkeyInputComponent {
private storeUpdatedHotkeys () {
this.hotkeysChange.emit(this.hotkeys)
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
protected castAny = (x: any): any => x
}

View File

@@ -23,12 +23,11 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
.d-flex.mb-3
.input-group
.input-group-prepend
.input-group-text
i.fas.fa-fw.fa-search
.input-group-text
i.fas.fa-fw.fa-search
input.form-control(type='search', [placeholder]='"Filter"|translate', [(ngModel)]='filter')
button.btn.btn-primary.flex-shrink-0.ml-3((click)='newProfile()')
button.btn.btn-primary.flex-shrink-0.ms-3((click)='newProfile()')
i.fas.fa-fw.fa-plus
span(translate) New profile
@@ -40,20 +39,20 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
)
.fa.fa-fw.fa-chevron-right(*ngIf='group.collapsed')
.fa.fa-fw.fa-chevron-down(*ngIf='!group.collapsed')
span.ml-3.mr-auto {{group.name || ("Ungrouped"|translate)}}
button.btn.btn-sm.btn-link.hover-reveal.ml-2(
span.ms-3.me-auto {{group.name || ("Ungrouped"|translate)}}
button.btn.btn-sm.btn-link.hover-reveal.ms-2(
*ngIf='group.editable && group.name',
(click)='$event.stopPropagation(); editGroup(group)'
)
i.fas.fa-pencil-alt
button.btn.btn-sm.btn-link.hover-reveal.ml-2(
button.btn.btn-sm.btn-link.hover-reveal.ms-2(
*ngIf='group.editable && group.name',
(click)='$event.stopPropagation(); deleteGroup(group)'
)
i.fas.fa-trash-alt
ng-container(*ngIf='!group.collapsed')
ng-container(*ngFor='let profile of group.profiles')
.list-group-item.pl-5.d-flex.align-items-center(
.list-group-item.ps-5.d-flex.align-items-center(
*ngIf='isProfileVisible(profile)',
[class.list-group-item-action]='!profile.isBuiltin',
(click)='profile.isBuiltin ? null : editProfile(profile)'
@@ -64,23 +63,23 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
)
.no-wrap {{profile.name}}
.text-muted.no-wrap.ml-2 {{getDescription(profile)}}
.text-muted.no-wrap.ms-2 {{getDescription(profile)}}
.mr-auto
.me-auto
button.btn.btn-link.hover-reveal.ml-1((click)='$event.stopPropagation(); launchProfile(profile)')
button.btn.btn-link.hover-reveal.ms-1((click)='$event.stopPropagation(); launchProfile(profile)')
i.fas.fa-play
button.btn.btn-link.hover-reveal.ml-1((click)='$event.stopPropagation(); newProfile(profile)')
button.btn.btn-link.hover-reveal.ms-1((click)='$event.stopPropagation(); newProfile(profile)')
i.fas.fa-copy
button.btn.btn-link.hover-reveal.ml-1(
button.btn.btn-link.hover-reveal.ms-1(
*ngIf='!profile.isBuiltin',
(click)='$event.stopPropagation(); deleteProfile(profile)'
)
i.fas.fa-trash-alt
.ml-1(class='badge badge-{{getTypeColorClass(profile)}}') {{getTypeLabel(profile)}}
.ms-1(class='badge text-bg-{{getTypeColorClass(profile)}}') {{getTypeLabel(profile)}}
li(ngbNavItem)
a(ngbNavLink, translate) Advanced

View File

@@ -19,8 +19,8 @@ _('Ungrouped')
/** @hidden */
@Component({
template: require('./profilesSettingsTab.component.pug'),
styles: [require('./profilesSettingsTab.component.scss')],
templateUrl:'./profilesSettingsTab.component.pug',
styleUrls: ['./profilesSettingsTab.component.scss'],
})
export class ProfilesSettingsTabComponent extends BaseComponent {
profiles: PartialProfile<Profile>[] = []

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
import axios from 'axios'
import { marked } from 'marked'
import * as marked from '../../node_modules/marked/src/marked'
import { Component, Injector } from '@angular/core'
import { BaseTabComponent, TranslateService } from 'tabby-core'
@@ -15,8 +15,8 @@ export interface Release {
/** @hidden */
@Component({
selector: 'release-notes-tab',
template: require('./releaseNotesTab.component.pug'),
styles: [require('./releaseNotesTab.component.scss')],
templateUrl:'./releaseNotesTab.component.pug',
styleUrls: ['./releaseNotesTab.component.scss'],
})
export class ReleaseNotesComponent extends BaseTabComponent {
releases: Release[] = []
@@ -36,7 +36,7 @@ export class ReleaseNotesComponent extends BaseTabComponent {
this.releases = this.releases.concat(response.data.map(r => ({
name: r.name,
version: r.tag_name,
content: marked(r.body),
content: marked.marked(r.body),
date: new Date(r.created_at),
})))
this.lastPage = page

View File

@@ -11,9 +11,8 @@ h3.modal-header.m-0.pb-0(translate) Set master passphrase
(keyup.enter)='ok()',
(keyup.esc)='cancel()',
)
.input-group-append
button.btn.btn-secondary((click)='showPassphrase = !showPassphrase')
i.fas.fa-eye
button.btn.btn-secondary((click)='showPassphrase = !showPassphrase')
i.fas.fa-eye
.modal-footer
button.btn.btn-primary((click)='ok()', translate) Set passphrase

View File

@@ -3,10 +3,11 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
/** @hidden */
@Component({
template: require('./setVaultPassphraseModal.component.pug'),
templateUrl:'./setVaultPassphraseModal.component.pug',
})
export class SetVaultPassphraseModalComponent {
passphrase: string
showPassphrase = false
@ViewChild('input') input: ElementRef
constructor (

View File

@@ -2,7 +2,7 @@
ul.nav-pills(ngbNav, #nav='ngbNav', [activeId]='activeTab', orientation='vertical')
li(ngbNavItem='application')
a(ngbNavLink)
i.fas.fa-fw.fa-window-maximize.mr-2
i.fas.fa-fw.fa-window-maximize.me-2
span(translate) Application
ng-template(ngbNavContent)
.content-box
@@ -71,7 +71,7 @@
.title(translate) Language
a.description((click)='homeBase.openTranslations()')
span(translate) Help translate Tabby
i.fas.fa-external-link-square-alt.ml-1
i.fas.fa-external-link-square-alt.ms-1
select.form-control([(ngModel)]='config.store.language', (ngModelChange)='saveConfiguration(true)')
option([ngValue]='null', translate) Automatic
option(
@@ -117,7 +117,7 @@
ng-container(*ngFor='let provider of settingsProviders')
li(*ngIf='provider.prioritized', [ngbNavItem]='provider.id')
a.d-flex.align-items-center(ngbNavLink)
i(class='fas fa-fw mr-2 fa-{{provider.icon}}')
i(class='fas fa-fw me-2 fa-{{provider.icon}}')
span {{provider.title|translate}}
ng-template(ngbNavContent)
settings-tab-body([provider]='provider')
@@ -127,14 +127,14 @@
ng-container(*ngFor='let provider of settingsProviders')
li(*ngIf='!provider.prioritized', [ngbNavItem]='provider.id')
a.d-flex.align-items-center(ngbNavLink)
i(class='fas fa-fw mr-2 fa-{{provider.icon || "puzzle-piece"}}')
i(class='fas fa-fw me-2 fa-{{provider.icon || "puzzle-piece"}}')
span {{provider.title|translate}}
ng-template(ngbNavContent)
settings-tab-body([provider]='provider')
li(ngbNavItem='config-file')
a.d-flex.align-items-center(ngbNavLink)
i.fas.fa-fw.fa-code.mr-2
i.fas.fa-fw.fa-code.me-2
span(translate) Config file
ng-template.test(ngbNavContent)
.d-flex.flex-column.w-100.h-100
@@ -152,20 +152,20 @@
)
.mt-3.d-flex
button.btn.btn-primary((click)='saveConfigFile()', *ngIf='isConfigFileValid()')
i.fas.fa-check.mr-2
i.fas.fa-check.me-2
span(translate) Save and apply
button.btn.btn-primary(disabled, *ngIf='!isConfigFileValid()')
i.fas.fa-exclamation-triangle.mr-2
i.fas.fa-exclamation-triangle.me-2
span(translate) Invalid syntax
button.btn.btn-secondary.ml-auto(
button.btn.btn-secondary.ms-auto(
(click)='showConfigDefaults = !showConfigDefaults',
translate
) Show defaults
button.btn.btn-secondary.ml-3(
button.btn.btn-secondary.ms-3(
*ngIf='platform.getConfigPath()',
(click)='showConfigFile()'
)
i.fas.fa-external-link-square-alt.mr-2
i.fas.fa-external-link-square-alt.me-2
span(translate) Show config file
div([ngbNavOutlet]='nav')

View File

@@ -43,11 +43,14 @@
> .tab-content {
flex: auto;
padding: 20px 30px;
padding: 20px 0;
overflow-y: auto;
display: flex;
flex-direction: column;
> ::ng-deep .tab-pane {
height: 100%;
padding: 0 30px;
min-height: 100%;
> settings-tab-body > * {
display: block;

View File

@@ -2,7 +2,7 @@
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
import * as yaml from 'js-yaml'
import { debounce } from 'utils-decorators/dist/esm/debounce/debounce'
import { Component, Inject, Input, HostBinding, NgZone, Injector } from '@angular/core'
import { Component, Inject, Input, HostBinding, Injector } from '@angular/core'
import {
ConfigService,
BaseTabComponent,
@@ -23,9 +23,9 @@ import { ReleaseNotesComponent } from './releaseNotesTab.component'
/** @hidden */
@Component({
selector: 'settings-tab',
template: require('./settingsTab.component.pug'),
styles: [
require('./settingsTab.component.scss'),
templateUrl:'./settingsTab.component.pug',
styleUrls: [
'./settingsTab.component.scss',
],
})
export class SettingsTabComponent extends BaseTabComponent {
@@ -46,9 +46,8 @@ export class SettingsTabComponent extends BaseTabComponent {
public hostWindow: HostWindowService,
public homeBase: HomeBaseService,
public platform: PlatformService,
public zone: NgZone,
public locale: LocaleService,
private updater: UpdaterService,
public updater: UpdaterService,
private app: AppService,
@Inject(SettingsTabProvider) public settingsProviders: SettingsTabProvider[],
translate: TranslateService,

View File

@@ -5,11 +5,12 @@ import { SettingsTabProvider } from '../api'
@Component({
selector: 'settings-tab-body',
template: '<ng-template #placeholder></ng-template>',
styles: [`:host { display: block; padding-bottom: 20px; }`],
})
export class SettingsTabBodyComponent {
@Input() provider: SettingsTabProvider
@ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef
component: ComponentRef<Component>
component: ComponentRef<unknown>
constructor (private componentFactoryResolver: ComponentFactoryResolver) { }

View File

@@ -8,7 +8,7 @@
div(*ngIf='vault.isEnabled()')
.d-flex.align-items-center.mb-3
h3.m-0(translate) Vault
.d-flex.ml-auto(ngbDropdown, *ngIf='vault.isEnabled()')
.d-flex.ms-auto(ngbDropdown, *ngIf='vault.isEnabled()')
button.btn.btn-secondary(ngbDropdownToggle, translate) Options
div(ngbDropdownMenu)
a(ngbDropdownItem, (click)='changePassphrase()')
@@ -24,9 +24,9 @@ div(*ngIf='vault.isEnabled()')
h3.m-3(translate) Vault is empty
.list-group
.list-group-item.d-flex.align-items-center.p-1.pl-3(*ngFor='let secret of vaultContents.secrets')
.list-group-item.d-flex.align-items-center.p-1.ps-3(*ngFor='let secret of vaultContents.secrets')
i.fas.fa-key
.mr-auto {{getSecretLabel(secret)}}
.me-auto {{getSecretLabel(secret)}}
.hover-reveal(ngbDropdown)
button.btn.btn-link(ngbDropdownToggle)
@@ -35,21 +35,21 @@ div(*ngIf='vault.isEnabled()')
button(
ngbDropdownItem,
*ngIf='secret.type === VAULT_SECRET_TYPE_FILE',
(click)='renameFile(secret)'
(click)='renameFile(castAny(secret))'
)
i.fas.fa-fw.fa-pencil-alt
span(translate) Rename
button(
ngbDropdownItem,
*ngIf='secret.type === VAULT_SECRET_TYPE_FILE',
(click)='replaceFileContent(secret)'
(click)='replaceFileContent(castAny(secret))'
)
i.fas.fa-fw.fa-file-import
span(translate) Replace
button(
ngbDropdownItem,
*ngIf='secret.type === VAULT_SECRET_TYPE_FILE',
(click)='exportFile(secret)'
(click)='exportFile(castAny(secret))'
)
i.fas.fa-fw.fa-file-export
span(translate) Export

View File

@@ -8,7 +8,7 @@ import { SetVaultPassphraseModalComponent } from './setVaultPassphraseModal.comp
/** @hidden */
@Component({
selector: 'vault-settings-tab',
template: require('./vaultSettingsTab.component.pug'),
templateUrl:'./vaultSettingsTab.component.pug',
})
export class VaultSettingsTabComponent extends BaseComponent {
vaultContents: Vault|null = null
@@ -148,4 +148,6 @@ export class VaultSettingsTabComponent extends BaseComponent {
download.close()
}
}
castAny = (x: any) => x
}

View File

@@ -34,24 +34,30 @@ h3.mb-3(translate) Window
.form-line(*ngIf='config.store.appearance.vibrancy && isFluentVibrancySupported && config.store.hacks.enableFluentBackground')
.header
.title(translate) Background type
.btn-group(
[(ngModel)]='config.store.appearance.vibrancyType',
(ngModelChange)='saveConfiguration()',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"blur"'
)
.btn-group
input.btn-check(
type='radio',
name='vibracy',
[(ngModel)]='config.store.appearance.vibrancyType',
(ngModelChange)='saveConfiguration()',
id='vibrancyTypeBlur',
[value]='"blur"'
)
label.btn.btn-secondary(
for='vibrancyTypeBlur'
)
span(translate) Blur
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"fluent"'
)
input.btn-check(
type='radio',
name='vibracy',
[(ngModel)]='config.store.appearance.vibrancyType',
(ngModelChange)='saveConfiguration()',
id='vibrancyTypeFluent',
[value]='"fluent"'
)
label.btn.btn-secondary(
for='vibrancyTypeFluent'
)
span Fluent
.form-line(*ngIf='platform.supportsWindowControls')
@@ -71,31 +77,36 @@ h3.mb-3(translate) Window
.title(translate) Window frame
.description(translate) Whether a custom window or an OS native window should be used
.btn-group(
[(ngModel)]='config.store.appearance.frame',
(ngModelChange)='saveConfiguration(true)',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"native"'
)
.btn-group
input.btn-check(
type='radio',
name='frame',
[(ngModel)]='config.store.appearance.frame',
(ngModelChange)='saveConfiguration(true)',
id='frameNative',
[value]='"native"'
)
label.btn.btn-secondary(for='frameNative')
span(translate) Native
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"thin"'
)
input.btn-check(
type='radio',
name='frame',
[(ngModel)]='config.store.appearance.frame',
(ngModelChange)='saveConfiguration(true)',
id='frameThin',
[value]='"thin"'
)
label.btn.btn-secondary(for='frameThin')
span(translate) Thin
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"full"'
)
input.btn-check(
type='radio',
name='frame',
[(ngModel)]='config.store.appearance.frame',
(ngModelChange)='saveConfiguration(true)',
id='frameFull',
[value]='"full"'
)
label.btn.btn-secondary(for='frameFull')
span(translate) Full
h3.mt-4(translate) Docking
@@ -105,73 +116,86 @@ h3.mt-4(translate) Docking
.title(translate) Dock the terminal
.description(translate) Snaps the window to a side of the screen
.btn-group(
[(ngModel)]='config.store.appearance.dock',
(ngModelChange)='saveConfiguration(); docking.dock()',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"off"'
)
.btn-group
input.btn-check(
type='radio',
name='docking',
[(ngModel)]='config.store.appearance.dock',
(ngModelChange)='saveConfiguration(); docking.dock()',
id='dockingOff',
[value]='"off"'
)
label.btn.btn-secondary(for='dockingOff')
span(translate) Off
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"top"'
)
input.btn-check(
type='radio',
name='docking',
[(ngModel)]='config.store.appearance.dock',
(ngModelChange)='saveConfiguration(); docking.dock()',
id='dockingTop',
[value]='"top"'
)
label.btn.btn-secondary(for='dockingTop')
span(translate) Top
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"left"'
)
input.btn-check(
type='radio',
name='docking',
[(ngModel)]='config.store.appearance.dock',
(ngModelChange)='saveConfiguration(); docking.dock()',
id='dockingLeft',
[value]='"left"'
)
label.btn.btn-secondary(for='dockingLeft')
span(translate) Left
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"right"'
)
input.btn-check(
type='radio',
name='docking',
[(ngModel)]='config.store.appearance.dock',
(ngModelChange)='saveConfiguration(); docking.dock()',
id='dockingRight',
[value]='"right"'
)
label.btn.btn-secondary(for='dockingRight')
span(translate) Right
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"bottom"'
)
input.btn-check(
type='radio',
name='docking',
[(ngModel)]='config.store.appearance.dock',
(ngModelChange)='saveConfiguration(); docking.dock()',
id='dockingBottom',
[value]='"bottom"'
)
label.btn.btn-secondary(for='dockingBottom')
span(translate) Bottom
.ml-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.ms-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.header
.title(translate) Display on
.description(translate) Snaps the window to a side of the screen
div(
[(ngModel)]='config.store.appearance.dockScreen',
(ngModelChange)='saveConfiguration(); docking.dock()',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
value='current'
)
div
input.btn-check(
type='radio',
name='dockScreen',
[(ngModel)]='config.store.appearance.dockScreen',
(ngModelChange)='saveConfiguration(); docking.dock()',
id='dockScreenCurrent',
value='current'
)
label.btn.btn-secondary(id='dockScreenCurrent')
span(translate) Current
label.btn.btn-secondary(*ngFor='let screen of screens', ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='screen.id'
)
input.btn-check(
type='radio',
name='dockScreen',
[(ngModel)]='config.store.appearance.dockScreen',
(ngModelChange)='saveConfiguration(); docking.dock()',
id='dockScreen{{screen.id}}',
[value]='screen.id'
)
label.btn.btn-secondary(*ngFor='let screen of screens', for='dockScreen{{screen.id}}')
| {{screen.name}}
.ml-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.ms-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.header
.title(translate) Dock always on top
.description(translate) Keep docked terminal always on top
@@ -180,7 +204,7 @@ h3.mt-4(translate) Docking
(ngModelChange)='saveConfiguration(); docking.dock()',
)
.ml-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.ms-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.header
.title(translate) Docked terminal size
.description(translate) Window dimension away from the edge
@@ -193,7 +217,7 @@ h3.mt-4(translate) Docking
step='0.01'
)
.ml-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.ms-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.header
.title(translate) Docked terminal space
.description(translate) Window dimension along the edge
@@ -206,7 +230,7 @@ h3.mt-4(translate) Docking
step='0.01'
)
.ml-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.ms-5.form-line(*ngIf='docking && config.store.appearance.dock != "off"')
.header
.title(translate) Hide window on focus loss
.description(translate) Hides the docked terminal when you click away.
@@ -220,61 +244,71 @@ h3.mt-4(translate) Tabs
.form-line
.header
.title(translate) Tabs location
.btn-group(
[(ngModel)]='config.store.appearance.tabsLocation',
(ngModelChange)='saveConfiguration()',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"top"'
)
.btn-group
input.btn-check(
type='radio',
name='tabsLocation',
[(ngModel)]='config.store.appearance.tabsLocation',
(ngModelChange)='saveConfiguration()',
id='tabsLocationTop',
[value]='"top"'
)
label.btn.btn-secondary(for='tabsLocationTop')
span(translate) Top
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"bottom"'
)
input.btn-check(
type='radio',
name='tabsLocation',
[(ngModel)]='config.store.appearance.tabsLocation',
(ngModelChange)='saveConfiguration()',
id='tabsLocationBottom',
[value]='"bottom"'
)
label.btn.btn-secondary(for='tabsLocationBottom')
span(translate) Bottom
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"left"'
)
input.btn-check(
type='radio',
name='tabsLocation',
[(ngModel)]='config.store.appearance.tabsLocation',
(ngModelChange)='saveConfiguration()',
id='tabsLocationLeft',
[value]='"left"'
)
label.btn.btn-secondary(for='tabsLocationLeft')
span(translate) Left
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"right"'
)
input.btn-check(
type='radio',
name='tabsLocation',
[(ngModel)]='config.store.appearance.tabsLocation',
(ngModelChange)='saveConfiguration()',
id='tabsLocationRight',
[value]='"right"'
)
label.btn.btn-secondary(for='tabsLocationRight')
span(translate) Right
.form-line
.header
.title(translate) Tabs width
.btn-group(
[(ngModel)]='config.store.appearance.flexTabs',
(ngModelChange)='saveConfiguration()',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='true'
)
.btn-group
input.btn-check(
type='radio',
name='flexTabs',
[(ngModel)]='config.store.appearance.flexTabs',
(ngModelChange)='saveConfiguration()',
id='flexTabsTrue',
[value]='true'
)
label.btn.btn-secondary(for='flexTabsTrue')
span(translate, translateComment='[Dynamic] tab width') id.tab-width.dynamic
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='false'
)
input.btn-check(
type='radio',
name='flexTabs',
[(ngModel)]='config.store.appearance.flexTabs',
(ngModelChange)='saveConfiguration()',
id='flexTabsFalse',
[value]='false'
)
label.btn.btn-secondary(for='flexTabsFalse')
span(translate) Fixed
.form-line

View File

@@ -18,7 +18,7 @@ import {
/** @hidden */
@Component({
selector: 'window-settings-tab',
template: require('./windowSettingsTab.component.pug'),
templateUrl:'./windowSettingsTab.component.pug',
})
export class WindowSettingsTabComponent extends BaseComponent {
screens: Screen[]

View File

@@ -1,5 +1,5 @@
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { CommonModule } from '@angular/common'
import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { InfiniteScrollModule } from 'ngx-infinite-scroll'
@@ -30,7 +30,7 @@ import { HotkeySettingsTabProvider, WindowSettingsTabProvider, VaultSettingsTabP
/** @hidden */
@NgModule({
imports: [
BrowserModule,
CommonModule,
FormsModule,
NgbModule,
TabbyCorePlugin,
@@ -46,18 +46,6 @@ import { HotkeySettingsTabProvider, WindowSettingsTabProvider, VaultSettingsTabP
{ provide: SettingsTabProvider, useClass: ProfilesSettingsTabProvider, multi: true },
{ provide: SettingsTabProvider, useClass: ConfigSyncSettingsTabProvider, multi: true },
],
entryComponents: [
EditProfileModalComponent,
HotkeyInputModalComponent,
HotkeySettingsTabComponent,
ProfilesSettingsTabComponent,
SettingsTabComponent,
SetVaultPassphraseModalComponent,
VaultSettingsTabComponent,
WindowSettingsTabComponent,
ConfigSyncSettingsTabComponent,
ReleaseNotesComponent,
],
declarations: [
EditProfileModalComponent,
HotkeyInputModalComponent,

View File

@@ -1,5 +0,0 @@
const config = require('../webpack.plugin.config')
module.exports = config({
name: 'settings',
dirname: __dirname,
})

View File

@@ -0,0 +1,10 @@
import * as path from 'path'
import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
import config from '../webpack.plugin.config.mjs'
export default () => config({
name: 'settings',
dirname: __dirname,
})

View File

@@ -2,30 +2,24 @@
# yarn lockfile v1
"@scarf/scarf@^1.1.0":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.1.1.tgz#d8b9f20037b3a37dbf8dcdc4b3b72f9285bfce35"
integrity sha512-VGbKDbk1RFIaSmdVb0cNjjWJoRWRI/Weo23AjRCC2nryO0iAS8pzsToJfPVPtVs74WHw4L1UTADNdIYRLkirZQ==
"@types/marked@^4.0.8":
version "4.0.8"
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.8.tgz#b316887ab3499d0a8f4c70b7bd8508f92d477955"
integrity sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw==
"@types/marked@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.2.tgz#cb2dbf10da2f41cf20bd91fb5f89b67540c282f7"
integrity sha512-auNrZ/c0w6wsM9DccwVxWHssrMDezHUAXNesdp2RQrCVCyrQbOiSq7yqdJKrUQQpw9VTm7CGYJH2A/YG7jjrjQ==
marked@^4.2.12:
version "4.2.12"
resolved "https://registry.yarnpkg.com/marked/-/marked-4.2.12.tgz#d69a64e21d71b06250da995dcd065c11083bebb5"
integrity sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==
marked@^4.0.8:
version "4.0.12"
resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d"
integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
ngx-infinite-scroll@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-10.0.1.tgz#6f51f2f8775a7c50d1dd8bad125d4e748abbe880"
integrity sha512-7is0eJZ9kJPsaHohRmMhJ/QFHAW9jp9twO5HcHRvFM/Yl/R8QCiokgjwmH0/CR3MuxUanxfHZMfO3PbYTwlBEg==
ngx-infinite-scroll@^15:
version "15.0.0"
resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-15.0.0.tgz#61bbf89f121a796880a4ad67fe785b406532b220"
integrity sha512-FSP5UphRdl47vW8f/dRnPAU+napzruAKizBX2HS7MH292Ca+va6IU0J5+UQQmO5rXod2RZV7UhJ6+7g4xLfs1A==
dependencies:
"@scarf/scarf" "^1.1.0"
opencollective-postinstall "^2.0.2"
tslib "^2.3.0"
opencollective-postinstall@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
tslib@^2.3.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==