Include startup icon

Fix UI layout
This commit is contained in:
death-claw
2019-12-06 23:09:57 +01:00
parent fb09e4c46b
commit 23d3553d99
9 changed files with 145 additions and 197 deletions
+22 -14
View File
@@ -1,17 +1,25 @@
<div fxLayout="column" *ngIf="connecting()" class="overlay loading" fxLayoutAlign="center center">
<mat-spinner></mat-spinner>
<h2>Loading...</h2>
</div>
<div fxLayout="column" *ngIf="noConnectionState()" class="overlay no-connection" fxLayoutAlign="center center">
<mat-icon class="overlay-icon">error</mat-icon>
<h2>The app seems to be shutdown</h2>
</div>
<div [ngClass]="{ electron: electronService.isElectronApp }" fxLayout="column" id="app-container">
<div id="app-header" fxFlex="nogrow">
<app-toolbar></app-toolbar>
<ng-container *ngIf="appState | async as state">
<div *ngIf="state === 'CONNECTING'" class="overlay loading" fxLayout="column" fxLayoutAlign="center center">
<div class="sk-chase">
<div class="sk-chase-dot"></div>
<div class="sk-chase-dot"></div>
<div class="sk-chase-dot"></div>
<div class="sk-chase-dot"></div>
<div class="sk-chase-dot"></div>
<div class="sk-chase-dot"></div>
</div>
</div>
<div id="app-body" fxFlex="grow">
<router-outlet></router-outlet>
<div *ngIf="state === 'DISCONNECTED'" class="overlay no-connection" fxLayout="column" fxLayoutAlign="center center">
<mat-icon class="overlay-icon">error</mat-icon>
<h2>Error connecting to daemon, try restarting the application</h2>
</div>
<div *ngIf="state === 'CONNECTED'" [ngClass]="{ electron: electron | async }" fxLayout="column" id="app-container">
<div fxFlex="nogrow" id="app-header">
<app-toolbar></app-toolbar>
</div>
<div fxFlex="grow" id="app-body" style="margin-bottom: 20px;">
<router-outlet></router-outlet>
</div>
<app-status-bar style="width: 100%"></app-status-bar>
</div>
</div>
</ng-container>
+72 -9
View File
@@ -1,13 +1,76 @@
#title {
user-select: none
}
.overlay-icon {
font-size: 128px;
width: 128px;
height: 128px;
font-size: 64px;
width: 64px;
height: 64px;
}
.no-connection {
color: #eb6060;
.no-connection, .loading {
background-color: #2c3e50;
}
.overlay {
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2000;
}
.sk-chase {
width: 60px;
height: 60px;
position: relative;
animation: sk-chase 2.5s infinite linear both;
}
.sk-chase-dot {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
animation: sk-chase-dot 2.0s infinite ease-in-out both;
}
.sk-chase-dot:before {
content: '';
display: block;
width: 25%;
height: 25%;
background-color: #fff;
border-radius: 100%;
animation: sk-chase-dot-before 2.0s infinite ease-in-out both;
}
.sk-chase-dot:nth-child(1) { animation-delay: -1.1s; }
.sk-chase-dot:nth-child(2) { animation-delay: -1.0s; }
.sk-chase-dot:nth-child(3) { animation-delay: -0.9s; }
.sk-chase-dot:nth-child(4) { animation-delay: -0.8s; }
.sk-chase-dot:nth-child(5) { animation-delay: -0.7s; }
.sk-chase-dot:nth-child(6) { animation-delay: -0.6s; }
.sk-chase-dot:nth-child(1):before { animation-delay: -1.1s; }
.sk-chase-dot:nth-child(2):before { animation-delay: -1.0s; }
.sk-chase-dot:nth-child(3):before { animation-delay: -0.9s; }
.sk-chase-dot:nth-child(4):before { animation-delay: -0.8s; }
.sk-chase-dot:nth-child(5):before { animation-delay: -0.7s; }
.sk-chase-dot:nth-child(6):before { animation-delay: -0.6s; }
@keyframes sk-chase {
100% { transform: rotate(360deg); }
}
@keyframes sk-chase-dot {
80%, 100% { transform: rotate(360deg); }
}
@keyframes sk-chase-dot-before {
50% {
transform: scale(0.4);
} 100%, 0% {
transform: scale(1.0);
}
}
+21 -30
View File
@@ -1,56 +1,47 @@
import { AppService } from './app.service';
import { ClipboardService } from './clipboard.service';
import { ElectronService } from 'ngx-electron';
import { Component, OnInit, OnDestroy, NgZone, AfterViewInit, Renderer2 } from '@angular/core';
import { Component, OnDestroy, AfterViewInit, Renderer2, ChangeDetectionStrategy, NgZone } from '@angular/core';
import { MatDialog } from '@angular/material';
import { Subscription } from 'rxjs';
import { Subscription, BehaviorSubject, Subject } from 'rxjs';
import { WsConnectionService, WSState } from './ws-connection.service';
import { WsHandler } from './ws-handler';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
styleUrls: ['./app.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
export class AppComponent implements OnDestroy, AfterViewInit {
constructor(
public dialog: MatDialog,
private dialog: MatDialog,
private ws: WsConnectionService,
public electronService: ElectronService,
private clipboardService: ClipboardService,
private ngZone: NgZone,
private appService: AppService,
private renderer: Renderer2
) {}
subscriptions: Subscription[] = [];
websocketHandlerPromise: Promise<WsHandler>;
currentState: WSState;
themeLoaded = false;
noConnectionState(): boolean {
return this.currentState === WSState.CLOSE || this.currentState === WSState.ERROR;
private renderer: Renderer2,
private ngZone: NgZone
) {
this.electron = new BehaviorSubject(electronService.isElectronApp);
}
connecting(): boolean {
return (this.currentState === WSState.INIT || this.currentState === WSState.CONNECTING) && !this.themeLoaded ;
}
private subscriptions: Subscription[] = [];
appState: Subject<string> = new BehaviorSubject('CONNECTING');
electron: Subject<boolean>;
ngAfterViewInit() {
this.appService.renderer = this.renderer;
}
ngOnInit() {
this.currentState = WSState.INIT;
this.subscriptions.push(this.ws.state.subscribe(e => {
this.currentState = e;
if (this.currentState === WSState.CLOSE || this.currentState === WSState.ERROR) {
this.dialog.closeAll();
} else if (this.currentState === WSState.OPEN) {
this.subscriptions.push(this.ws.state.subscribe(wsState => {
if (wsState === WSState.CLOSE || wsState === WSState.ERROR) {
setTimeout(() => this.ngZone.run(() => {
this.dialog.closeAll();
this.appState.next('DISCONNECTED');
}), 500);
} else if (wsState === WSState.OPEN) {
this.clipboardService.init();
this.appService
.loadTheme()
.subscribe(() => this.ngZone.run(() => this.themeLoaded = true));
.subscribe(() => this.ngZone.run(() => this.appState.next('CONNECTED')));
}
}));
}
-2
View File
@@ -7,7 +7,6 @@ import {
MatIconModule,
MatFormFieldModule,
MatInputModule,
MatProgressSpinnerModule,
MatMenuModule,
MatDialogModule,
MatCardModule,
@@ -28,7 +27,6 @@ import {
MatIconModule,
MatInputModule,
MatFormFieldModule,
MatProgressSpinnerModule,
MatMenuModule,
MatDialogModule,
MatCardModule,
@@ -1,110 +1,3 @@
<!-- <div class="container" style="height: 100%; background-color: white">
<div
[ngClass]="{
error: postState.status === 'ERROR',
downloading: postState.status === 'DOWNLOADING' || postState.status === 'PARTIAL',
complete: postState.status === 'COMPLETE',
stopped: postState.status === 'STOPPED'
}"
class="progress-bar-back"
style="position: relative; height: 100%; max-height: 48px;"
>
<div
class="progress-foreground"
fxLayout="row"
fxLayoutAlign="space-between"
style="background-color: transparent; width: 100%; height: 100%;"
>
<div class="progress-bar" color="accent" style="position: absolute; width: 100%; top: 37px; padding: 0 50px">
<mat-progress-bar [value]="postState.progress" class="example-margin" color="primary" mode="determinate">
</mat-progress-bar>
</div>
<span fxLayout="row">
<span (click)="toggleExpand()" class="chevron">
<button *ngIf="expanded; else notExpanded" mat-icon-button>
<mat-icon>expand_more</mat-icon>
</button>
<ng-template #notExpanded>
<button mat-icon-button>
<mat-icon>chevron_right</mat-icon>
</button>
</ng-template>
</span>
<span>{{ postState.title }}</span>
<span class="filler" fxFlex="grow"></span>
</span>
<span>
<span class="progress-percentage">{{ postState.done + '/' + postState.total }}</span>
<button [matMenuTriggerFor]="menu" mat-icon-button>
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button
(click)="restart()"
*ngIf="
(postState.status === 'COMPLETE' && postState.progress !== 100) ||
postState.status === 'ERROR' ||
postState.status === 'STOPPED'
"
mat-menu-item
>
<mat-icon>play_arrow</mat-icon>
<span>Start</span>
</button>
<button
(click)="stop()"
*ngIf="
postState.status === 'DOWNLOADING' || postState.status === 'PARTIAL' || postState.status === 'PENDING'
"
mat-menu-item
>
<ng-container>
<mat-icon>stop</mat-icon>
<span>Stop</span>
</ng-container>
</button>
<button (click)="seeDetails()" mat-menu-item>
<mat-icon>list</mat-icon>
<span>Files</span>
</button>
<button (click)="remove()" mat-menu-item>
<mat-icon>delete</mat-icon>
<span>Remove</span>
</button>
<button (click)="open()" *ngIf="electronService.isElectronApp" mat-menu-item>
<mat-icon>open_in_new</mat-icon>
<span>Download Location</span>
</button>
</mat-menu>
</span>
</div>
</div>
<section *ngIf="expanded">
<div class="details table">
<div class="row" style="display: table-row">
<h4 class="cell attribute">Status:</h4>
<p class="cell value">
{{ postState.status | titlecase }}
</p>
</div>
<div class="row" style="display: table-row">
<h4 class="cell attribute">Post URL:</h4>
<p class="cell value">
<a (click)="goTo()" [appPreview]="postState.previews" href="javascript:void(0)"
>https://vipergirls/threads/?p={{ postState.postId }}</a
>
</p>
</div>
<div style="display: table-row">
<h4 class="cell attribute">Host:</h4>
<p class="cell value">
{{ postState.hosts }}
</p>
</div>
</div>
</section>
</div> -->
<div class="container" style="height: 100%; background-color: white">
<ng-container *ngIf="postState$ | async as postState">
<div
@@ -124,16 +17,14 @@
fxLayoutGap="5px"
style="background-color: transparent; width: 100%; height: 100%;"
>
<div class="checkbox" style="display: inline-block; width: 5px; height: 100%;"></div>
<span fxFlex="grow" fxLayout="row" fxLayoutAlign="space-between center">
<span
><a (click)="goTo()" [appPreview]="postState.previews" href="javascript:void(0)">{{
postState.title
}}</a></span
<div class="checkbox" fxFlex="nogrow" style="width: 5px; height: 100%;"></div>
<span class="row-text" fxFlex="grow" fxLayout="row" fxLayoutAlign="space-between center" fxLayoutGap="20px">
<span [title]="postState.title">{{ postState.title }}</span>
<span [title]="postState.done + '/' + postState.total + ' from ' + postState.hosts"
>{{ postState.done + '/' + postState.total }} from {{ postState.hosts }}</span
>
<span>{{postState.done + '/' + postState.total}} done from {{postState.hosts}}</span>
</span>
<button [matMenuTriggerFor]="menu" mat-icon-button>
<button [matMenuTriggerFor]="menu" fxFlex="nogrow" mat-icon-button>
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
@@ -1,3 +1,14 @@
.checkbox {
background-color: transparent;
}
.row-text {
white-space: nowrap;
overflow: hidden;
}
.row-text > span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@@ -38,9 +38,11 @@ export class StatusBarComponent implements OnInit, OnDestroy, AfterViewInit {
selected: EventEmitter<number> = new EventEmitter();
ngAfterViewInit(): void {
this.selected.emit(0);
this.globalState.emit(new GlobalState(0, 0, 0, 0));
this.downloadSpeed.emit(new DownloadSpeed('0 B'));
this.ngZone.run(() => {
this.selected.emit(0);
this.globalState.emit(new GlobalState(0, 0, 0, 0));
this.downloadSpeed.emit(new DownloadSpeed('0 B'));
});
}
ngOnInit() {
@@ -63,7 +65,9 @@ export class StatusBarComponent implements OnInit, OnDestroy, AfterViewInit {
handler.send(new WSMessage(CMD.GLOBAL_STATE_SUB.toString()));
handler.send(new WSMessage(CMD.SPEED_SUB.toString()));
});
this.subscriptions.push(this.selectionService.selected$.subscribe(selected => this.selected.emit(selected.length)));
this.subscriptions.push(
this.selectionService.selected$.subscribe(selected => this.ngZone.run(() => this.selected.emit(selected.length)))
);
}
ngOnDestroy(): void {
@@ -210,8 +210,10 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
}
ngAfterViewInit(): void {
this.disableSelection.next(true);
this.loggedUser.emit(new LoggedUser(null));
this.ngZone.run(() => {
this.disableSelection.next(true);
this.loggedUser.emit(new LoggedUser(null));
});
}
ngOnInit() {
@@ -229,7 +231,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
this.selectionService.selected$.subscribe(selected => {
this.selected = selected;
this.disableSelection.next(this.selected.length === 0);
this.ngZone.run(() => this.disableSelection.next(this.selected.length === 0));
});
}
-20
View File
@@ -75,26 +75,6 @@ app-root {
margin: 8px;
}
.overlay {
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2000;
}
.loading {
background-color: whitesmoke;
}
.no-connection {
background-color: whitesmoke !important;
}
#app-container {
position: fixed;
display: block;