mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-29 07:49:53 +00:00
settings ui updates
This commit is contained in:
parent
dc53668685
commit
b4e703674b
@ -21,4 +21,5 @@ export { NotificationsService } from '../services/notifications.service'
|
|||||||
export { ShellIntegrationService } from '../services/shellIntegration.service'
|
export { ShellIntegrationService } from '../services/shellIntegration.service'
|
||||||
export { ThemesService } from '../services/themes.service'
|
export { ThemesService } from '../services/themes.service'
|
||||||
export { TabsService } from '../services/tabs.service'
|
export { TabsService } from '../services/tabs.service'
|
||||||
|
export { UpdaterService } from '../services/updater.service'
|
||||||
export * from '../utils'
|
export * from '../utils'
|
||||||
|
@ -86,7 +86,7 @@ title-bar(
|
|||||||
button.btn.btn-secondary.btn-tab-bar.btn-update(
|
button.btn.btn-secondary.btn-tab-bar.btn-update(
|
||||||
*ngIf='updatesAvailable',
|
*ngIf='updatesAvailable',
|
||||||
title='Update available - Click to install',
|
title='Update available - Click to install',
|
||||||
(click)='updateApp()',
|
(click)='updater.update()',
|
||||||
[fastHtmlBind]='updateIcon'
|
[fastHtmlBind]='updateIcon'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -136,9 +136,13 @@ export class AppRootComponent {
|
|||||||
ngbModal.open(SafeModeModalComponent)
|
ngbModal.open(SafeModeModalComponent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
if (this.config.store.enableAutomaticUpdates) {
|
||||||
this.updater.check().then(available => {
|
this.updater.check().then(available => {
|
||||||
this.updatesAvailable = available
|
this.updatesAvailable = available
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
}, 3600 * 12)
|
||||||
|
|
||||||
this.touchbar.update()
|
this.touchbar.update()
|
||||||
|
|
||||||
@ -190,20 +194,6 @@ export class AppRootComponent {
|
|||||||
return this.config.store.appearance.tabsLocation === 'left' || this.config.store.appearance.tabsLocation === 'right'
|
return this.config.store.appearance.tabsLocation === 'left' || this.config.store.appearance.tabsLocation === 'right'
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateApp () {
|
|
||||||
if ((await this.electron.showMessageBox(
|
|
||||||
this.hostApp.getWindow(),
|
|
||||||
{
|
|
||||||
type: 'warning',
|
|
||||||
message: 'Installing the update will close all tabs and restart Terminus.',
|
|
||||||
buttons: ['Cancel', 'Update'],
|
|
||||||
defaultId: 1,
|
|
||||||
}
|
|
||||||
)).response === 1) {
|
|
||||||
this.updater.update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onTabDragStart () {
|
onTabDragStart () {
|
||||||
this.tabsDragging = true
|
this.tabsDragging = true
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,8 @@
|
|||||||
#handle,
|
#handle,
|
||||||
[style.background-color]='tab.color',
|
[style.background-color]='tab.color',
|
||||||
) {{index + 1}}
|
) {{index + 1}}
|
||||||
.name([title]='tab.customTitle || tab.title') {{tab.customTitle || tab.title}}
|
.name(
|
||||||
|
[title]='tab.customTitle || tab.title',
|
||||||
|
[class.no-hover]='config.store.terminal.hideCloseButton'
|
||||||
|
) {{tab.customTitle || tab.title}}
|
||||||
button(*ngIf='!config.store.terminal.hideCloseButton',(click)='app.closeTab(tab, true)') ×
|
button(*ngIf='!config.store.terminal.hideCloseButton',(click)='app.closeTab(tab, true)') ×
|
||||||
|
@ -76,7 +76,7 @@ $tabs-height: 38px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover .name {
|
&:hover .name:not(.no-hover) {
|
||||||
-webkit-mask-image: linear-gradient(black 0 0), linear-gradient(to left, transparent 0%, black 100%);
|
-webkit-mask-image: linear-gradient(black 0 0), linear-gradient(to left, transparent 0%, black 100%);
|
||||||
-webkit-mask-size: calc(100% - 60px) auto, 60px auto;
|
-webkit-mask-size: calc(100% - 60px) auto, 60px auto;
|
||||||
-webkit-mask-repeat: no-repeat;
|
-webkit-mask-repeat: no-repeat;
|
||||||
|
@ -4,6 +4,7 @@ import { Injectable } from '@angular/core'
|
|||||||
import { Logger, LogService } from './log.service'
|
import { Logger, LogService } from './log.service'
|
||||||
import { ElectronService } from './electron.service'
|
import { ElectronService } from './electron.service'
|
||||||
import { ConfigService } from './config.service'
|
import { ConfigService } from './config.service'
|
||||||
|
import { HostAppService } from './hostApp.service'
|
||||||
|
|
||||||
const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/latest'
|
const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/latest'
|
||||||
|
|
||||||
@ -17,8 +18,9 @@ export class UpdaterService {
|
|||||||
|
|
||||||
private constructor (
|
private constructor (
|
||||||
log: LogService,
|
log: LogService,
|
||||||
|
config: ConfigService,
|
||||||
private electron: ElectronService,
|
private electron: ElectronService,
|
||||||
private config: ConfigService,
|
private hostApp: HostAppService,
|
||||||
) {
|
) {
|
||||||
this.logger = log.create('updater')
|
this.logger = log.create('updater')
|
||||||
|
|
||||||
@ -58,10 +60,42 @@ export class UpdaterService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async check (): Promise<boolean> {
|
async check (): Promise<boolean> {
|
||||||
if (!this.config.store.enableAutomaticUpdates) {
|
if (this.electronUpdaterAvailable) {
|
||||||
return false
|
return new Promise((resolve, reject) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/init-declarations, prefer-const
|
||||||
|
let cancel
|
||||||
|
const onNoUpdate = () => {
|
||||||
|
cancel()
|
||||||
|
resolve(false)
|
||||||
}
|
}
|
||||||
if (!this.electronUpdaterAvailable) {
|
const onUpdate = () => {
|
||||||
|
cancel()
|
||||||
|
resolve(this.downloaded)
|
||||||
|
}
|
||||||
|
const onError = (err) => {
|
||||||
|
cancel()
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
cancel = () => {
|
||||||
|
this.electron.autoUpdater.off('error', onError)
|
||||||
|
this.electron.autoUpdater.off('update-not-available', onNoUpdate)
|
||||||
|
this.electron.autoUpdater.off('update-available', onUpdate)
|
||||||
|
}
|
||||||
|
this.electron.autoUpdater.on('error', onError)
|
||||||
|
this.electron.autoUpdater.on('update-not-available', onNoUpdate)
|
||||||
|
this.electron.autoUpdater.on('update-available', onUpdate)
|
||||||
|
this.electron.autoUpdater.checkForUpdates()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.electron.autoUpdater.on('update-available', () => {
|
||||||
|
this.logger.info('Update available')
|
||||||
|
})
|
||||||
|
|
||||||
|
this.electron.autoUpdater.once('update-not-available', () => {
|
||||||
|
this.logger.info('No updates')
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
this.logger.debug('Checking for updates through fallback method.')
|
this.logger.debug('Checking for updates through fallback method.')
|
||||||
const response = await axios.get(UPDATES_URL)
|
const response = await axios.get(UPDATES_URL)
|
||||||
const data = response.data
|
const data = response.data
|
||||||
@ -81,8 +115,18 @@ export class UpdaterService {
|
|||||||
if (!this.electronUpdaterAvailable) {
|
if (!this.electronUpdaterAvailable) {
|
||||||
this.electron.shell.openExternal(this.updateURL)
|
this.electron.shell.openExternal(this.updateURL)
|
||||||
} else {
|
} else {
|
||||||
|
if ((await this.electron.showMessageBox(
|
||||||
|
this.hostApp.getWindow(),
|
||||||
|
{
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Installing the update will close all tabs and restart Terminus.',
|
||||||
|
buttons: ['Cancel', 'Update'],
|
||||||
|
defaultId: 1,
|
||||||
|
}
|
||||||
|
)).response === 1) {
|
||||||
await this.downloaded
|
await this.downloaded
|
||||||
this.electron.autoUpdater.quitAndInstall()
|
this.electron.autoUpdater.quitAndInstall()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
h3.mb-3 Hotkeys
|
||||||
|
|
||||||
|
.input-group.mb-4
|
||||||
|
.input-group-prepend
|
||||||
|
.input-group-text
|
||||||
|
i.fas.fa-fw.fa-search
|
||||||
|
input.form-control(type='search', placeholder='Search hotkeys', [(ngModel)]='hotkeyFilter')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
table.hotkeys-table
|
||||||
|
tr
|
||||||
|
th Name
|
||||||
|
th ID
|
||||||
|
th Hotkey
|
||||||
|
ng-container(*ngFor='let hotkey of hotkeyDescriptions')
|
||||||
|
tr(*ngIf='!hotkeyFilter || hotkeyFilterFn(hotkey, hotkeyFilter)')
|
||||||
|
td {{hotkey.name}}
|
||||||
|
td {{hotkey.id}}
|
||||||
|
td.pr-5
|
||||||
|
multi-hotkey-input(
|
||||||
|
[model]='getHotkey(hotkey.id) || []',
|
||||||
|
(modelChange)='setHotkey(hotkey.id, $event)'
|
||||||
|
)
|
@ -0,0 +1,7 @@
|
|||||||
|
.hotkeys-table {
|
||||||
|
margin-top: 30px;
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
import { Component, NgZone } from '@angular/core'
|
||||||
|
import {
|
||||||
|
ConfigService,
|
||||||
|
HotkeyDescription,
|
||||||
|
HotkeysService,
|
||||||
|
HostAppService,
|
||||||
|
} from 'terminus-core'
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Component({
|
||||||
|
selector: 'hotkey-settings-tab',
|
||||||
|
template: require('./hotkeySettingsTab.component.pug'),
|
||||||
|
styles: [
|
||||||
|
require('./hotkeySettingsTab.component.scss'),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class HotkeySettingsTabComponent {
|
||||||
|
hotkeyFilter = ''
|
||||||
|
hotkeyDescriptions: HotkeyDescription[]
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
public config: ConfigService,
|
||||||
|
public hostApp: HostAppService,
|
||||||
|
public zone: NgZone,
|
||||||
|
hotkeys: HotkeysService,
|
||||||
|
) {
|
||||||
|
hotkeys.getHotkeyDescriptions().then(descriptions => {
|
||||||
|
this.hotkeyDescriptions = descriptions
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getHotkey (id: string) {
|
||||||
|
let ptr = this.config.store.hotkeys
|
||||||
|
for (const token of id.split(/\./g)) {
|
||||||
|
ptr = ptr[token]
|
||||||
|
}
|
||||||
|
return ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
setHotkey (id: string, value) {
|
||||||
|
let ptr = this.config.store
|
||||||
|
let prop = 'hotkeys'
|
||||||
|
for (const token of id.split(/\./g)) {
|
||||||
|
ptr = ptr[prop]
|
||||||
|
prop = token
|
||||||
|
}
|
||||||
|
ptr[prop] = value
|
||||||
|
this.config.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
hotkeyFilterFn (hotkey: HotkeyDescription, query: string): boolean {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||||
|
const s = hotkey.name + (this.getHotkey(hotkey.id) || []).toString()
|
||||||
|
return s.toLowerCase().includes(query.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
@ -7,135 +7,38 @@ button.btn.btn-outline-warning.btn-block(*ngIf='config.restartRequested', '(clic
|
|||||||
i.fas.fa-fw.fa-window-maximize.mr-2
|
i.fas.fa-fw.fa-window-maximize.mr-2
|
||||||
| Application
|
| Application
|
||||||
ng-template(ngbNavContent)
|
ng-template(ngbNavContent)
|
||||||
.d-flex.align-items-center.flex-wrap.mb-4
|
.terminus-logo.mt-3
|
||||||
h1.terminus-title.mb-2.mr-2 Terminus
|
h1.terminus-title Terminus
|
||||||
sup α
|
sup α
|
||||||
|
|
||||||
.text-muted.mr-auto {{homeBase.appVersion}}
|
.text-center
|
||||||
|
.text-muted {{homeBase.appVersion}}
|
||||||
|
|
||||||
div
|
.mb-5.mt-3
|
||||||
button.btn.btn-secondary.mr-3((click)='homeBase.openGitHub()')
|
button.btn.btn-secondary.mr-3((click)='homeBase.openGitHub()')
|
||||||
i.fab.fa-github
|
i.fab.fa-github
|
||||||
span GitHub
|
span GitHub
|
||||||
|
|
||||||
button.btn.btn-secondary((click)='homeBase.reportBug()')
|
button.btn.btn-secondary.mr-3((click)='homeBase.reportBug()')
|
||||||
i.fas.fa-bug
|
i.fas.fa-bug
|
||||||
span Report a problem
|
span Report a problem
|
||||||
|
|
||||||
.form-line
|
button.btn.btn-secondary(
|
||||||
.header
|
*ngIf='!updateAvailable',
|
||||||
.title Theme
|
(click)='checkForUpdates()',
|
||||||
select.form-control(
|
[disabled]='checkingForUpdate'
|
||||||
[(ngModel)]='config.store.appearance.theme',
|
|
||||||
(ngModelChange)='saveConfiguration()',
|
|
||||||
)
|
)
|
||||||
option(*ngFor='let theme of themes', [ngValue]='theme.name') {{theme.name}}
|
i.fas.fa-sync(
|
||||||
|
[class.fa-spin]='checkingForUpdate'
|
||||||
|
)
|
||||||
|
span Check for updates
|
||||||
|
|
||||||
.form-line
|
button.btn.btn-info(
|
||||||
.header
|
*ngIf='updateAvailable',
|
||||||
.title Tabs location
|
(click)='updater.update()',
|
||||||
.btn-group(
|
|
||||||
[(ngModel)]='config.store.appearance.tabsLocation',
|
|
||||||
(ngModelChange)='saveConfiguration()',
|
|
||||||
ngbRadioGroup
|
|
||||||
)
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"top"'
|
|
||||||
)
|
|
||||||
| Top
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"bottom"'
|
|
||||||
)
|
|
||||||
| Bottom
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"left"'
|
|
||||||
)
|
|
||||||
| Left
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"right"'
|
|
||||||
)
|
|
||||||
| Right
|
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title Tabs width
|
|
||||||
.btn-group(
|
|
||||||
[(ngModel)]='config.store.appearance.flexTabs',
|
|
||||||
(ngModelChange)='saveConfiguration()',
|
|
||||||
ngbRadioGroup
|
|
||||||
)
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='true'
|
|
||||||
)
|
|
||||||
| Dynamic
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='false'
|
|
||||||
)
|
|
||||||
| Fixed
|
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title(*ngIf='hostApp.platform !== Platform.macOS') Acrylic background
|
|
||||||
.title(*ngIf='hostApp.platform === Platform.macOS') Vibrancy
|
|
||||||
.description Gives the window a blurred transparent background
|
|
||||||
|
|
||||||
toggle(
|
|
||||||
[(ngModel)]='config.store.appearance.vibrancy',
|
|
||||||
(ngModelChange)='saveConfiguration()'
|
|
||||||
)
|
|
||||||
|
|
||||||
.form-line(*ngIf='config.store.appearance.vibrancy && isFluentVibrancySupported')
|
|
||||||
.header
|
|
||||||
.title Background type
|
|
||||||
.btn-group(
|
|
||||||
[(ngModel)]='config.store.appearance.vibrancyType',
|
|
||||||
(ngModelChange)='saveConfiguration()',
|
|
||||||
ngbRadioGroup
|
|
||||||
)
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"blur"'
|
|
||||||
)
|
|
||||||
| Blur
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"fluent"'
|
|
||||||
)
|
|
||||||
| Fluent
|
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title Opacity
|
|
||||||
input(
|
|
||||||
type='range',
|
|
||||||
[(ngModel)]='config.store.appearance.opacity',
|
|
||||||
(ngModelChange)='saveConfiguration(); (hostApp.platform === Platform.Linux && config.requestRestart())',
|
|
||||||
min='0.4',
|
|
||||||
max='1',
|
|
||||||
step='0.01'
|
|
||||||
)
|
)
|
||||||
|
i.fas.fa-sync
|
||||||
|
span Update
|
||||||
|
|
||||||
.form-line(*ngIf='hostApp.platform !== Platform.Linux')
|
.form-line(*ngIf='hostApp.platform !== Platform.Linux')
|
||||||
.header
|
.header
|
||||||
@ -143,151 +46,6 @@ button.btn.btn-outline-warning.btn-block(*ngIf='config.restartRequested', '(clic
|
|||||||
.description Allows quickly opening a terminal in the selected folder
|
.description Allows quickly opening a terminal in the selected folder
|
||||||
toggle([ngModel]='isShellIntegrationInstalled', (ngModelChange)='toggleShellIntegration()')
|
toggle([ngModel]='isShellIntegrationInstalled', (ngModelChange)='toggleShellIntegration()')
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title Window frame
|
|
||||||
.description 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"'
|
|
||||||
)
|
|
||||||
| Native
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"thin"'
|
|
||||||
)
|
|
||||||
| Thin
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"full"'
|
|
||||||
)
|
|
||||||
| Full
|
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title Dock the terminal
|
|
||||||
.description 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"'
|
|
||||||
)
|
|
||||||
| Off
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"top"'
|
|
||||||
)
|
|
||||||
| Top
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"left"'
|
|
||||||
)
|
|
||||||
| Left
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"right"'
|
|
||||||
)
|
|
||||||
| Right
|
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='"bottom"'
|
|
||||||
)
|
|
||||||
| Bottom
|
|
||||||
|
|
||||||
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
|
||||||
.header
|
|
||||||
.title Display on
|
|
||||||
.description 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'
|
|
||||||
)
|
|
||||||
| Current
|
|
||||||
label.btn.btn-secondary(*ngFor='let screen of screens', ngbButtonLabel)
|
|
||||||
input(
|
|
||||||
type='radio',
|
|
||||||
ngbButton,
|
|
||||||
[value]='screen.id'
|
|
||||||
)
|
|
||||||
| {{screen.name}}
|
|
||||||
|
|
||||||
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
|
||||||
.header
|
|
||||||
.title Dock always on top
|
|
||||||
.description Keep docked terminal always on top
|
|
||||||
toggle(
|
|
||||||
[(ngModel)]='config.store.appearance.dockAlwaysOnTop',
|
|
||||||
(ngModelChange)='saveConfiguration(); docking.dock()',
|
|
||||||
)
|
|
||||||
|
|
||||||
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
|
||||||
.header
|
|
||||||
.title Docked terminal size
|
|
||||||
input(
|
|
||||||
type='range',
|
|
||||||
[(ngModel)]='config.store.appearance.dockFill',
|
|
||||||
(mouseup)='saveConfiguration(); docking.dock()',
|
|
||||||
min='0.05',
|
|
||||||
max='1',
|
|
||||||
step='0.01'
|
|
||||||
)
|
|
||||||
|
|
||||||
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
|
||||||
.header
|
|
||||||
.title Docked terminal space
|
|
||||||
input(
|
|
||||||
type='range',
|
|
||||||
[(ngModel)]='config.store.appearance.dockSpace',
|
|
||||||
(mouseup)='saveConfiguration(); docking.dock()',
|
|
||||||
min='0.2',
|
|
||||||
max='1',
|
|
||||||
step='0.01'
|
|
||||||
)
|
|
||||||
|
|
||||||
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
|
||||||
.header
|
|
||||||
.title Hide dock on blur
|
|
||||||
.description Hides the docked terminal when you click away.
|
|
||||||
toggle(
|
|
||||||
[(ngModel)]='config.store.appearance.dockHideOnBlur',
|
|
||||||
(ngModelChange)='saveConfiguration(); ',
|
|
||||||
)
|
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Debugging
|
.title Debugging
|
||||||
@ -311,43 +69,6 @@ button.btn.btn-outline-warning.btn-block(*ngIf='config.restartRequested', '(clic
|
|||||||
.description Enable automatic installation of updates when they become available.
|
.description Enable automatic installation of updates when they become available.
|
||||||
toggle([(ngModel)]='config.store.enableAutomaticUpdates', (ngModelChange)='saveConfiguration()')
|
toggle([(ngModel)]='config.store.enableAutomaticUpdates', (ngModelChange)='saveConfiguration()')
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title Custom CSS
|
|
||||||
textarea.form-control(
|
|
||||||
[(ngModel)]='config.store.appearance.css',
|
|
||||||
(ngModelChange)='saveConfiguration()',
|
|
||||||
)
|
|
||||||
|
|
||||||
li(ngbNavItem='hotkeys')
|
|
||||||
a(ngbNavLink)
|
|
||||||
i.fas.fa-fw.fa-keyboard.mr-2
|
|
||||||
| Hotkeys
|
|
||||||
ng-template(ngbNavContent)
|
|
||||||
h3.mb-3 Hotkeys
|
|
||||||
|
|
||||||
.input-group.mb-4
|
|
||||||
.input-group-prepend
|
|
||||||
.input-group-text
|
|
||||||
i.fas.fa-fw.fa-search
|
|
||||||
input.form-control(type='search', placeholder='Search hotkeys', [(ngModel)]='hotkeyFilter')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
table.hotkeys-table
|
|
||||||
tr
|
|
||||||
th Name
|
|
||||||
th ID
|
|
||||||
th Hotkey
|
|
||||||
ng-container(*ngFor='let hotkey of hotkeyDescriptions')
|
|
||||||
tr(*ngIf='!hotkeyFilter || hotkeyFilterFn(hotkey, hotkeyFilter)')
|
|
||||||
td {{hotkey.name}}
|
|
||||||
td {{hotkey.id}}
|
|
||||||
td.pr-5
|
|
||||||
multi-hotkey-input(
|
|
||||||
[model]='getHotkey(hotkey.id) || []',
|
|
||||||
(modelChange)='setHotkey(hotkey.id, $event); saveConfiguration(); docking.dock()'
|
|
||||||
)
|
|
||||||
|
|
||||||
li(*ngFor='let provider of settingsProviders', [ngbNavItem]='provider.id')
|
li(*ngFor='let provider of settingsProviders', [ngbNavItem]='provider.id')
|
||||||
a(ngbNavLink)
|
a(ngbNavLink)
|
||||||
i(class='fas fa-fw mr-2 fa-{{provider.icon || "puzzle-piece"}}')
|
i(class='fas fa-fw mr-2 fa-{{provider.icon || "puzzle-piece"}}')
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
padding: 20px 30px;
|
padding: 20px 30px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
> .tab-pane {
|
> ::ng-deep .tab-pane {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,15 +35,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.hotkeys-table {
|
|
||||||
margin-top: 30px;
|
|
||||||
|
|
||||||
td, th {
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
font-family: 'Source Code Pro', monospace;
|
font-family: 'Source Code Pro', monospace;
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
|
@ -5,18 +5,13 @@ import { Subscription } from 'rxjs'
|
|||||||
import { Component, Inject, Input, HostBinding, NgZone } from '@angular/core'
|
import { Component, Inject, Input, HostBinding, NgZone } from '@angular/core'
|
||||||
import {
|
import {
|
||||||
ElectronService,
|
ElectronService,
|
||||||
DockingService,
|
|
||||||
ConfigService,
|
ConfigService,
|
||||||
HotkeyDescription,
|
|
||||||
HotkeysService,
|
|
||||||
BaseTabComponent,
|
BaseTabComponent,
|
||||||
Theme,
|
|
||||||
HostAppService,
|
HostAppService,
|
||||||
Platform,
|
Platform,
|
||||||
HomeBaseService,
|
HomeBaseService,
|
||||||
ShellIntegrationService,
|
ShellIntegrationService,
|
||||||
isWindowsBuild,
|
UpdaterService,
|
||||||
WIN_BUILD_FLUENT_BG_SUPPORTED,
|
|
||||||
} from 'terminus-core'
|
} from 'terminus-core'
|
||||||
|
|
||||||
import { SettingsTabProvider } from '../api'
|
import { SettingsTabProvider } from '../api'
|
||||||
@ -31,34 +26,29 @@ import { SettingsTabProvider } from '../api'
|
|||||||
})
|
})
|
||||||
export class SettingsTabComponent extends BaseTabComponent {
|
export class SettingsTabComponent extends BaseTabComponent {
|
||||||
@Input() activeTab: string
|
@Input() activeTab: string
|
||||||
hotkeyFilter = ''
|
|
||||||
hotkeyDescriptions: HotkeyDescription[]
|
|
||||||
screens: any[]
|
|
||||||
Platform = Platform
|
Platform = Platform
|
||||||
configDefaults: any
|
configDefaults: any
|
||||||
configFile: string
|
configFile: string
|
||||||
isShellIntegrationInstalled = false
|
isShellIntegrationInstalled = false
|
||||||
isFluentVibrancySupported = false
|
checkingForUpdate = false
|
||||||
|
updateAvailable = false
|
||||||
@HostBinding('class.pad-window-controls') padWindowControls = false
|
@HostBinding('class.pad-window-controls') padWindowControls = false
|
||||||
private configSubscription: Subscription
|
private configSubscription: Subscription
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
public config: ConfigService,
|
public config: ConfigService,
|
||||||
private electron: ElectronService,
|
private electron: ElectronService,
|
||||||
public docking: DockingService,
|
|
||||||
public hostApp: HostAppService,
|
public hostApp: HostAppService,
|
||||||
public homeBase: HomeBaseService,
|
public homeBase: HomeBaseService,
|
||||||
public shellIntegration: ShellIntegrationService,
|
public shellIntegration: ShellIntegrationService,
|
||||||
public zone: NgZone,
|
public zone: NgZone,
|
||||||
hotkeys: HotkeysService,
|
private updater: UpdaterService,
|
||||||
@Inject(SettingsTabProvider) public settingsProviders: SettingsTabProvider[],
|
@Inject(SettingsTabProvider) public settingsProviders: SettingsTabProvider[],
|
||||||
@Inject(Theme) public themes: Theme[],
|
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
this.setTitle('Settings')
|
this.setTitle('Settings')
|
||||||
this.screens = this.docking.getScreens()
|
|
||||||
this.settingsProviders = config.enabledServices(this.settingsProviders)
|
this.settingsProviders = config.enabledServices(this.settingsProviders)
|
||||||
this.themes = config.enabledServices(this.themes)
|
this.settingsProviders.sort((a, b) => a.title.localeCompare(b.title))
|
||||||
|
|
||||||
this.configDefaults = yaml.dump(config.getDefaults())
|
this.configDefaults = yaml.dump(config.getDefaults())
|
||||||
|
|
||||||
@ -70,16 +60,6 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
|
|
||||||
this.configSubscription = config.changed$.subscribe(onConfigChange)
|
this.configSubscription = config.changed$.subscribe(onConfigChange)
|
||||||
onConfigChange()
|
onConfigChange()
|
||||||
|
|
||||||
hostApp.displaysChanged$.subscribe(() => {
|
|
||||||
this.zone.run(() => this.screens = this.docking.getScreens())
|
|
||||||
})
|
|
||||||
|
|
||||||
hotkeys.getHotkeyDescriptions().then(descriptions => {
|
|
||||||
this.hotkeyDescriptions = descriptions
|
|
||||||
})
|
|
||||||
|
|
||||||
this.isFluentVibrancySupported = isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
@ -131,27 +111,9 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getHotkey (id: string) {
|
async checkForUpdates () {
|
||||||
let ptr = this.config.store.hotkeys
|
this.checkingForUpdate = true
|
||||||
for (const token of id.split(/\./g)) {
|
this.updateAvailable = await this.updater.check()
|
||||||
ptr = ptr[token]
|
this.checkingForUpdate = false
|
||||||
}
|
|
||||||
return ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
setHotkey (id: string, value) {
|
|
||||||
let ptr = this.config.store
|
|
||||||
let prop = 'hotkeys'
|
|
||||||
for (const token of id.split(/\./g)) {
|
|
||||||
ptr = ptr[prop]
|
|
||||||
prop = token
|
|
||||||
}
|
|
||||||
ptr[prop] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
hotkeyFilterFn (hotkey: HotkeyDescription, query: string): boolean {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
||||||
const s = hotkey.name + (this.getHotkey(hotkey.id) || []).toString()
|
|
||||||
return s.toLowerCase().includes(query.toLowerCase())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
279
terminus-settings/src/components/windowSettingsTab.component.pug
Normal file
279
terminus-settings/src/components/windowSettingsTab.component.pug
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
h3.mb-3 Window
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Theme
|
||||||
|
select.form-control(
|
||||||
|
[(ngModel)]='config.store.appearance.theme',
|
||||||
|
(ngModelChange)='saveConfiguration()',
|
||||||
|
)
|
||||||
|
option(*ngFor='let theme of themes', [ngValue]='theme.name') {{theme.name}}
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title(*ngIf='hostApp.platform !== Platform.macOS') Acrylic background
|
||||||
|
.title(*ngIf='hostApp.platform === Platform.macOS') Vibrancy
|
||||||
|
.description Gives the window a blurred transparent background
|
||||||
|
|
||||||
|
toggle(
|
||||||
|
[(ngModel)]='config.store.appearance.vibrancy',
|
||||||
|
(ngModelChange)='saveConfiguration()'
|
||||||
|
)
|
||||||
|
|
||||||
|
.form-line(*ngIf='config.store.appearance.vibrancy && isFluentVibrancySupported')
|
||||||
|
.header
|
||||||
|
.title Background type
|
||||||
|
.btn-group(
|
||||||
|
[(ngModel)]='config.store.appearance.vibrancyType',
|
||||||
|
(ngModelChange)='saveConfiguration()',
|
||||||
|
ngbRadioGroup
|
||||||
|
)
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"blur"'
|
||||||
|
)
|
||||||
|
| Blur
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"fluent"'
|
||||||
|
)
|
||||||
|
| Fluent
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Opacity
|
||||||
|
input(
|
||||||
|
type='range',
|
||||||
|
[(ngModel)]='config.store.appearance.opacity',
|
||||||
|
(ngModelChange)='saveConfiguration(); (hostApp.platform === Platform.Linux && config.requestRestart())',
|
||||||
|
min='0.4',
|
||||||
|
max='1',
|
||||||
|
step='0.01'
|
||||||
|
)
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Window frame
|
||||||
|
.description 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"'
|
||||||
|
)
|
||||||
|
| Native
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"thin"'
|
||||||
|
)
|
||||||
|
| Thin
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"full"'
|
||||||
|
)
|
||||||
|
| Full
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Dock the terminal
|
||||||
|
.description 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"'
|
||||||
|
)
|
||||||
|
| Off
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"top"'
|
||||||
|
)
|
||||||
|
| Top
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"left"'
|
||||||
|
)
|
||||||
|
| Left
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"right"'
|
||||||
|
)
|
||||||
|
| Right
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"bottom"'
|
||||||
|
)
|
||||||
|
| Bottom
|
||||||
|
|
||||||
|
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
||||||
|
.header
|
||||||
|
.title Display on
|
||||||
|
.description 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'
|
||||||
|
)
|
||||||
|
| Current
|
||||||
|
label.btn.btn-secondary(*ngFor='let screen of screens', ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='screen.id'
|
||||||
|
)
|
||||||
|
| {{screen.name}}
|
||||||
|
|
||||||
|
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
||||||
|
.header
|
||||||
|
.title Dock always on top
|
||||||
|
.description Keep docked terminal always on top
|
||||||
|
toggle(
|
||||||
|
[(ngModel)]='config.store.appearance.dockAlwaysOnTop',
|
||||||
|
(ngModelChange)='saveConfiguration(); docking.dock()',
|
||||||
|
)
|
||||||
|
|
||||||
|
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
||||||
|
.header
|
||||||
|
.title Docked terminal size
|
||||||
|
input(
|
||||||
|
type='range',
|
||||||
|
[(ngModel)]='config.store.appearance.dockFill',
|
||||||
|
(mouseup)='saveConfiguration(); docking.dock()',
|
||||||
|
min='0.05',
|
||||||
|
max='1',
|
||||||
|
step='0.01'
|
||||||
|
)
|
||||||
|
|
||||||
|
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
||||||
|
.header
|
||||||
|
.title Docked terminal space
|
||||||
|
input(
|
||||||
|
type='range',
|
||||||
|
[(ngModel)]='config.store.appearance.dockSpace',
|
||||||
|
(mouseup)='saveConfiguration(); docking.dock()',
|
||||||
|
min='0.2',
|
||||||
|
max='1',
|
||||||
|
step='0.01'
|
||||||
|
)
|
||||||
|
|
||||||
|
.ml-5.form-line(*ngIf='config.store.appearance.dock != "off"')
|
||||||
|
.header
|
||||||
|
.title Hide dock on blur
|
||||||
|
.description Hides the docked terminal when you click away.
|
||||||
|
toggle(
|
||||||
|
[(ngModel)]='config.store.appearance.dockHideOnBlur',
|
||||||
|
(ngModelChange)='saveConfiguration(); ',
|
||||||
|
)
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Tabs location
|
||||||
|
.btn-group(
|
||||||
|
[(ngModel)]='config.store.appearance.tabsLocation',
|
||||||
|
(ngModelChange)='saveConfiguration()',
|
||||||
|
ngbRadioGroup
|
||||||
|
)
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"top"'
|
||||||
|
)
|
||||||
|
| Top
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"bottom"'
|
||||||
|
)
|
||||||
|
| Bottom
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"left"'
|
||||||
|
)
|
||||||
|
| Left
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"right"'
|
||||||
|
)
|
||||||
|
| Right
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Tabs width
|
||||||
|
.btn-group(
|
||||||
|
[(ngModel)]='config.store.appearance.flexTabs',
|
||||||
|
(ngModelChange)='saveConfiguration()',
|
||||||
|
ngbRadioGroup
|
||||||
|
)
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='true'
|
||||||
|
)
|
||||||
|
| Dynamic
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='false'
|
||||||
|
)
|
||||||
|
| Fixed
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Hide tab index
|
||||||
|
|
||||||
|
toggle(
|
||||||
|
[(ngModel)]='config.store.terminal.hideTabIndex',
|
||||||
|
(ngModelChange)='config.save();',
|
||||||
|
)
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Hide tab close button
|
||||||
|
|
||||||
|
toggle(
|
||||||
|
[(ngModel)]='config.store.terminal.hideCloseButton',
|
||||||
|
(ngModelChange)='config.save();',
|
||||||
|
)
|
@ -0,0 +1,49 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
import { debounce } from 'utils-decorators/dist/cjs'
|
||||||
|
import { Component, Inject, NgZone } from '@angular/core'
|
||||||
|
import {
|
||||||
|
DockingService,
|
||||||
|
ConfigService,
|
||||||
|
Theme,
|
||||||
|
HostAppService,
|
||||||
|
Platform,
|
||||||
|
isWindowsBuild,
|
||||||
|
WIN_BUILD_FLUENT_BG_SUPPORTED,
|
||||||
|
} from 'terminus-core'
|
||||||
|
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Component({
|
||||||
|
selector: 'window-settings-tab',
|
||||||
|
template: require('./windowSettingsTab.component.pug'),
|
||||||
|
})
|
||||||
|
export class WindowSettingsTabComponent {
|
||||||
|
screens: any[]
|
||||||
|
Platform = Platform
|
||||||
|
isFluentVibrancySupported = false
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
public config: ConfigService,
|
||||||
|
public docking: DockingService,
|
||||||
|
public hostApp: HostAppService,
|
||||||
|
public zone: NgZone,
|
||||||
|
@Inject(Theme) public themes: Theme[],
|
||||||
|
) {
|
||||||
|
this.screens = this.docking.getScreens()
|
||||||
|
this.themes = config.enabledServices(this.themes)
|
||||||
|
|
||||||
|
hostApp.displaysChanged$.subscribe(() => {
|
||||||
|
this.zone.run(() => this.screens = this.docking.getScreens())
|
||||||
|
})
|
||||||
|
|
||||||
|
this.isFluentVibrancySupported = isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)
|
||||||
|
}
|
||||||
|
|
||||||
|
@debounce(500)
|
||||||
|
saveConfiguration (requireRestart?: boolean) {
|
||||||
|
this.config.save()
|
||||||
|
if (requireRestart) {
|
||||||
|
this.config.requestRestart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,13 +6,17 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
|||||||
import TerminusCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider } from 'terminus-core'
|
import TerminusCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider } from 'terminus-core'
|
||||||
|
|
||||||
import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component'
|
import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component'
|
||||||
|
import { HotkeySettingsTabComponent } from './components/hotkeySettingsTab.component'
|
||||||
import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.component'
|
import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.component'
|
||||||
import { SettingsTabComponent } from './components/settingsTab.component'
|
import { SettingsTabComponent } from './components/settingsTab.component'
|
||||||
import { SettingsTabBodyComponent } from './components/settingsTabBody.component'
|
import { SettingsTabBodyComponent } from './components/settingsTabBody.component'
|
||||||
|
import { WindowSettingsTabComponent } from './components/windowSettingsTab.component'
|
||||||
|
|
||||||
|
import { SettingsTabProvider } from './api'
|
||||||
import { ButtonProvider } from './buttonProvider'
|
import { ButtonProvider } from './buttonProvider'
|
||||||
import { SettingsHotkeyProvider } from './hotkeys'
|
import { SettingsHotkeyProvider } from './hotkeys'
|
||||||
import { SettingsConfigProvider } from './config'
|
import { SettingsConfigProvider } from './config'
|
||||||
|
import { HotkeySettingsTabProvider, WindowSettingsTabProvider } from './settings'
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -26,16 +30,22 @@ import { SettingsConfigProvider } from './config'
|
|||||||
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
||||||
{ provide: ConfigProvider, useClass: SettingsConfigProvider, multi: true },
|
{ provide: ConfigProvider, useClass: SettingsConfigProvider, multi: true },
|
||||||
{ provide: HotkeyProvider, useClass: SettingsHotkeyProvider, multi: true },
|
{ provide: HotkeyProvider, useClass: SettingsHotkeyProvider, multi: true },
|
||||||
|
{ provide: SettingsTabProvider, useClass: HotkeySettingsTabProvider, multi: true },
|
||||||
|
{ provide: SettingsTabProvider, useClass: WindowSettingsTabProvider, multi: true },
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
HotkeyInputModalComponent,
|
HotkeyInputModalComponent,
|
||||||
|
HotkeySettingsTabComponent,
|
||||||
SettingsTabComponent,
|
SettingsTabComponent,
|
||||||
|
WindowSettingsTabComponent,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
HotkeyInputModalComponent,
|
HotkeyInputModalComponent,
|
||||||
|
HotkeySettingsTabComponent,
|
||||||
MultiHotkeyInputComponent,
|
MultiHotkeyInputComponent,
|
||||||
SettingsTabComponent,
|
SettingsTabComponent,
|
||||||
SettingsTabBodyComponent,
|
SettingsTabBodyComponent,
|
||||||
|
WindowSettingsTabComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export default class SettingsModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
|
export default class SettingsModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||||
|
29
terminus-settings/src/settings.ts
Normal file
29
terminus-settings/src/settings.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
import { SettingsTabProvider } from './api'
|
||||||
|
import { HotkeySettingsTabComponent } from './components/hotkeySettingsTab.component'
|
||||||
|
import { WindowSettingsTabComponent } from './components/windowSettingsTab.component'
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Injectable()
|
||||||
|
export class HotkeySettingsTabProvider extends SettingsTabProvider {
|
||||||
|
id = 'hotkeys'
|
||||||
|
icon = 'keyboard'
|
||||||
|
title = 'Hotkeys'
|
||||||
|
|
||||||
|
getComponentType (): any {
|
||||||
|
return HotkeySettingsTabComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Injectable()
|
||||||
|
export class WindowSettingsTabProvider extends SettingsTabProvider {
|
||||||
|
id = 'window'
|
||||||
|
icon = 'window-maximize'
|
||||||
|
title = 'Window'
|
||||||
|
|
||||||
|
getComponentType (): any {
|
||||||
|
return WindowSettingsTabComponent
|
||||||
|
}
|
||||||
|
}
|
@ -33,19 +33,6 @@ h3.mb-3 Appearance
|
|||||||
.col-12.col-md-6
|
.col-12.col-md-6
|
||||||
color-scheme-preview([scheme]='config.store.terminal.colorScheme', [fontPreview]='true')
|
color-scheme-preview([scheme]='config.store.terminal.colorScheme', [fontPreview]='true')
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title Frontend
|
|
||||||
.description Switches terminal frontend implementation (experimental)
|
|
||||||
|
|
||||||
select.form-control(
|
|
||||||
[(ngModel)]='config.store.terminal.frontend',
|
|
||||||
(ngModelChange)='config.save()',
|
|
||||||
)
|
|
||||||
option(value='hterm') hterm
|
|
||||||
option(value='xterm') xterm
|
|
||||||
option(value='xterm-webgl') xterm (WebGL)
|
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Terminal background
|
.title Terminal background
|
||||||
@ -110,24 +97,6 @@ h3.mb-3 Appearance
|
|||||||
(ngModelChange)='config.save()',
|
(ngModelChange)='config.save()',
|
||||||
)
|
)
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title Hide tab index
|
|
||||||
|
|
||||||
toggle(
|
|
||||||
[(ngModel)]='config.store.terminal.hideTabIndex',
|
|
||||||
(ngModelChange)='config.save();',
|
|
||||||
)
|
|
||||||
|
|
||||||
.form-line
|
|
||||||
.header
|
|
||||||
.title Hide tab close button
|
|
||||||
|
|
||||||
toggle(
|
|
||||||
[(ngModel)]='config.store.terminal.hideCloseButton',
|
|
||||||
(ngModelChange)='config.save();',
|
|
||||||
)
|
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Fallback font
|
.title Fallback font
|
||||||
@ -139,3 +108,13 @@ h3.mb-3 Appearance
|
|||||||
[(ngModel)]='config.store.terminal.fallbackFont',
|
[(ngModel)]='config.store.terminal.fallbackFont',
|
||||||
(ngModelChange)='config.save()'
|
(ngModelChange)='config.save()'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Custom CSS
|
||||||
|
|
||||||
|
textarea.form-control(
|
||||||
|
[(ngModel)]='config.store.appearance.css',
|
||||||
|
(ngModelChange)='saveConfiguration()',
|
||||||
|
)
|
||||||
|
@ -2,3 +2,8 @@ color-scheme-preview {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
font-family: 'Source Code Pro', monospace;
|
||||||
|
min-height: 120px;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,18 @@
|
|||||||
h3.mb-3 Terminal
|
h3.mb-3 Terminal
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Frontend
|
||||||
|
.description Switches terminal frontend implementation (experimental)
|
||||||
|
|
||||||
|
select.form-control(
|
||||||
|
[(ngModel)]='config.store.terminal.frontend',
|
||||||
|
(ngModelChange)='config.save()',
|
||||||
|
)
|
||||||
|
option(value='hterm') hterm
|
||||||
|
option(value='xterm') xterm
|
||||||
|
option(value='xterm-webgl') xterm (WebGL)
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Terminal bell
|
.title Terminal bell
|
||||||
|
Loading…
x
Reference in New Issue
Block a user