mirror of
https://github.com/Eugeny/tabby.git
synced 2025-10-04 22:14:55 +00:00
color scheme previews (fixes #2286)
This commit is contained in:
@@ -262,6 +262,29 @@ ngb-tabset .tab-content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.list-group-light {
|
||||||
|
.list-group-item {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, .1);
|
||||||
|
|
||||||
|
&:not(.combi) {
|
||||||
|
padding: $list-group-item-padding-y $list-group-item-padding-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.list-group-item-action {
|
||||||
|
&:hover, &.active {
|
||||||
|
background: $list-group-hover-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkbox i.on {
|
checkbox i.on {
|
||||||
color: $blue;
|
color: $blue;
|
||||||
}
|
}
|
||||||
@@ -392,3 +415,7 @@ search-panel {
|
|||||||
border-color: $nav-tabs-link-active-border-color;
|
border-color: $nav-tabs-link-active-border-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-color: $list-group-border-color;
|
||||||
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
h3.mb-3 Appearance
|
h3.mb-3 Appearance
|
||||||
.d-flex
|
.d-flex
|
||||||
.mr-5
|
.mr-5.w-100
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Font
|
.title Font
|
||||||
@@ -27,148 +27,7 @@ h3.mb-3 Appearance
|
|||||||
(ngModelChange)='config.save()',
|
(ngModelChange)='config.save()',
|
||||||
)
|
)
|
||||||
|
|
||||||
.form-line(*ngIf='!editingColorScheme')
|
color-scheme-preview([scheme]='config.store.terminal.colorScheme', [fontPreview]='true')
|
||||||
.header
|
|
||||||
.title Color scheme
|
|
||||||
|
|
||||||
.input-group.w-50
|
|
||||||
select.form-control(
|
|
||||||
[compareWith]='equalComparator',
|
|
||||||
[(ngModel)]='config.store.terminal.colorScheme',
|
|
||||||
(ngModelChange)='config.save()',
|
|
||||||
)
|
|
||||||
option(*ngFor='let scheme of config.store.terminal.customColorSchemes', [ngValue]='scheme') Custom: {{scheme.name}}
|
|
||||||
option(*ngFor='let scheme of colorSchemes', [ngValue]='scheme') {{scheme.name}}
|
|
||||||
.input-group-append
|
|
||||||
button.btn.btn-secondary((click)='editScheme(config.store.terminal.colorScheme)')
|
|
||||||
i.fas.fa-pen
|
|
||||||
.input-group-append
|
|
||||||
button.btn.btn-outline-danger(
|
|
||||||
(click)='deleteScheme(config.store.terminal.colorScheme)',
|
|
||||||
*ngIf='isCustomScheme(config.store.terminal.colorScheme)'
|
|
||||||
)
|
|
||||||
i.fas.fa-trash
|
|
||||||
|
|
||||||
.form-group(*ngIf='editingColorScheme')
|
|
||||||
label Editing
|
|
||||||
.input-group
|
|
||||||
input.form-control(type='text', [(ngModel)]='editingColorScheme.name')
|
|
||||||
.input-group-append
|
|
||||||
button.btn.btn-secondary((click)='saveScheme()')
|
|
||||||
i.fas.fa-check
|
|
||||||
.input-group-append
|
|
||||||
button.btn.btn-secondary((click)='cancelEditing()')
|
|
||||||
i.fas.fa-times
|
|
||||||
|
|
||||||
.form-group(*ngIf='editingColorScheme')
|
|
||||||
color-picker(
|
|
||||||
[(model)]='editingColorScheme.foreground',
|
|
||||||
(modelChange)='config.save(); schemeChanged = true',
|
|
||||||
title='FG',
|
|
||||||
)
|
|
||||||
color-picker(
|
|
||||||
[(model)]='editingColorScheme.background',
|
|
||||||
(modelChange)='config.save(); schemeChanged = true',
|
|
||||||
title='BG',
|
|
||||||
)
|
|
||||||
color-picker(
|
|
||||||
[(model)]='editingColorScheme.cursor',
|
|
||||||
(modelChange)='config.save(); schemeChanged = true',
|
|
||||||
title='CU',
|
|
||||||
)
|
|
||||||
color-picker(
|
|
||||||
*ngFor='let _ of editingColorScheme.colors; let idx = index; trackBy: colorsTrackBy',
|
|
||||||
[(model)]='editingColorScheme.colors[idx]',
|
|
||||||
(modelChange)='config.save(); schemeChanged = true',
|
|
||||||
[title]='idx',
|
|
||||||
)
|
|
||||||
|
|
||||||
div
|
|
||||||
.form-group
|
|
||||||
.appearance-preview(
|
|
||||||
[style.font-family]='getPreviewFontFamily()',
|
|
||||||
[style.font-size]='config.store.terminal.fontSize + "px"',
|
|
||||||
[style.background-color]='(config.store.terminal.background == "theme") ? null : config.store.terminal.colorScheme.background',
|
|
||||||
[style.color]='config.store.terminal.colorScheme.foreground',
|
|
||||||
[style.font-feature-settings]='\'"liga" \' + config.store.terminal.ligatures ? 1 : 0',
|
|
||||||
[style.font-variant-ligatures]='config.store.terminal.ligatures ? "initial" : "none"',
|
|
||||||
)
|
|
||||||
div
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[0]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[1]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[2]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[3]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[4]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[5]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[6]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[7]')
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[0]') B
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[1]') R
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[2]') G
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[3]') Y
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[4]') B
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[5]') M
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[6]') T
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[7]') W
|
|
||||||
div
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[8]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[9]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[10]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[11]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[12]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[13]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[14]')
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.colors[15]')
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[8]') B
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[9]') R
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[10]') G
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[11]') Y
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[12]') B
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[13]') M
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[14]') T
|
|
||||||
span
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[15]') W
|
|
||||||
div
|
|
||||||
span
|
|
||||||
div
|
|
||||||
span john@doe-pc
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[1]') $
|
|
||||||
span ls -l
|
|
||||||
div
|
|
||||||
span drwxr-xr-x 1 root
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[4]') directory 📁
|
|
||||||
div
|
|
||||||
span -rw-r--r-- 1 root файл
|
|
||||||
div
|
|
||||||
span -rwxr-xr-x 1 root
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[2]') 実行可能ファイル
|
|
||||||
div
|
|
||||||
span -rwxr-xr-x 1 root
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[6]') sym
|
|
||||||
span ->
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[1]') link
|
|
||||||
div
|
|
||||||
span
|
|
||||||
div
|
|
||||||
span john@doe-pc
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[1]') $
|
|
||||||
span rm -rf /
|
|
||||||
span([style.background-color]='config.store.terminal.colorScheme.cursor')
|
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
|
@@ -1,12 +1,4 @@
|
|||||||
.appearance-preview {
|
color-scheme-preview {
|
||||||
padding: 10px 0;
|
flex-shrink: 0;
|
||||||
margin-left: 20px;
|
margin-bottom: 20px;
|
||||||
padding: 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
max-width: 400px;
|
|
||||||
max-height: 400px;
|
|
||||||
|
|
||||||
span {
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -2,13 +2,10 @@
|
|||||||
import { Observable } from 'rxjs'
|
import { Observable } from 'rxjs'
|
||||||
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
|
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
|
||||||
import { exec } from 'mz/child_process'
|
import { exec } from 'mz/child_process'
|
||||||
import deepEqual from 'deep-equal'
|
|
||||||
const fontManager = require('fontmanager-redux') // eslint-disable-line
|
const fontManager = require('fontmanager-redux') // eslint-disable-line
|
||||||
|
|
||||||
import { Component, Inject } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ConfigService, HostAppService, Platform, ElectronService, getCSSFontFamily } from 'terminus-core'
|
import { ConfigService, HostAppService, Platform, getCSSFontFamily } from 'terminus-core'
|
||||||
import { TerminalColorSchemeProvider } from '../api/colorSchemeProvider'
|
|
||||||
import { TerminalColorScheme } from '../api/interfaces'
|
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Component({
|
@Component({
|
||||||
@@ -17,15 +14,9 @@ import { TerminalColorScheme } from '../api/interfaces'
|
|||||||
})
|
})
|
||||||
export class AppearanceSettingsTabComponent {
|
export class AppearanceSettingsTabComponent {
|
||||||
fonts: string[] = []
|
fonts: string[] = []
|
||||||
colorSchemes: TerminalColorScheme[] = []
|
|
||||||
equalComparator = deepEqual
|
|
||||||
editingColorScheme: TerminalColorScheme|null = null
|
|
||||||
schemeChanged = false
|
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
@Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[],
|
|
||||||
private hostApp: HostAppService,
|
private hostApp: HostAppService,
|
||||||
private electron: ElectronService,
|
|
||||||
public config: ConfigService,
|
public config: ConfigService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@@ -49,7 +40,6 @@ export class AppearanceSettingsTabComponent {
|
|||||||
this.fonts.sort()
|
this.fonts.sort()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.colorSchemes = (await Promise.all(this.config.enabledServices(this.colorSchemeProviders).map(x => x.getSchemes()))).reduce((a, b) => a.concat(b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fontAutocomplete = (text$: Observable<string>) => {
|
fontAutocomplete = (text$: Observable<string>) => {
|
||||||
@@ -61,49 +51,6 @@ export class AppearanceSettingsTabComponent {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
editScheme (scheme: TerminalColorScheme) {
|
|
||||||
this.editingColorScheme = scheme
|
|
||||||
this.schemeChanged = false
|
|
||||||
}
|
|
||||||
|
|
||||||
saveScheme () {
|
|
||||||
let schemes = this.config.store.terminal.customColorSchemes
|
|
||||||
schemes = schemes.filter(x => x !== this.editingColorScheme && x.name !== this.editingColorScheme!.name)
|
|
||||||
schemes.push(this.editingColorScheme)
|
|
||||||
this.config.store.terminal.customColorSchemes = schemes
|
|
||||||
this.config.save()
|
|
||||||
this.cancelEditing()
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelEditing () {
|
|
||||||
this.editingColorScheme = null
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteScheme (scheme: TerminalColorScheme) {
|
|
||||||
if ((await this.electron.showMessageBox(
|
|
||||||
this.hostApp.getWindow(),
|
|
||||||
{
|
|
||||||
type: 'warning',
|
|
||||||
message: `Delete "${scheme.name}"?`,
|
|
||||||
buttons: ['Keep', 'Delete'],
|
|
||||||
defaultId: 1,
|
|
||||||
}
|
|
||||||
)).response === 1) {
|
|
||||||
let schemes = this.config.store.terminal.customColorSchemes
|
|
||||||
schemes = schemes.filter(x => x !== scheme)
|
|
||||||
this.config.store.terminal.customColorSchemes = schemes
|
|
||||||
this.config.save()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isCustomScheme (scheme: TerminalColorScheme) {
|
|
||||||
return this.config.store.terminal.customColorSchemes.some(x => deepEqual(x, scheme))
|
|
||||||
}
|
|
||||||
|
|
||||||
colorsTrackBy (index) {
|
|
||||||
return index
|
|
||||||
}
|
|
||||||
|
|
||||||
getPreviewFontFamily () {
|
getPreviewFontFamily () {
|
||||||
return getCSSFontFamily(this.config.store)
|
return getCSSFontFamily(this.config.store)
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ div(
|
|||||||
[ngbPopover]='content',
|
[ngbPopover]='content',
|
||||||
[style.background]='model',
|
[style.background]='model',
|
||||||
(click)='open()',
|
(click)='open()',
|
||||||
|
autoClose='outside',
|
||||||
container='body',
|
container='body',
|
||||||
#popover='ngbPopover',
|
#popover='ngbPopover',
|
||||||
) {{ title }}
|
) {{ title }}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, Output, EventEmitter, HostListener, ViewChild } from '@angular/core'
|
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core'
|
||||||
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@@ -12,34 +12,14 @@ export class ColorPickerComponent {
|
|||||||
@Input() title: string
|
@Input() title: string
|
||||||
@Output() modelChange = new EventEmitter<string>()
|
@Output() modelChange = new EventEmitter<string>()
|
||||||
@ViewChild('popover') popover: NgbPopover
|
@ViewChild('popover') popover: NgbPopover
|
||||||
@ViewChild('input') input
|
|
||||||
isOpen: boolean
|
|
||||||
|
|
||||||
open (): void {
|
open (): void {
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.popover.open()
|
this.popover.open()
|
||||||
setImmediate(() => {
|
this.popover['_windowRef'].location.nativeElement.querySelector('input').focus()
|
||||||
this.input.nativeElement.focus()
|
|
||||||
this.isOpen = true
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('document:click', ['$event']) onOutsideClick ($event: MouseEvent): void {
|
|
||||||
if (!this.isOpen) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const windowRef = (this.popover as any)._windowRef
|
|
||||||
if (!windowRef) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ($event.target !== windowRef.location.nativeElement &&
|
|
||||||
!windowRef.location.nativeElement.contains($event.target)) {
|
|
||||||
this.popover.close()
|
|
||||||
this.isOpen = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange (): void {
|
onChange (): void {
|
||||||
this.modelChange.emit(this.model)
|
this.modelChange.emit(this.model)
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,35 @@
|
|||||||
|
.preview(
|
||||||
|
[style.font-family]='getPreviewFontFamily()',
|
||||||
|
[style.font-size]='(fontPreview ? config.store.terminal.fontSize : 11) + "px"',
|
||||||
|
[style.background-color]='scheme.background',
|
||||||
|
[style.color]='scheme.foreground',
|
||||||
|
[style.font-feature-settings]='\'"liga" \' + config.store.terminal.ligatures ? 1 : 0',
|
||||||
|
[style.font-variant-ligatures]='config.store.terminal.ligatures ? "initial" : "none"',
|
||||||
|
)
|
||||||
|
div
|
||||||
|
span([style.color]='scheme.colors[2]') john
|
||||||
|
span([style.color]='scheme.colors[6]') @
|
||||||
|
span([style.color]='scheme.colors[4]') doe-pc
|
||||||
|
strong([style.color]='scheme.colors[1]') $
|
||||||
|
span ls
|
||||||
|
span([style.background-color]='scheme.cursor')
|
||||||
|
div
|
||||||
|
span -rwxr-xr-x 1 root
|
||||||
|
strong([style.color]='scheme.colors[3]') Documents
|
||||||
|
div
|
||||||
|
span -rwxr-xr-x 1 root
|
||||||
|
strong([style.color]='scheme.colors[5]') Downloads
|
||||||
|
div
|
||||||
|
span -rwxr-xr-x 1 root
|
||||||
|
strong([style.color]='scheme.colors[13]') Pictures
|
||||||
|
div
|
||||||
|
span -rwxr-xr-x 1 root
|
||||||
|
strong([style.color]='scheme.colors[12]') Music
|
||||||
|
div(*ngIf='fontPreview')
|
||||||
|
span -rwxr-xr-x 1 root
|
||||||
|
span([style.color]='scheme.colors[2]') 実行可能ファイル
|
||||||
|
div(*ngIf='fontPreview')
|
||||||
|
span -rwxr-xr-x 1 root
|
||||||
|
span([style.color]='scheme.colors[6]') sym
|
||||||
|
span ->
|
||||||
|
span([style.color]='scheme.colors[1]') link
|
@@ -0,0 +1,15 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
import { Component, Input, ChangeDetectionStrategy } from '@angular/core'
|
||||||
|
import { ConfigService, getCSSFontFamily } from 'terminus-core'
|
||||||
|
import { TerminalColorScheme } from '../api/interfaces'
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Component({
|
||||||
|
selector: 'color-scheme-preview',
|
||||||
|
template: require('./colorSchemePreview.component.pug'),
|
||||||
|
styles: [require('./colorSchemePreview.component.scss')],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ColorSchemePreviewComponent {
|
||||||
|
@Input() scheme: TerminalColorScheme
|
||||||
|
@Input() fontPreview = false
|
||||||
|
|
||||||
|
constructor (public config: ConfigService) {}
|
||||||
|
|
||||||
|
getPreviewFontFamily (): string {
|
||||||
|
return getCSSFontFamily(this.config.store)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,96 @@
|
|||||||
|
.head
|
||||||
|
h3.mb-3 Current color scheme
|
||||||
|
|
||||||
|
.d-flex.align-items-center(*ngIf='!editing')
|
||||||
|
span {{getCurrentSchemeName()}}
|
||||||
|
.mr-auto
|
||||||
|
.btn-toolbar
|
||||||
|
button.btn.btn-secondary((click)='editScheme()')
|
||||||
|
i.fas.fa-pen
|
||||||
|
span Edit
|
||||||
|
.mr-1
|
||||||
|
button.btn.btn-danger(
|
||||||
|
(click)='deleteScheme(config.store.terminal.colorScheme)',
|
||||||
|
*ngIf='currentCustomScheme'
|
||||||
|
)
|
||||||
|
i.fas.fa-trash
|
||||||
|
span Delete
|
||||||
|
|
||||||
|
div(*ngIf='editing')
|
||||||
|
.form-group
|
||||||
|
label Name
|
||||||
|
input.form-control(type='text', [(ngModel)]='config.store.terminal.colorScheme.name')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
color-picker(
|
||||||
|
[(model)]='config.store.terminal.colorScheme.foreground',
|
||||||
|
(modelChange)='config.save()',
|
||||||
|
title='FG',
|
||||||
|
)
|
||||||
|
color-picker(
|
||||||
|
[(model)]='config.store.terminal.colorScheme.background',
|
||||||
|
(modelChange)='config.save()',
|
||||||
|
title='BG',
|
||||||
|
)
|
||||||
|
color-picker(
|
||||||
|
[(model)]='config.store.terminal.colorScheme.cursor',
|
||||||
|
(modelChange)='config.save()',
|
||||||
|
title='CU',
|
||||||
|
)
|
||||||
|
color-picker(
|
||||||
|
*ngFor='let _ of config.store.terminal.colorScheme.colors; let idx = index; trackBy: colorsTrackBy',
|
||||||
|
[(model)]='config.store.terminal.colorScheme.colors[idx]',
|
||||||
|
(modelChange)='config.save()',
|
||||||
|
[title]='idx',
|
||||||
|
)
|
||||||
|
|
||||||
|
color-scheme-preview([scheme]='config.store.terminal.colorScheme')
|
||||||
|
|
||||||
|
.btn-toolbar.d-flex.mt-2(*ngIf='editing')
|
||||||
|
.mr-auto
|
||||||
|
button.btn.btn-primary((click)='saveScheme()')
|
||||||
|
i.fas.fa-check
|
||||||
|
span Save
|
||||||
|
.mr-1
|
||||||
|
button.btn.btn-secondary((click)='cancelEditing()')
|
||||||
|
i.fas.fa-times
|
||||||
|
span Cancel
|
||||||
|
|
||||||
|
hr.mt-3.mb-4
|
||||||
|
|
||||||
|
.input-group.mb-3
|
||||||
|
.input-group-prepend
|
||||||
|
.input-group-text
|
||||||
|
i.fas.fa-fw.fa-search
|
||||||
|
input.form-control(type='search', placeholder='Search color schemes', [(ngModel)]='filter')
|
||||||
|
|
||||||
|
.body
|
||||||
|
.list-group-light.mb-3
|
||||||
|
ng-container(*ngFor='let scheme of allColorSchemes')
|
||||||
|
.list-group-item.list-group-item-action(
|
||||||
|
[hidden]='filter && !scheme.name.toLowerCase().includes(filter.toLowerCase())',
|
||||||
|
(click)='selectScheme(scheme)',
|
||||||
|
[class.active]='(currentCustomScheme || currentStockScheme) === scheme'
|
||||||
|
)
|
||||||
|
.d-flex.w-100.align-items-center
|
||||||
|
i.fas.fa-fw([class.fa-check]='(currentCustomScheme || currentStockScheme) === scheme')
|
||||||
|
|
||||||
|
.ml-2
|
||||||
|
|
||||||
|
.mr-auto
|
||||||
|
span {{scheme.name}}
|
||||||
|
.badge.badge-info.ml-2(*ngIf='customColorSchemes.includes(scheme)') Custom
|
||||||
|
|
||||||
|
div
|
||||||
|
.d-flex
|
||||||
|
.swatch(
|
||||||
|
*ngFor='let index of colorIndexes.slice(0, 8)',
|
||||||
|
[style.background-color]='scheme.colors[index]'
|
||||||
|
)
|
||||||
|
.d-flex
|
||||||
|
.swatch(
|
||||||
|
*ngFor='let index of colorIndexes.slice(8, 16)',
|
||||||
|
[style.background-color]='scheme.colors[index]'
|
||||||
|
)
|
||||||
|
|
||||||
|
color-scheme-preview([scheme]='scheme')
|
@@ -0,0 +1,22 @@
|
|||||||
|
.head {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
overflow: auto;
|
||||||
|
flex: auto;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swatch {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 3px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item color-scheme-preview {
|
||||||
|
margin-left: 14px;
|
||||||
|
}
|
@@ -0,0 +1,106 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
import deepEqual from 'deep-equal'
|
||||||
|
|
||||||
|
import { Component, Inject, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'
|
||||||
|
import { ConfigService, HostAppService, ElectronService } from 'terminus-core'
|
||||||
|
import { TerminalColorSchemeProvider } from '../api/colorSchemeProvider'
|
||||||
|
import { TerminalColorScheme } from '../api/interfaces'
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Component({
|
||||||
|
template: require('./colorSchemeSettingsTab.component.pug'),
|
||||||
|
styles: [require('./colorSchemeSettingsTab.component.scss')],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ColorSchemeSettingsTabComponent {
|
||||||
|
@Input() stockColorSchemes: TerminalColorScheme[] = []
|
||||||
|
@Input() customColorSchemes: TerminalColorScheme[] = []
|
||||||
|
@Input() allColorSchemes: TerminalColorScheme[] = []
|
||||||
|
@Input() filter = ''
|
||||||
|
@Input() editing = false
|
||||||
|
colorIndexes = [...new Array(16).keys()]
|
||||||
|
|
||||||
|
currentStockScheme: TerminalColorScheme|null = null
|
||||||
|
currentCustomScheme: TerminalColorScheme|null = null
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
@Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[],
|
||||||
|
private changeDetector: ChangeDetectorRef,
|
||||||
|
private hostApp: HostAppService,
|
||||||
|
private electron: ElectronService,
|
||||||
|
public config: ConfigService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
async ngOnInit () {
|
||||||
|
this.stockColorSchemes = (await Promise.all(this.config.enabledServices(this.colorSchemeProviders).map(x => x.getSchemes()))).reduce((a, b) => a.concat(b))
|
||||||
|
this.stockColorSchemes.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
this.customColorSchemes = this.config.store.terminal.customColorSchemes
|
||||||
|
this.changeDetector.markForCheck()
|
||||||
|
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges () {
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
selectScheme (scheme: TerminalColorScheme) {
|
||||||
|
this.config.store.terminal.colorScheme = { ...scheme }
|
||||||
|
this.config.save()
|
||||||
|
this.cancelEditing()
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
update () {
|
||||||
|
this.currentCustomScheme = this.findMatchingScheme(this.config.store.terminal.colorScheme, this.customColorSchemes)
|
||||||
|
this.currentStockScheme = this.findMatchingScheme(this.config.store.terminal.colorScheme, this.stockColorSchemes)
|
||||||
|
this.allColorSchemes = this.customColorSchemes.concat(this.stockColorSchemes)
|
||||||
|
this.changeDetector.markForCheck()
|
||||||
|
}
|
||||||
|
|
||||||
|
editScheme () {
|
||||||
|
this.editing = true
|
||||||
|
}
|
||||||
|
|
||||||
|
saveScheme () {
|
||||||
|
this.customColorSchemes = this.customColorSchemes.filter(x => x.name !== this.config.store.terminal.colorScheme.name)
|
||||||
|
this.customColorSchemes.push(this.config.store.terminal.colorScheme)
|
||||||
|
this.config.store.terminal.customColorSchemes = this.customColorSchemes
|
||||||
|
this.config.save()
|
||||||
|
this.cancelEditing()
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelEditing () {
|
||||||
|
this.editing = false
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteScheme (scheme: TerminalColorScheme) {
|
||||||
|
if ((await this.electron.showMessageBox(
|
||||||
|
this.hostApp.getWindow(),
|
||||||
|
{
|
||||||
|
type: 'warning',
|
||||||
|
message: `Delete "${scheme.name}"?`,
|
||||||
|
buttons: ['Keep', 'Delete'],
|
||||||
|
defaultId: 1,
|
||||||
|
}
|
||||||
|
)).response === 1) {
|
||||||
|
this.customColorSchemes = this.customColorSchemes.filter(x => x.name !== scheme.name)
|
||||||
|
this.config.store.terminal.customColorSchemes = this.customColorSchemes
|
||||||
|
this.config.save()
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentSchemeName () {
|
||||||
|
return (this.currentCustomScheme || this.currentStockScheme)?.name || 'Custom'
|
||||||
|
}
|
||||||
|
|
||||||
|
findMatchingScheme (scheme: TerminalColorScheme, schemes: TerminalColorScheme[]) {
|
||||||
|
return schemes.find(x => deepEqual(x, scheme)) || null
|
||||||
|
}
|
||||||
|
|
||||||
|
colorsTrackBy (index) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
@@ -11,10 +11,12 @@ import TerminusCorePlugin, { HostAppService, ToolbarButtonProvider, TabRecoveryP
|
|||||||
import { SettingsTabProvider } from 'terminus-settings'
|
import { SettingsTabProvider } from 'terminus-settings'
|
||||||
|
|
||||||
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
|
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
|
||||||
|
import { ColorSchemeSettingsTabComponent } from './components/colorSchemeSettingsTab.component'
|
||||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||||
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
|
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
|
||||||
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
|
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
|
||||||
import { ColorPickerComponent } from './components/colorPicker.component'
|
import { ColorPickerComponent } from './components/colorPicker.component'
|
||||||
|
import { ColorSchemePreviewComponent } from './components/colorSchemePreview.component'
|
||||||
import { EditProfileModalComponent } from './components/editProfileModal.component'
|
import { EditProfileModalComponent } from './components/editProfileModal.component'
|
||||||
import { EnvironmentEditorComponent } from './components/environmentEditor.component'
|
import { EnvironmentEditorComponent } from './components/environmentEditor.component'
|
||||||
import { SearchPanelComponent } from './components/searchPanel.component'
|
import { SearchPanelComponent } from './components/searchPanel.component'
|
||||||
@@ -30,7 +32,7 @@ import { TerminalDecorator } from './api/decorator'
|
|||||||
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
|
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
|
||||||
import { TerminalColorSchemeProvider } from './api/colorSchemeProvider'
|
import { TerminalColorSchemeProvider } from './api/colorSchemeProvider'
|
||||||
import { ShellProvider } from './api/shellProvider'
|
import { ShellProvider } from './api/shellProvider'
|
||||||
import { TerminalSettingsTabProvider, AppearanceSettingsTabProvider, ShellSettingsTabProvider } from './settings'
|
import { TerminalSettingsTabProvider, AppearanceSettingsTabProvider, ColorSchemeSettingsTabProvider, ShellSettingsTabProvider } from './settings'
|
||||||
import { DebugDecorator } from './features/debug'
|
import { DebugDecorator } from './features/debug'
|
||||||
import { PathDropDecorator } from './features/pathDrop'
|
import { PathDropDecorator } from './features/pathDrop'
|
||||||
import { ZModemDecorator } from './features/zmodem'
|
import { ZModemDecorator } from './features/zmodem'
|
||||||
@@ -68,6 +70,7 @@ import { XTermFrontend, XTermWebGLFrontend } from './frontends/xtermFrontend'
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: SettingsTabProvider, useClass: AppearanceSettingsTabProvider, multi: true },
|
{ provide: SettingsTabProvider, useClass: AppearanceSettingsTabProvider, multi: true },
|
||||||
|
{ provide: SettingsTabProvider, useClass: ColorSchemeSettingsTabProvider, multi: true },
|
||||||
{ provide: SettingsTabProvider, useClass: ShellSettingsTabProvider, multi: true },
|
{ provide: SettingsTabProvider, useClass: ShellSettingsTabProvider, multi: true },
|
||||||
{ provide: SettingsTabProvider, useClass: TerminalSettingsTabProvider, multi: true },
|
{ provide: SettingsTabProvider, useClass: TerminalSettingsTabProvider, multi: true },
|
||||||
|
|
||||||
@@ -106,14 +109,17 @@ import { XTermFrontend, XTermWebGLFrontend } from './frontends/xtermFrontend'
|
|||||||
entryComponents: [
|
entryComponents: [
|
||||||
TerminalTabComponent,
|
TerminalTabComponent,
|
||||||
AppearanceSettingsTabComponent,
|
AppearanceSettingsTabComponent,
|
||||||
|
ColorSchemeSettingsTabComponent,
|
||||||
ShellSettingsTabComponent,
|
ShellSettingsTabComponent,
|
||||||
TerminalSettingsTabComponent,
|
TerminalSettingsTabComponent,
|
||||||
EditProfileModalComponent,
|
EditProfileModalComponent,
|
||||||
] as any[],
|
] as any[],
|
||||||
declarations: [
|
declarations: [
|
||||||
ColorPickerComponent,
|
ColorPickerComponent,
|
||||||
|
ColorSchemePreviewComponent,
|
||||||
TerminalTabComponent,
|
TerminalTabComponent,
|
||||||
AppearanceSettingsTabComponent,
|
AppearanceSettingsTabComponent,
|
||||||
|
ColorSchemeSettingsTabComponent,
|
||||||
ShellSettingsTabComponent,
|
ShellSettingsTabComponent,
|
||||||
TerminalSettingsTabComponent,
|
TerminalSettingsTabComponent,
|
||||||
EditProfileModalComponent,
|
EditProfileModalComponent,
|
||||||
|
@@ -4,12 +4,13 @@ import { SettingsTabProvider } from 'terminus-settings'
|
|||||||
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
|
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
|
||||||
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
|
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
|
||||||
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
|
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
|
||||||
|
import { ColorSchemeSettingsTabComponent } from './components/colorSchemeSettingsTab.component'
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AppearanceSettingsTabProvider extends SettingsTabProvider {
|
export class AppearanceSettingsTabProvider extends SettingsTabProvider {
|
||||||
id = 'terminal-appearance'
|
id = 'terminal-appearance'
|
||||||
icon = 'palette'
|
icon = 'swatchbook'
|
||||||
title = 'Appearance'
|
title = 'Appearance'
|
||||||
|
|
||||||
getComponentType (): any {
|
getComponentType (): any {
|
||||||
@@ -17,6 +18,18 @@ export class AppearanceSettingsTabProvider extends SettingsTabProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Injectable()
|
||||||
|
export class ColorSchemeSettingsTabProvider extends SettingsTabProvider {
|
||||||
|
id = 'terminal-color-scheme'
|
||||||
|
icon = 'palette'
|
||||||
|
title = 'Color Scheme'
|
||||||
|
|
||||||
|
getComponentType (): any {
|
||||||
|
return ColorSchemeSettingsTabComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ShellSettingsTabProvider extends SettingsTabProvider {
|
export class ShellSettingsTabProvider extends SettingsTabProvider {
|
||||||
|
Reference in New Issue
Block a user