new toolbar design

上级 621536a0
......@@ -132,6 +132,10 @@ app-root {
tab-body {
background: $content-bg;
.terminal-toolbar .btn, .toolbar-pin-button {
font-weight: bold;
}
}
multi-hotkey-input {
......
......@@ -31,3 +31,26 @@ export function wrapPromise <T> (zone: NgZone, promise: Promise<T>): Promise<T>
})
})
}
export class ResettableTimeout {
private fn: () => void
private timeout: number
private id: any
constructor (fn: () => void, timeout: number) {
this.fn = fn
this.timeout = timeout
this.id = null
}
set (timeout?: number): void {
this.clear()
this.id = setTimeout(this.fn, timeout ?? this.timeout)
}
clear (): void {
if (this.id) {
clearTimeout(this.id)
}
}
}
.tab-toolbar([class.show]='!session || !session.open')
.btn.btn-outline-secondary.reveal-button
i.fas.fa-ellipsis-h
.toolbar
i.fas.fa-circle.text-success.mr-2(*ngIf='session && session.open')
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session || !session.open')
strong {{profile.options.port}} ({{profile.options.baudrate}})
.terminal-toolbar(
(mouseenter)='showToolbar()',
(mouseleave)='hideToolbar()'
)
i.fas.fa-xs.fa-circle.text-success.mr-2(*ngIf='session && session.open')
i.fas.fa-xs.fa-circle.text-danger.mr-2(*ngIf='!session || !session.open')
strong {{profile.options.port}} ({{profile.options.baudrate}})
.mr-auto
.mr-auto
button.btn.btn-secondary.mr-3((click)='changeBaudRate()', *ngIf='session && session.open')
span Change baud rate
button.btn.btn-sm.btn-link.mr-3((click)='changeBaudRate()', *ngIf='session && session.open')
span Change baud rate
button.btn.btn-info((click)='reconnect()', *ngIf='!session || !session.open')
i.fas.fa-reload
span Reconnect
button.btn.btn-sm.btn-link((click)='reconnect()', *ngIf='!session || !session.open')
i.fas.fa-redo
span Reconnect
......@@ -14,6 +14,7 @@ import { SerialSession, BAUD_RATES, SerialProfile } from '../api'
animations: BaseTerminalTabComponent.animations,
})
export class SerialTabComponent extends BaseTerminalTabComponent {
enableToolbar = true
profile?: SerialProfile
session: SerialSession|null = null
serialPort: any
......
.tab-toolbar([class.show]='!session || !session.open')
.btn.btn-outline-secondary.reveal-button
i.fas.fa-ellipsis-h
.toolbar
i.fas.fa-circle.text-success.mr-2(*ngIf='session && session.open')
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session || !session.open')
strong.mr-auto {{profile.options.user}}@{{profile.options.host}}:{{profile.options.port}}
.terminal-toolbar(
(mouseenter)='showToolbar()',
(mouseleave)='hideToolbar()'
)
i.fas.fa-xs.fa-circle.text-success.mr-2(*ngIf='session && session.open')
i.fas.fa-xs.fa-circle.text-danger.mr-2(*ngIf='!session || !session.open')
strong.mr-auto {{profile.options.user}}@{{profile.options.host}}:{{profile.options.port}}
button.btn.btn-sm.btn-link.mr-2((click)='reconnect()')
i.fas.fa-redo
span Reconnect
button.btn.btn-secondary.mr-2((click)='reconnect()', [class.btn-info]='!session || !session.open')
span Reconnect
button.btn.btn-sm.btn-link.mr-2((click)='openSFTP()', *ngIf='session && session.open')
i.far.fa-folder-open
span SFTP
button.btn.btn-secondary.mr-2((click)='openSFTP()', *ngIf='session && session.open')
span SFTP
span.badge.badge-info.ml-2
i.fas.fa-flask
span Experimental
button.btn.btn-sm.btn-link(
*ngIf='session && session.open && hostApp.platform !== Platform.Web',
(click)='showPortForwarding()'
)
i.fas.fa-plug
span Ports
button.btn.btn-secondary(
*ngIf='session && session.open && hostApp.platform !== Platform.Web',
(click)='showPortForwarding()'
)
i.fas.fa-plug
span Ports
sftp-panel.bg-dark(
@panelSlide,
......
:host {
flex: auto;
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
&> .content {
flex: auto;
position: relative;
display: block;
overflow: hidden;
margin: 15px;
}
> .tab-toolbar {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 4;
pointer-events: none;
.reveal-button {
position: absolute;
top: 10px;
right: 30px;
border-radius: 50%;
width: 35px;
padding: 0;
height: 35px;
line-height: 35px;
transition: 0.125s opacity;
opacity: .5;
pointer-events: all;
}
&:hover .reveal-button {
opacity: 0;
}
&:hover .toolbar {
opacity: 1;
transform: translate(0, 0);
}
.toolbar {
opacity: 0;
background: rgba(0, 0, 0, .75);
padding: 10px 20px;
transition: 0.25s opacity;
display: flex;
align-items: center;
z-index: 1;
will-change: transform;
transform: translate(0, -100px);
transition: 0.25s transform ease-out;
pointer-events: all;
}
&.show {
.reveal-button {
opacity: 0;
}
.toolbar {
opacity: 1;
transform: translate(0, 0);
}
}
}
}
sftp-panel {
position: absolute;
height: 80%;
......
......@@ -17,6 +17,7 @@ import { SSHPortForwardingModalComponent } from './sshPortForwardingModal.compon
animations: BaseTerminalTabComponent.animations,
})
export class SSHTabComponent extends BaseTerminalTabComponent {
enableToolbar = true
Platform = Platform
profile?: SSHProfile
session: SSHSession|null = null
......
.tab-toolbar([class.show]='!session || !session.open')
.btn.btn-outline-secondary.reveal-button
i.fas.fa-ellipsis-h
.toolbar
i.fas.fa-circle.text-success.mr-2(*ngIf='session && session.open')
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session || !session.open')
strong.mr-auto {{profile.options.host}}:{{profile.options.port}}
.terminal-toolbar(
(mouseenter)='showToolbar()',
(mouseleave)='hideToolbar()'
)
i.fas.fa-xs.fa-circle.text-success.mr-2(*ngIf='session && session.open')
i.fas.fa-xs.fa-circle.text-danger.mr-2(*ngIf='!session || !session.open')
strong.mr-auto {{profile.options.host}}:{{profile.options.port}}
button.btn.btn-secondary.mr-2((click)='reconnect()', [class.btn-info]='!session || !session.open')
span Reconnect
button.btn.btn-sm.btn-link.mr-2((click)='reconnect()')
i.fas.fa-redo
span Reconnect
......@@ -14,6 +14,7 @@ import { TelnetProfile, TelnetSession } from '../session'
animations: BaseTerminalTabComponent.animations,
})
export class TelnetTabComponent extends BaseTerminalTabComponent {
enableToolbar = true
Platform = Platform
profile?: TelnetProfile
session: TelnetSession|null = null
......
......@@ -3,7 +3,7 @@ import { Spinner } from 'cli-spinner'
import colors from 'ansi-colors'
import { NgZone, OnInit, OnDestroy, Injector, ViewChild, HostBinding, Input, ElementRef, InjectFlags } from '@angular/core'
import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations'
import { AppService, ConfigService, BaseTabComponent, HostAppService, HotkeysService, NotificationsService, Platform, LogService, Logger, TabContextMenuItemProvider, SplitTabComponent, SubscriptionContainer, MenuItemOptions, PlatformService, HostWindowService } from 'tabby-core'
import { AppService, ConfigService, BaseTabComponent, HostAppService, HotkeysService, NotificationsService, Platform, LogService, Logger, TabContextMenuItemProvider, SplitTabComponent, SubscriptionContainer, MenuItemOptions, PlatformService, HostWindowService, ResettableTimeout } from 'tabby-core'
import { BaseSession } from '../session'
import { TerminalFrontendService } from '../services/terminalFrontend.service'
......@@ -75,6 +75,15 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
/** @hidden */
@HostBinding('class.top-padded') topPadded: boolean
/** @hidden */
@HostBinding('class.toolbar-enabled') enableToolbar = false
/** @hidden */
@HostBinding('class.toolbar-pinned') pinToolbar = false
/** @hidden */
@HostBinding('class.toolbar-revealed') revealToolbar = false
frontend?: Frontend
/** @hidden */
......@@ -125,6 +134,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
},
})
private spinnerActive = false
private toolbarRevealTimeout = new ResettableTimeout(() => {
this.revealToolbar = false
}, 1000)
get input$ (): Observable<Buffer> {
if (!this.frontend) {
......@@ -260,6 +272,8 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.bellPlayer.src = require('../bell.ogg').default
this.contextMenuProviders.sort((a, b) => a.weight - b.weight)
this.pinToolbar = (window.localStorage.pinTerminalToolbar ?? 'true') === 'true'
}
/** @hidden */
......@@ -646,6 +660,20 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.sessionChanged.next(session)
}
showToolbar (): void {
this.revealToolbar = true
this.toolbarRevealTimeout.clear()
}
hideToolbar (): void {
this.toolbarRevealTimeout.set()
}
togglePinToolbar (): void {
this.pinToolbar = !this.pinToolbar
window.localStorage.pinTerminalToolbar = this.pinToolbar
}
protected attachSessionHandler <T> (observable: Observable<T>, handler: (v: T) => void): void {
this.sessionHandlers.subscribe(observable, handler)
}
......
......@@ -5,3 +5,14 @@ search-panel(
[frontend]='frontend',
(close)='showSearchPanel = false'
)
button.btn.btn-sm.btn-link.toolbar-pin-button(
*ngIf='enableToolbar',
(click)='togglePinToolbar()',
(mouseenter)='showToolbar()',
(mouseleave)='hideToolbar()'
)
i.fas.fa-thumbtack(*ngIf='revealToolbar || pinToolbar')
i.fas.fa-wrench.mr-3(*ngIf='!revealToolbar && !pinToolbar')
span(*ngIf='pinToolbar') Unpin
span(*ngIf='!pinToolbar && revealToolbar') Pin
......@@ -3,6 +3,7 @@
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
&.top-padded {
padding-top: 20px;
......@@ -22,4 +23,47 @@
color: white !important;
}
}
$toolbarHeight: 40px;
&>.terminal-toolbar {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 4;
height: $toolbarHeight;
opacity: 0;
background: rgba(0, 0, 0, .75);
padding: 5px 85px 5px 15px;
transition: 0.25s opacity;
display: flex;
align-items: center;
z-index: 3;
will-change: transform;
transform: translate(0, -100px);
transition: 0.25s transform ease-out;
}
&.toolbar-revealed, &.toolbar-pinned {
> .terminal-toolbar {
opacity: 1;
transform: translate(0, 0);
}
}
&>.toolbar-pin-button {
position: absolute;
right: 10px;
top: 2px;
z-index: 4;
}
&.toolbar-pinned {
.content {
margin-top: 15px + $toolbarHeight;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册