finished transfers menu

This commit is contained in:
Eugene Pankov
2021-06-07 01:13:53 +02:00
parent 49369873cc
commit 57c7e48bea
18 changed files with 221 additions and 108 deletions

View File

@@ -10,7 +10,7 @@ export { Theme } from './theme'
export { TabContextMenuItemProvider } from './tabContextMenuProvider'
export { SelectorOption } from './selector'
export { CLIHandler, CLIEvent } from './cli'
export { PlatformService, ClipboardContent, MessageBoxResult, MessageBoxOptions, FileDownload, FileUpload, FileTransfer } from './platform'
export { PlatformService, ClipboardContent, MessageBoxResult, MessageBoxOptions, FileDownload, FileUpload, FileTransfer, FileUploadOptions } from './platform'
export { MenuItemOptions } from './menu'
export { BootstrapData, BOOTSTRAP_DATA } from './mainProcess'
export { HostWindowService } from './hostWindow'

View File

@@ -1,4 +1,5 @@
import { MenuItemOptions } from './menu'
import { Subject, Observable } from 'rxjs'
/* eslint-disable @typescript-eslint/no-unused-vars */
export interface ClipboardContent {
@@ -54,18 +55,38 @@ export abstract class FileDownload extends FileTransfer {
export abstract class FileUpload extends FileTransfer {
abstract read (): Promise<Buffer>
async readAll (): Promise<Buffer> {
const buffers: Buffer[] = []
while (true) {
const buf = await this.read()
if (!buf.length) {
break
}
buffers.push(Buffer.from(buf))
}
return Buffer.concat(buffers)
}
}
export interface FileUploadOptions {
multiple: boolean
}
export abstract class PlatformService {
supportsWindowControls = false
get fileTransferStarted$ (): Observable<FileTransfer> { return this.fileTransferStarted }
protected fileTransferStarted = new Subject<FileTransfer>()
abstract readClipboard (): string
abstract setClipboard (content: ClipboardContent): void
abstract loadConfig (): Promise<string>
abstract saveConfig (content: string): Promise<void>
abstract startDownload (name: string, size: number): Promise<FileDownload>
abstract startUpload (): Promise<FileUpload[]>
abstract startDownload (name: string, size: number): Promise<FileDownload|null>
abstract startUpload (options?: FileUploadOptions): Promise<FileUpload[]>
getConfigPath (): string|null {
return null

View File

@@ -57,6 +57,17 @@ title-bar(
)
div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}}
.d-flex(
*ngIf='activeTransfers.length > 0',
ngbDropdown,
[(open)]='activeTransfersDropdownOpen'
)
button.btn.btn-secondary.btn-tab-bar(
title='File transfers',
ngbDropdownToggle
) !{require('../icons/download-solid.svg')}
transfers-menu(ngbDropdownMenu, [(transfers)]='activeTransfers')
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
.btn-group.background
@@ -83,22 +94,6 @@ title-bar(
)
div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}}
.d-flex(ngbDropdown)
button.btn.btn-secondary.btn-tab-bar(
title='File transfers',
ngbDropdownToggle
) !{require('../icons/download.svg')}
.transfers-dropdown-menu(ngbDropdownMenu)
.dropdown-header File transfers
.dropdown-item.transfer
.mr-3 !{require('../icons/download.svg')}
.main
label file.bin
.progress
.progress-bar.w-25
small 25%
button.btn.btn-link !{require('../icons/times.svg')}
button.btn.btn-secondary.btn-tab-bar.btn-update(
*ngIf='updatesAvailable',
title='Update available - Click to install',

View File

@@ -178,25 +178,3 @@ hotkey-hint {
::ng-deep .btn-update svg {
fill: cyan;
}
.transfers-dropdown-menu {
min-width: 300px;
.transfer {
display: flex;
align-items: center;
padding: 5px 0 5px 25px;
.main {
margin-right: auto;
label {
margin-bottom: 5px;
}
}
> i {
margin-right: 10px;
}
}
}

View File

@@ -12,7 +12,7 @@ import { UpdaterService } from '../services/updater.service'
import { BaseTabComponent } from './baseTab.component'
import { SafeModeModalComponent } from './safeModeModal.component'
import { AppService, HostWindowService, PlatformService, ToolbarButton, ToolbarButtonProvider } from '../api'
import { AppService, FileTransfer, HostWindowService, PlatformService, ToolbarButton, ToolbarButtonProvider } from '../api'
/** @hidden */
@Component({
@@ -60,6 +60,8 @@ export class AppRootComponent {
tabsDragging = false
unsortedTabs: BaseTabComponent[] = []
updatesAvailable = false
activeTransfers: FileTransfer[] = []
activeTransfersDropdownOpen = false
private logger: Logger
private constructor (
@@ -131,6 +133,11 @@ export class AppRootComponent {
this.noTabs = app.tabs.length === 0
})
platform.fileTransferStarted$.subscribe(transfer => {
this.activeTransfers.push(transfer)
this.activeTransfersDropdownOpen = true
})
config.ready$.toPromise().then(() => {
this.leftToolbarButtons = this.getToolbarButtons(false)
this.rightToolbarButtons = this.getToolbarButtons(true)

View File

@@ -0,0 +1,13 @@
.dropdown-header File transfers
.dropdown-item.transfer(*ngFor='let transfer of transfers', (click)='showTransfer(transfer)')
.icon(*ngIf='isDownload(transfer)') !{require('../icons/download.svg')}
.icon(*ngIf='!isDownload(transfer)') !{require('../icons/upload.svg')}
.main
label {{transfer.getName()}}
.status(*ngIf='transfer.isComplete()')
ngb-progressbar(type='success', [value]='100')
.status(*ngIf='transfer.isCancelled()')
ngb-progressbar(type='danger', [value]='100')
.status(*ngIf='!transfer.isComplete() && !transfer.isCancelled()')
ngb-progressbar(type='info', [value]='getProgress(transfer)')
button.btn.btn-link((click)='removeTransfer(transfer); $event.stopPropagation()') !{require('../icons/times.svg')}

View File

@@ -0,0 +1,31 @@
:host {
min-width: 300px;
}
.transfer {
display: flex;
align-items: center;
padding: 5px 0 5px 25px;
.icon {
padding: 4px 10px;
width: 36px;
height: 32px;
background: rgba(0,0,0,.25);
margin-right: 12px;
}
.main {
width: 100%;
margin-right: auto;
margin-bottom: 7px;
label {
margin: 0;
}
}
> i {
margin-right: 10px;
}
}

View File

@@ -0,0 +1,38 @@
import { Component, Input, Output, EventEmitter } from '@angular/core'
import { FileDownload, FileTransfer, PlatformService } from '../api/platform'
/** @hidden */
@Component({
selector: 'transfers-menu',
template: require('./transfersMenu.component.pug'),
styles: [require('./transfersMenu.component.scss')],
})
export class TransfersMenuComponent {
@Input() transfers: FileTransfer[]
@Output() transfersChange = new EventEmitter<FileTransfer[]>()
constructor (private platform: PlatformService) { }
isDownload (transfer: FileTransfer): boolean {
return transfer instanceof FileDownload
}
getProgress (transfer: FileTransfer): number {
return Math.round(100 * transfer.getCompletedBytes() / transfer.getSize())
}
showTransfer (transfer: FileTransfer): void {
const fp = transfer['filePath']
if (fp) {
this.platform.showItemInFolder(fp)
}
}
removeTransfer (transfer: FileTransfer): void {
if (!transfer.isComplete()) {
transfer.cancel()
}
this.transfers = this.transfers.filter(x => x !== transfer)
this.transfersChange.emit(this.transfers)
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z"></path></svg>

After

Width:  |  Height:  |  Size: 529 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M528 288h-92.1l46.1-46.1c30.1-30.1 8.8-81.9-33.9-81.9h-64V48c0-26.5-21.5-48-48-48h-96c-26.5 0-48 21.5-48 48v112h-64c-42.6 0-64.2 51.7-33.9 81.9l46.1 46.1H48c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V336c0-26.5-21.5-48-48-48zm-400-80h112V48h96v160h112L288 368 128 208zm400 256H48V336h140.1l65.9 65.9c18.8 18.8 49.1 18.7 67.9 0l65.9-65.9H528v128zm-88-64c0-13.3 10.7-24 24-24s24 10.7 24 24-10.7 24-24 24-24-10.7-24-24z"></path></svg>
<svg aria-hidden="true" focusable="false" data-prefix="fad" data-icon="download" class="svg-inline--fa fa-download fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="fa-group"><path class="fa-secondary" fill="currentColor" d="M320 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3a19.37 19.37 0 0 1-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24a23.94 23.94 0 0 1 24-24h80a23.94 23.94 0 0 1 24 24z" opacity="0.4"></path><path class="fa-primary" fill="currentColor" d="M488 352H341.3l-49 49a51.24 51.24 0 0 1-72.6 0l-49-49H24a23.94 23.94 0 0 0-24 24v112a23.94 23.94 0 0 0 24 24h464a23.94 23.94 0 0 0 24-24V376a23.94 23.94 0 0 0-24-24zm-120 96a16 16 0 1 1 16-16 16 16 0 0 1-16 16zm64 0a16 16 0 1 1 16-16 16 16 0 0 1-16 16z"></path></g></svg>

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 784 B

View File

@@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fad" data-icon="upload" class="svg-inline--fa fa-upload fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="fa-group"><path class="fa-secondary" fill="currentColor" d="M488 351.92H352v8a56 56 0 0 1-56 56h-80a56 56 0 0 1-56-56v-8H24a23.94 23.94 0 0 0-24 24v112a23.94 23.94 0 0 0 24 24h464a23.94 23.94 0 0 0 24-24v-112a23.94 23.94 0 0 0-24-24zm-120 132a20 20 0 1 1 20-20 20.06 20.06 0 0 1-20 20zm64 0a20 20 0 1 1 20-20 20.06 20.06 0 0 1-20 20z" opacity="0.4"></path><path class="fa-primary" fill="currentColor" d="M192 359.93v-168h-87.7c-17.8 0-26.7-21.5-14.1-34.11L242.3 5.62a19.37 19.37 0 0 1 27.3 0l152.2 152.2c12.6 12.61 3.7 34.11-14.1 34.11H320v168a23.94 23.94 0 0 1-24 24h-80a23.94 23.94 0 0 1-24-24z"></path></g></svg>

After

Width:  |  Height:  |  Size: 813 B

View File

@@ -21,6 +21,7 @@ import { SplitTabComponent, SplitTabRecoveryProvider } from './components/splitT
import { SplitTabSpannerComponent } from './components/splitTabSpanner.component'
import { UnlockVaultModalComponent } from './components/unlockVaultModal.component'
import { WelcomeTabComponent } from './components/welcomeTab.component'
import { TransfersMenuComponent } from './components/transfersMenu.component'
import { AutofocusDirective } from './directives/autofocus.directive'
import { FastHtmlBindDirective } from './directives/fastHtmlBind.directive'
@@ -81,6 +82,7 @@ const PROVIDERS = [
SplitTabSpannerComponent,
UnlockVaultModalComponent,
WelcomeTabComponent,
TransfersMenuComponent,
],
entryComponents: [
RenameTabModalComponent,

View File

@@ -242,7 +242,7 @@ export class ConfigService {
private migrate (config) {
config.version ??= 0
if (config.version < 1) {
for (const connection of config.ssh?.connections) {
for (const connection of config.ssh?.connections ?? []) {
if (connection.privateKey) {
connection.privateKeys = [connection.privateKey]
delete connection.privateKey

View File

@@ -43,7 +43,10 @@ app-root {
.btn-tab-bar {
background: transparent;
&:hover { background: rgba(0, 0, 0, .25) !important; }
&:active { background: rgba(0, 0, 0, .5) !important; }
&:active, &[aria-expanded-true] { background: rgba(0, 0, 0, .5) !important; }
&:focus {
box-shadow: none;
}
&::after {
display: none;
@@ -386,3 +389,7 @@ search-panel {
hr {
border-color: $list-group-border-color;
}
.dropdown-menu {
box-shadow: $dropdown-box-shadow;
}

View File

@@ -191,5 +191,5 @@ $modal-footer-border-color: #222;
$modal-footer-border-width: 1px;
$modal-content-border-width: 0;
$progress-bar-bg: $table-bg;
$progress-bg: $table-bg;
$progress-height: 3px;