This commit is contained in:
Eugene Pankov 2023-02-16 00:45:45 +01:00
parent 4d86850bc7
commit 921214dd09
No known key found for this signature in database
GPG Key ID: 5896FCBBDD1CF4F4
26 changed files with 624 additions and 91 deletions

View File

@ -144,6 +144,5 @@ $tabs-height: 38px;
right: 10px;
bottom: 4px;
height: 2px;
z-index: -1;
}
}

View File

@ -36,8 +36,7 @@ hotkeys:
- '⌘-8'
tab-9:
- '⌘-9'
tab-10:
- '⌘-0'
tab-10: []
duplicate-tab: []
restart-tab: []
explode-tab:

View File

@ -44,7 +44,7 @@ import { HotkeysService } from './services/hotkeys.service'
import { LocaleService, TranslateServiceWrapper } from './services/locale.service'
import { CommandService } from './services/commands.service'
import { StandardTheme, StandardCompactTheme, PaperTheme } from './theme'
import { StandardTheme, StandardCompactTheme, PaperTheme, NewTheme } from './theme'
import { CoreConfigProvider } from './config'
import { AppHotkeyProvider } from './hotkeys'
import { TaskCompletionContextMenu, CommonOptionsContextMenu, TabManagementContextMenu, ProfilesContextMenu } from './tabContextMenu'
@ -61,6 +61,7 @@ const PROVIDERS = [
{ provide: Theme, useClass: StandardTheme, multi: true },
{ provide: Theme, useClass: StandardCompactTheme, multi: true },
{ provide: Theme, useClass: PaperTheme, multi: true },
{ provide: Theme, useClass: NewTheme, multi: true },
{ provide: ConfigProvider, useClass: CoreConfigProvider, multi: true },
{ provide: TabContextMenuItemProvider, useClass: CommonOptionsContextMenu, multi: true },
{ provide: TabContextMenuItemProvider, useClass: TabManagementContextMenu, multi: true },

View File

@ -18,10 +18,34 @@ export class ThemesService {
this.applyTheme(this.findTheme('Standard')!)
config.ready$.toPromise().then(() => {
this.applyCurrentTheme()
this.applyThemeVariables()
config.changed$.subscribe(() => {
this.applyCurrentTheme()
})
})
config.changed$.subscribe(() => this.applyThemeVariables())
}
private applyThemeVariables () {
const theme = this.config.store.terminal.colorScheme
document.documentElement.style.setProperty('--bs-body-bg', this.config.store?.appearance.vibrancy ? 'rgba(255, 255, 255,.4)' : theme.background)
document.documentElement.style.setProperty('--bs-body-color', theme.foreground)
document.documentElement.style.setProperty('--bs-black', theme.colors[0])
document.documentElement.style.setProperty('--bs-blue', theme.colors[1])
document.documentElement.style.setProperty('--bs-green', theme.colors[2])
document.documentElement.style.setProperty('--bs-cyan', theme.colors[3])
document.documentElement.style.setProperty('--bs-red', theme.colors[4])
document.documentElement.style.setProperty('--bs-purple', theme.colors[5])
document.documentElement.style.setProperty('--bs-yellow', theme.colors[6])
document.documentElement.style.setProperty('--bs-gray', theme.colors[7])
document.documentElement.style.setProperty('--bs-gray-dark', theme.colors[8])
// document.documentElement.style.setProperty('--bs-blue', theme.colors[9])
// document.documentElement.style.setProperty('--bs-green', theme.colors[10])
// document.documentElement.style.setProperty('--bs-cyan', theme.colors[11])
// document.documentElement.style.setProperty('--bs-red', theme.colors[12])
// document.documentElement.style.setProperty('--bs-purple', theme.colors[13])
// document.documentElement.style.setProperty('--bs-yellow', theme.colors[14])
document.documentElement.style.setProperty('--bs-white', theme.colors[15])
}
findTheme (name: string): Theme|null {

View File

@ -0,0 +1,499 @@
$font-family-sans-serif: "Source Sans Pro";
$font-size-base: 14rem / 16;
app-root {
background: transparent;
&> .content {
.tab-bar {
background: var(--bs-gray-dark);
.btn-tab-bar {
background: transparent;
line-height: 42px;
align-items: center;
svg, path {
fill: var(--bs-body-color);
fill-opacity: 0.75;
}
&:hover { background: rgba(0, 0, 0, .125) !important; }
&:active { background: rgba(0, 0, 0, .25) !important; }
}
&>.tabs {
tab-header {
border-left: 1px solid transparent;
border-right: 1px solid transparent;
// color: $base01;
transition: 0.125s ease-out width;
.index {
color: var(--bs-body-color);
opacity: 0.4;
}
button {
color: var(--bs-body-color);
border: none;
transition: 0.25s all;
// &:hover { background: $button-hover-bg !important; }
// &:active { background: $button-active-bg !important; }
}
.progressbar {
background: var(--bs-blue);
}
.activity-indicator {
background:var(--bs-body-color);
opacity: .2;
}
&.active {
// color: $black;
background: var(--bs-body-bg);
// border-left: 1px solid $border-color;
// border-right: 1px solid $border-color;
}
}
}
}
// &.tabs-on-top .tab-bar {
// &>.background {
// border-bottom: 1px solid $border-color;
// }
// tab-header {
// border-bottom: 1px solid $border-color;
// &.active {
// border-bottom-color: transparent;
// }
// }
// }
// &:not(.tabs-on-top) .tab-bar {
// &>.background {
// border-top: 1px solid $border-color;
// }
// tab-header {
// border-top: 1px solid $border-color;
// &.active {
// margin-top: -1px;
// }
// }
// }
}
// &.platform-win32, &.platform-linux {
// border: 1px solid #111;
// &>.content .tab-bar .tabs tab-header:first-child {
// border-left: none;
// }
// }
}
tab-body {
background: var(--bs-body-bg);
}
// $black: #002b36;
// $base02: #073642;
// $base01: #586e75;
// $base00: #657b83;
// $base0: #839496;
// $base1: #93a1a1;
// $base2: #eee8d5;
// $white: #fdf6e3;
// $yellow: #b58900;
// $orange: #cb4b16;
// $red: #dc322f;
// $pink: #d33682;
// $purple: #6c71c4;
// $blue: #268bd2;
// $teal: #2aa198;
// $green: #859900;
$tab-border-radius: 5px;
// $button-hover-bg: rgba(0, 0, 0, .125);
// $button-active-bg: rgba(0, 0, 0, .25);
// $btn-border-radius: 0;
// $input-bg: $base2;
// $input-disabled-bg: $base1;
// $input-color: $body-color;
// $input-color-placeholder: $base1;
// $input-border-color: $base1;
// //$input-box-shadow: inset 0 1px 1px rgba($black,.075);
// $input-border-radius: 0;
// $custom-select-border-radius: 0;
// $input-bg-focus: $input-bg;
// //$input-border-focus: lighten($brand-primary, 25%);
// //$input-box-shadow-focus: $input-box-shadow, rgba($input-border-focus, .6);
// $input-color-focus: $input-color;
// $input-group-addon-bg: $body-bg;
// $input-group-addon-border-color: $input-border-color;
// $modal-content-bg: $content-bg-solid;
// $modal-content-border-color: $body-bg;
// $modal-header-border-color: transparent;
// $modal-footer-border-color: transparent;
// $popover-bg: $body-bg;
// $dropdown-bg: $body-bg;
// $dropdown-link-color: $body-color;
// $dropdown-link-hover-color: #333;
// $dropdown-link-hover-bg: $body-bg2;
// //$dropdown-link-active-color: $component-active-color;
// //$dropdown-link-active-bg: $component-active-bg;
// $dropdown-link-disabled-color: #333;
// $dropdown-header-color: #333;
// $list-group-color: $body-color;
// $list-group-bg: rgba($black,.05);
// $list-group-border-color: rgba($black,.1);
// $list-group-hover-bg: rgba($black,.1);
// $list-group-link-active-bg: rgba($black,.2);
// $list-group-action-color: $body-color;
// $list-group-action-bg: rgba($black,.05);
// $list-group-action-active-bg: $list-group-link-active-bg;
// $list-group-border-radius: 0;
// $pre-bg: $dropdown-bg;
// $pre-color: $dropdown-link-color;
// $headings-font-weight: lighter;
// $headings-color: $base0;
@import '~bootstrap/scss/bootstrap.scss';
@import "./theme.vendor.scss";
.nav {
// scss-docs-start nav-css-vars
// --#{$prefix}nav-link-padding-x: #{$nav-link-padding-x};
// --#{$prefix}nav-link-padding-y: #{$nav-link-padding-y};
// @include rfs($nav-link-font-size, --#{$prefix}nav-link-font-size);
// --#{$prefix}nav-link-font-weight: #{$nav-link-font-weight};
--#{$prefix}nav-link-color: var(--bs-body-color);
--#{$prefix}nav-link-hover-color: var(--bs-white);
--#{$prefix}nav-link-disabled-color: var(--bs-gray);
// scss-docs-end nav-css-vars
}
.nav-tabs {
// scss-docs-start nav-tabs-css-vars
--#{$prefix}nav-tabs-border-width: 2px;
--#{$prefix}nav-tabs-border-radius: 0;
--#{$prefix}nav-tabs-link-hover-border-color: var(--bs-body-bg);
--#{$prefix}nav-tabs-border-color: var(--bs-white);
--#{$prefix}nav-tabs-link-active-color: var(--bs-white);
--#{$prefix}nav-tabs-link-active-bg: transparent;
--#{$prefix}nav-tabs-link-active-border-color: transparent;
// scss-docs-end nav-tabs-css-vars
}
.nav-pills {
// scss-docs-start nav-pills-css-vars
--#{$prefix}nav-pills-border-radius: #{$nav-pills-border-radius};
--#{$prefix}nav-pills-link-active-color: #{$nav-pills-link-active-color};
--#{$prefix}nav-pills-link-active-bg: #{$nav-pills-link-active-bg};
// scss-docs-end nav-pills-css-vars
}
.nav-tabs {
margin-bottom: 10px;
border: none;
&.nav-justified .nav-link {
margin-right: 5px;
}
.nav-link {
border: none;
border-bottom: var(--bs-nav-tabs-border-width) solid transparent;
text-transform: uppercase;
font-weight: bold;
padding: 5px 0;
margin-right: 20px;
uib-tab-heading > i {
font-size: 18px;
}
&.disabled {
color: var(--bs-nav-tabs-link-disabled-color);
border-color: transparent;
}
}
.nav-item:last-child .nav-link {
margin-right: 0;
}
.nav-link.active,
.nav-item.show .nav-link {
color: var(--bs-nav-tabs-link-active-color);
border-color: var(--bs-nav-tabs-border-color);
}
}
// tab-body {
// background: $content-bg;
// terminal-toolbar .btn, .toolbar-pin-button {
// font-weight: bold;
// }
// }
// multi-hotkey-input {
// .item {
// background: $body-bg2;
// border: 1px solid $blue;
// border-radius: 3px;
// margin-right: 5px;
// .body {
// padding: 3px 0 2px;
// .stroke {
// padding: 0 6px;
// border-right: 1px solid $content-bg;
// }
// }
// .remove {
// padding: 3px 8px 2px;
// }
// }
// .item:has(.duplicate) {
// background-color: map-get($theme-colors, 'danger');
// border: 1px solid map-get($theme-colors, 'danger');
// }
// .add {
// color: #777;
// padding: 4px 10px 0;
// }
// .add, .item .body, .item .remove {
// &:hover { background: darken($body-bg2, 5%); }
// &:active { background: darken($body-bg2, 15%); }
// }
// .add:has(.duplicate), .item:has(.duplicate) .body, .item:has(.duplicate) .remove {
// &:hover { background: darken(map-get($theme-colors, 'danger'), 5%); }
// &:active { background: darken(map-get($theme-colors, 'danger'), 15%); }
// }
// }
// hotkey-input-modal {
// .input {
// background: $input-bg;
// padding: 10px;
// font-size: 24px;
// line-height: 27px;
// height: 55px;
// .stroke {
// background: $body-bg2;
// border: 1px solid $blue;
// border-radius: 3px;
// margin-right: 10px;
// padding: 3px 10px;
// }
// }
// .timeout {
// background: $input-bg;
// div {
// background: $blue;
// }
// }
// }
// .mb-3 label {
// margin-bottom: 2px;
// }
// .btn-check:checked + label {
// background: $blue;
// }
// .btn {
// i + * {
// margin-left: 5px;
// }
// &.btn-lg i + * {
// margin-left: 10px;
// }
// }
// .input-group-addon + .form-control {
// border-left: none;
// }
// .input-group > select.form-control {
// flex-direction: row;
// }
// .list-group-item {
// // transition: 0.0625s background ease;
// i + * {
// margin-left: 10px;
// }
// }
// .list-group.list-group-flush .list-group-item {
// background: transparent;
// border: none;
// &:not(:last-child) {
// border-bottom: none;
// }
// &.list-group-item-action {
// &:hover, &.active {
// background: $list-group-hover-bg;
// }
// }
// }
// .list-group-light {
// .list-group-item {
// border: none !important;
// outline: none !important;
// background: transparent;
// border-radius: $border-radius;
// margin: 0 !important;
// &.list-group-item-action {
// &:hover, &.active {
// background: $component-active-bg;
// color: $component-active-color;
// }
// }
// }
// }
// checkbox i.on {
// color: $blue;
// }
// .modal .modal-footer {
// background: rgba(0, 0, 0, .25);
// .btn {
// font-weight: bold;
// padding: 0.375rem 1.5rem;
// }
// }
// .list-group-item svg {
// fill: white;
// fill-opacity: 0.75;
// }
// *::-webkit-scrollbar {
// background: rgba(0, 0, 0, .125);
// width: 10px;
// margin: 5px;
// }
// *::-webkit-scrollbar-thumb {
// background: rgba(255, 255, 255, .25);
// }
// *::-webkit-scrollbar-corner,
// *::-webkit-resizer {
// opacity: 0;
// }
// search-panel {
// background: #131d27 !important;
// input {
// border-radius: 0 !important;
// }
// }
// .btn {
// cursor: pointer;
// justify-content: flex-start;
// overflow: hidden;
// &.disabled,
// &:disabled {
// cursor: not-allowed;
// }
// }
// .btn-warning:not(:disabled):not(.disabled) {
// &.active, &:active {
// color: $gray-900;
// }
// }
// .btn-secondary:not(:disabled):not(.disabled) {
// &.active, &:active {
// background: #191e23;
// align-items: center;
// }
// }
// .btn-link {
// text-decoration: none;
// &:hover, &[aria-expanded=true], &:active, &.active {
// color: $link-hover-color;
// border-radius: $btn-border-radius;
// }
// &[aria-expanded=true], &:active, &.active {
// background: rgba(255, 255, 255, 0.1);
// }
// }
// .btn-group .btn.active {
// border-color: transparent !important;
// }
// hr {
// border-color: $list-group-border-color;
// }
// .dropdown-menu {
// box-shadow: $dropdown-box-shadow;
// }
// ngx-colors-panel .opened {
// background: $body-bg !important;
// button {
// color: $body-color !important;
// }
// .button svg {
// fill: white;
// }
// }

View File

@ -343,6 +343,8 @@ search-panel {
}
.btn-link {
text-decoration: none;
&:hover, &[aria-expanded=true], &:active, &.active {
color: $link-hover-color;
border-radius: $btn-border-radius;

View File

@ -5,7 +5,7 @@ import { Theme } from './api'
/** @hidden */
@Injectable()
export class StandardTheme extends Theme {
name = this.translate.instant('Standard')
name = this.translate.instant('Standard (legacy)')
css = require('./theme.scss')
terminalBackground = '#222a33'
@ -17,7 +17,7 @@ export class StandardTheme extends Theme {
/** @hidden */
@Injectable()
export class StandardCompactTheme extends Theme {
name = this.translate.instant('Compact')
name = this.translate.instant('Compact (legacy)')
css = require('./theme.compact.scss')
terminalBackground = '#222a33'
macOSWindowButtonsInsetX = 8
@ -35,3 +35,15 @@ export class PaperTheme extends Theme {
css = require('./theme.paper.scss')
terminalBackground = '#f7f1e0'
}
/** @hidden */
@Injectable()
export class NewTheme extends Theme {
name = this.translate.instant('Standard')
css = require('./theme.new.scss')
terminalBackground = '#f7f1e0'
constructor (private translate: TranslateService) {
super()
}
}

View File

@ -200,3 +200,13 @@ $alert-color-level: -5;
$text-muted: rgba(255, 255, 255, 0.5);
$card-bg: $list-group-bg;
$tooltip-color: rgba(255, 255, 255, .75);
$tooltip-bg: rgba(0, 0, 0, .75);
$accordion-border-color: $list-group-border-color;
$accordion-bg: $list-group-bg;
$accordion-button-active-bg: $list-group-active-bg;
$accordion-button-active-color: $list-group-active-color;
$btn-close-color: $body-color;

View File

@ -2,13 +2,12 @@ ng-container(*ngIf='!argvMode')
.mb-3
label(translate) Command line
.input-group
.input-group-prepend
a.input-group-text(
(click)='switchToArgv()',
ngbTooltip='Split into unescaped arguments',
href='#'
)
i.fas.fa-fw.fa-caret-right
a.input-group-text.text-decoration-none(
(click)='switchToArgv()',
ngbTooltip='Split into unescaped arguments',
href='#'
)
i.fas.fa-fw.fa-caret-right
input.form-control.text-monospace(
[(ngModel)]='command',
(ngModelChange)='parseCommand()'
@ -18,13 +17,12 @@ ng-container(*ngIf='argvMode')
.mb-3
label(translate) Program
.input-group
.input-group-prepend
a.input-group-text(
(click)='switchToCommand()',
ngbTooltip='Combine into a single escaped command',
href='#'
)
i.fas.fa-fw.fa-caret-down
a.input-group-text.text-decoration-none(
(click)='switchToCommand()',
ngbTooltip='Combine into a single escaped command',
href='#'
)
i.fas.fa-fw.fa-caret-down
input.form-control.text-monospace(
type='text',
[(ngModel)]='_model.command',
@ -39,9 +37,8 @@ ng-container(*ngIf='argvMode')
type='text',
[(ngModel)]='_model.args[i]',
)
.input-group-append
button.btn.btn-secondary((click)='_model.args.splice(i, 1)')
i.fas.fa-fw.fa-trash
button.btn.btn-secondary((click)='_model.args.splice(i, 1)')
i.fas.fa-fw.fa-trash
.mt-2
button.btn.btn-secondary((click)='_model.args.push("")')

View File

@ -1,12 +1,10 @@
.mb-2.d-flex.align-items-center(*ngFor='let pair of vars')
.input-group
input.form-control.w-25.text-monospace([(ngModel)]='pair.key', (blur)='emitUpdate()', placeholder='Variable name')
.input-group-append
.input-group-text =
.input-group-text =
input.form-control.w-50.text-monospace([(ngModel)]='pair.value', (blur)='emitUpdate()', placeholder='Value')
.input-group-append
button.btn.btn-secondary((click)='removeEnvironmentVar(pair.key)')
i.fas.fa-fw.fa-trash
button.btn.btn-secondary((click)='removeEnvironmentVar(pair.key)')
i.fas.fa-fw.fa-trash
.d-flex
button.btn.btn-secondary((click)='addEnvironmentVar()')

View File

@ -16,9 +16,8 @@ command-line-editor([model]='profile.options')
placeholder='Home directory',
[(ngModel)]='profile.options.cwd'
)
.input-group-append
button.btn.btn-secondary((click)='pickWorkingDirectory()')
i.fas.fa-folder-open
button.btn.btn-secondary((click)='pickWorkingDirectory()')
i.fas.fa-folder-open
.mb-3
label(translate) Environment

View File

@ -16,10 +16,9 @@ ul.nav-tabs.mb-2(ngbNav, #nav='ngbNav')
a(ngbNavLink, translate) Available
ng-template(ngbNavContent)
.input-group.mb-3.mt-3
.input-group-prepend
.input-group-text
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='!availablePluginsReady')
i.fas.fa-fw.fa-search(*ngIf='availablePluginsReady')
.input-group-text
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='!availablePluginsReady')
i.fas.fa-fw.fa-search(*ngIf='availablePluginsReady')
input.form-control(
type='text',
[(ngModel)]='_1',
@ -61,9 +60,8 @@ ul.nav-tabs.mb-2(ngbNav, #nav='ngbNav')
a(ngbNavLink, translate) Installed
ng-template(ngbNavContent)
.input-group.mb-3.mt-3
.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='text',
[(ngModel)]='_2',

View File

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
// import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
@ -12,7 +12,7 @@ import { PluginsSettingsTabProvider } from './settings'
@NgModule({
imports: [
// BrowserModule,
CommonModule,
FormsModule,
NgbModule,
TabbyCorePlugin,

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,11 +31,10 @@ 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')
@ -50,7 +51,7 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
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)',

View File

@ -38,12 +38,11 @@
[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')

View File

@ -1,9 +1,8 @@
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')
.mb-3.hotkeys-table

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

@ -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

@ -9,8 +9,8 @@
[(ngModel)]='editingPath'
)
.breadcrumb(*ngIf='editingPath === null', (dblclick)='editPath()')
a.breadcrumb-item((click)='navigate("/")') SFTP
a.breadcrumb-item(
a.breadcrumb-item.text-decoration-none((click)='navigate("/")') SFTP
a.breadcrumb-item.text-decoration-none(
*ngFor='let segment of pathSegments',
(click)='navigate(segment.path)'
) {{segment.name}}
@ -25,7 +25,7 @@
i.fas.fa-upload.me-1
div(translate) Upload
button.btn.btn-link.btn-close((click)='close()') !{require('../../../tabby-core/src/icons/times.svg')}
button.btn.btn-link.text-decoration-none((click)='close()') !{require('../../../tabby-core/src/icons/times.svg')}
.body(dropZone, (transfer)='uploadOne($event)')
a.alert.alert-info.d-flex.align-items-center(

View File

@ -17,23 +17,18 @@ h5(translate) Add a port forward
.input-group.mb-2(*ngIf='newForward.type === PortForwardType.Dynamic')
input.form-control(type='text', [(ngModel)]='newForward.host')
.input-group-append
.input-group-text :
.input-group-text :
input.form-control(type='number', [(ngModel)]='newForward.port')
.input-group-append
.input-group-text →
.input-group-append.input-group-text(style='flex: 3 1 0', translate) SOCKS proxy
.input-group-text →
.input-group-text(style='flex: 3 1 0', translate) SOCKS proxy
.input-group.mb-2(*ngIf='newForward.type !== PortForwardType.Dynamic')
input.form-control(type='text', [(ngModel)]='newForward.host')
.input-group-append
.input-group-text :
.input-group-text :
input.form-control(type='number', [(ngModel)]='newForward.port')
.input-group-append
.input-group-text →
.input-group-text →
input.form-control(type='text', [(ngModel)]='newForward.targetAddress')
.input-group-append
.input-group-text :
.input-group-text :
input.form-control(type='number', [(ngModel)]='newForward.targetPort')
.input-group.mb-2

View File

@ -284,7 +284,7 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
checkbox([text]='alg', [(ngModel)]='algorithms.serverHostKey[alg]')
li(ngbNavItem)
a(ngbNavLink, translate) Color scheme
a(ngbNavLink, translate) Colors
ng-template(ngbNavContent)
color-scheme-selector([(model)]='profile.terminalColorScheme')

View File

@ -16,8 +16,10 @@ import { SSHMultiplexerService } from '../services/sshMultiplexer.service'
@Component({
selector: 'ssh-tab',
template: `${BaseTerminalTabComponent.template} ${require('./sshTab.component.pug')}`,
styles: BaseTerminalTabComponent.styles,
styleUrls: ['./sshTab.component.scss'],
styles: [
...BaseTerminalTabComponent.styles,
require('./sshTab.component.scss'),
],
animations: BaseTerminalTabComponent.animations,
})
export class SSHTabComponent extends BaseTerminalTabComponent<SSHProfile> {

View File

@ -8,13 +8,12 @@
color-scheme-preview([scheme]='model')
.input-group.mb-3
.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 color schemes"|translate', [(ngModel)]='filter')
.body
.list-group-light.mb-3
.list-group.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())',

View File

@ -81,13 +81,12 @@
hr.mt-3.mb-4
.input-group.mb-3
.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 color schemes"|translate', [(ngModel)]='filter')
.body
.list-group-light.mb-3
.list-group.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())',

View File

@ -11,7 +11,7 @@ div
placeholder='Send',
[(ngModel)]='script.send'
)
.input-group-append.input-group-text.p-0.border-0
.input-group-text.p-0.border-0
.hover-reveal(ngbDropdown)
button.btn.btn-link.btn-sm(ngbDropdownToggle)
i.fas.fa-fw.fa-cog

View File

@ -9,8 +9,7 @@
(keyup.esc)='close.emit()',
[placeholder]='"Search"|translate'
)
.input-group-append(*ngIf='state.resultCount > 0')
.input-group-text.result-counter {{state.resultIndex ?? 0 + 1}} / {{state.resultCount}}
.input-group-text.result-counter(*ngIf='state.resultCount > 0') {{state.resultIndex ?? 0 + 1}} / {{state.resultCount}}
ng-container(*ngIf='state.resultCount > 0')
button.btn.btn-link(