Skip to content

Commit

Permalink
offline playlists: export to external device (pendrive, external hd) …
Browse files Browse the repository at this point in the history
…or any other location, bug fixes & enhancements
  • Loading branch information
marcio199226 committed Oct 7, 2021
1 parent dfc5afb commit 03615da
Show file tree
Hide file tree
Showing 52 changed files with 480 additions and 6,065 deletions.
3 changes: 2 additions & 1 deletion frontend/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<router-outlet></router-outlet>
<audio-player></audio-player>
<audio-player></audio-player>
<loader-overlay></loader-overlay>
22 changes: 20 additions & 2 deletions frontend/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { ApplicationRef, ChangeDetectorRef, Component } from '@angular/core';
import { ApplicationRef, ChangeDetectorRef, Component, NgZone } from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import * as Wails from '@wails/runtime';
import { RegisterCustomIcons } from './common/custom-icons';
import { LoaderService, LoaderEventBackend } from './services/loader.service';

@Component({
selector: 'app-root,[id="app"]',
Expand All @@ -10,9 +14,15 @@ export class AppComponent {
title = 'frontend';

constructor(
private _ngZone: NgZone,
private _cdr: ChangeDetectorRef,
private _appRef: ApplicationRef,
) {}
private _loader: LoaderService,
private _matIconRegistry: MatIconRegistry,
private _domSanitizer: DomSanitizer
) {
RegisterCustomIcons(this._matIconRegistry, this._domSanitizer);
}

ngOnInit() {
window.addEventListener('focus', () => Wails.Events.Emit("ytd:app:focused"));
Expand All @@ -26,5 +36,13 @@ export class AppComponent {
this._appRef.tick();
}
});

Wails.Events.On("ytd:loader:show", (payload: LoaderEventBackend) => {
this._loader.show(payload.label, null , payload.templateName);
});

Wails.Events.On("ytd:loader:hide", () => {
this._loader.hide();
});
}
}
8 changes: 6 additions & 2 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { APP_BASE_HREF, CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
Expand All @@ -10,6 +11,7 @@ import { HomeComponent, OfflinePlaylistComponent } from './pages';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatButtonModule } from '@angular/material/button';
import { MatBadgeModule } from '@angular/material/badge';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
Expand All @@ -25,9 +27,8 @@ import { MatSnackBarModule, MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/mater
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { NG_EVENT_PLUGINS } from '@tinkoff/ng-event-plugins';
import { AudioPlayerComponent, SettingsComponent, UpdaterComponent} from './components';
import { AudioPlayerComponent, LoaderOverlayComponent, SettingsComponent, UpdaterComponent, ConfirmationDialogComponent } from './components';
import { AddToPlaylistComponent, CreatePlaylistComponent } from './components/playlist';
import { ConfirmationDialogComponent } from './components/confirmation-dialog/confirmation-dialog.component';
import { AutofocusDirective } from './directives';


Expand All @@ -42,19 +43,22 @@ import { AutofocusDirective } from './directives';
AddToPlaylistComponent,
CreatePlaylistComponent,
ConfirmationDialogComponent,
LoaderOverlayComponent,
// directives
AutofocusDirective
],
imports: [
BrowserModule,
CommonModule,
HttpClientModule,
AppRoutingModule,
BrowserAnimationsModule,
FormsModule,
ReactiveFormsModule,
FlexLayoutModule,
MatBadgeModule,
MatButtonModule,
MatCardModule,
MatCheckboxModule,
MatDialogModule,
MatFormFieldModule,
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/app/common/custom-icons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { MatIconRegistry } from "@angular/material/icon";
import { DomSanitizer } from "@angular/platform-browser";

export function RegisterCustomIcons(matIconRegistry: MatIconRegistry, domSanitizer: DomSanitizer) {
matIconRegistry.addSvgIcon(
'github',
domSanitizer.bypassSecurityTrustResourceUrl('http://localhost:8080/static/frontend/dist/assets/icons/github.svg')
)
}
2 changes: 2 additions & 0 deletions frontend/src/app/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './audio-player/audio-player.component';
export * from './settings/settings.component';
export * from './updater/updater.component';
export * from './loader/loader.component';
export * from './confirmation-dialog/confirmation-dialog.component';
33 changes: 33 additions & 0 deletions frontend/src/app/components/loader/loader.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<div class="loader-overlay" [hidden]="isHidden()">
<div class="content-template">
<ng-container
*ngTemplateOutlet="loadingState.templateRef ? loadingState.templateRef : templatesMap[loadingState.templateName]; context: {label: loadingState.label, data: loadingState.data}"
></ng-container>
</div>
</div>

<ng-template #defaultLoaderTpl let-label="label">
<div class="sk-cube-grid">
<div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div>
</div>
<div class="label" *ngIf="label">{{ label }}</div>
</ng-template>

<ng-template #cardLoaderTpl let-label="label">
<mat-card class="card-tpl">
<mat-card-header *ngIf="label">
<mat-card-title>{{ label }}</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</mat-card-content>
</mat-card>
</ng-template>
107 changes: 107 additions & 0 deletions frontend/src/app/components/loader/loader.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
.loader-overlay {
&::before {
content: "";
display: block;
width: 100%;
height: 100%;
background-color: #2c3e50;
opacity: 0.6;
z-index: 9998;
position: fixed;
top: 0;
left: 0;
}

.label {
text-align: center;
color: #fff;
font-size: 18px;
z-index: 9999;
padding-top: 110px;
}

.content-template {
position: fixed;
text-align: center;
top: 50%;
transform: translate(-50%, -50%);
left: 50%;
color: #fff;
z-index: 9999;

.card-tpl {
max-width: 30vw;
width: fit-content;
min-width: 100px;
}
}
}

.sk-cube-grid {
width: 75px;
height: 75px;
position: fixed;
top: 0;
left: 0;
overflow: visible;
margin: auto;
bottom: 0;
right: 0;
z-index: 9999;
}

.sk-cube-grid .sk-cube {
width: 33%;
height: 33%;
background-color: #fff ;
float: left;
-webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
}
.sk-cube-grid .sk-cube1 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }
.sk-cube-grid .sk-cube2 {
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s; }
.sk-cube-grid .sk-cube3 {
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s; }
.sk-cube-grid .sk-cube4 {
-webkit-animation-delay: 0.1s;
animation-delay: 0.1s; }
.sk-cube-grid .sk-cube5 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }
.sk-cube-grid .sk-cube6 {
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s; }
.sk-cube-grid .sk-cube7 {
-webkit-animation-delay: 0s;
animation-delay: 0s; }
.sk-cube-grid .sk-cube8 {
-webkit-animation-delay: 0.1s;
animation-delay: 0.1s; }
.sk-cube-grid .sk-cube9 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }

@-webkit-keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
} 35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}

@keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
} 35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}
55 changes: 55 additions & 0 deletions frontend/src/app/components/loader/loader.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Component, OnInit, OnDestroy, TemplateRef, ChangeDetectionStrategy, ChangeDetectorRef, QueryList, ViewChildren, ViewChild, AfterViewInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { LoaderService, LoaderState } from 'app/services/loader.service';

@Component({
selector: 'loader-overlay',
templateUrl: './loader.component.html',
styleUrls: ['./loader.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class LoaderOverlayComponent implements OnInit, AfterViewInit, OnDestroy {

public loadingState: LoaderState;

public defaultTpl: "default" | "card" = 'card';

public templatesMap: {[key: string]: TemplateRef<any>} = {};

private subscription: Subscription;

@ViewChild('defaultLoaderTpl')
private _defaultLoaderTpl: TemplateRef<any>;

@ViewChild('cardLoaderTpl')
private _cardLoaderTpl: TemplateRef<any>;

constructor(
private _cdr: ChangeDetectorRef,
private _loaderService: LoaderService
) { }

ngOnInit(): void {
this.subscription = this._loaderService.loaderState$.subscribe(
state => {
this.loadingState = state;
this._cdr.detectChanges();
}
);
}

ngAfterViewInit(): void {
this.templatesMap = {
'default': this._defaultLoaderTpl,
'card': this._cardLoaderTpl
}
}

isHidden(): boolean {
return !this.loadingState.isLoading || !this.loadingState.show;
}

ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
2 changes: 1 addition & 1 deletion frontend/src/app/models/app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export interface BackendCallbacks {
RemovePlaylist: (uuid: string) => Promise<boolean>;
RemoveTrackFromPlaylist: (tid: string, playlist: OfflinePlaylist) => Promise<OfflinePlaylist>;
AddTrackToPlaylist: (playlists: OfflinePlaylist[]) => Promise<boolean>;
ExportPlaylist: (uuid: string) => Promise<string>;
ExportPlaylist: (uuid: string, path: string) => Promise<string>;
}
}
}
5 changes: 5 additions & 0 deletions frontend/src/app/pages/home/home.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
</div>
</div>
</div>
<div class="footer" fxLayout="column" fxLayoutGap="4px" fxLayoutAlign="start center">
<mat-icon svgIcon="github" class="clickable" (click)="openGithubProfile()"></mat-icon>
<div class="version clickable" (click)="openReleasePage()">{{ appVersion }}</div>
<div>Made with ❤️ by marcio199226</div>
</div>
</mat-drawer>
<mat-drawer-content>
<router-outlet (activate)="onRouterOutletActivate($event)" (deactivate)="onRouterOutletDeactivate($event)"></router-outlet>
Expand Down
17 changes: 17 additions & 0 deletions frontend/src/app/pages/home/home.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,33 @@ app-home {

.mat-drawer {
width: 250px;
height: calc(768px - 96px);
padding: 20px 10px;
background-color: rgba(0,0,0,0.4);
border-right: none;
color: white;

.mat-drawer-inner-container {
display: flex;
flex-direction: column;
}

.footer {
.version {
&:hover {
text-decoration: underline;
}
}
}
}

.mat-drawer-container {
}

.offline-playlists {
flex: 1;
overflow-y: auto;

.title {
font-weight: 200;
margin-bottom: 0px;
Expand Down
Loading

0 comments on commit 03615da

Please sign in to comment.