Compare commits

..

8 Commits

Author SHA1 Message Date
Tzahi12345
70d89d310c Removed unneeded hooks 2020-08-24 02:18:39 -04:00
Tzahi12345
c48aaaf13c Possible fix for arm autobuild (2) 2020-08-24 00:25:59 -04:00
Tzahi12345
6cf7ea193a Possible fix for arm autobuild 2020-08-24 00:21:10 -04:00
Isaac Abadi
c9016f446d Ghosting colors for loading videos is now customizable in an internal config, allowing dark mode to have different colors for the ghosting 2020-08-22 18:55:24 -04:00
Isaac Abadi
919e2a649a Updated styling of recent videos
Added content loader module which will add ghosting to the recent videos component while the files are loading

Updated custom playlists component to support large sized cards
2020-08-22 18:34:28 -04:00
Isaac Abadi
dc6dd5f5a2 Added support for "large" sized cards 2020-08-22 00:47:18 -04:00
Tzahi12345
2e4ef3b224 Moves hooks back into their proper directory and updated arm dockerfile to avoid installing curl just go get qemu 2020-08-18 16:43:52 -04:00
Tzahi12345
0e35b2ca1b Proxy now forces safe download mode 2020-08-18 15:34:03 -04:00
17 changed files with 134 additions and 32 deletions

View File

@@ -1,11 +1,15 @@
FROM arm32v7/alpine:3.12 as frontend
FROM alpine:3.12 as frontend
RUN apk add --no-cache \
npm
npm \
curl
RUN npm install -g @angular/cli
WORKDIR /build
RUN curl -L https://github.com/balena-io/qemu/releases/download/v3.0.0%2Bresin/qemu-3.0.0+resin-arm.tar.gz | tar zxvf - -C . && mv qemu-3.0.0+resin-arm/qemu-arm-static .
COPY [ "package.json", "package-lock.json", "/build/" ]
RUN npm install
@@ -17,7 +21,7 @@ RUN ng build --prod
FROM arm32v7/alpine:3.12
COPY qemu-arm-static /usr/bin
COPY --from=frontend /build/qemu-arm-static /usr/bin
ENV UID=1000 \
GID=1000 \

View File

@@ -157,7 +157,7 @@ function setConfigItems(items) {
function globalArgsRequiresSafeDownload() {
const globalArgs = getConfigItem('ytdl_custom_args').split(',,');
const argsThatRequireSafeDownload = ['--write-sub', '--write-srt'];
const argsThatRequireSafeDownload = ['--write-sub', '--write-srt', '--proxy'];
const failedArgs = globalArgs.filter(arg => argsThatRequireSafeDownload.includes(arg));
return failedArgs && failedArgs.length > 0;
}

View File

@@ -1,3 +0,0 @@
#!/bin/bash
# downloads a local copy of qemu on docker-hub build machines
curl -L https://github.com/balena-io/qemu/releases/download/v3.0.0%2Bresin/qemu-3.0.0+resin-arm.tar.gz | tar zxvf - -C . && mv qemu-3.0.0+resin-arm/qemu-arm-static .

View File

@@ -1,4 +0,0 @@
#!/bin/bash
# Register qemu-*-static for all supported processors except the
# current one, but also remove all registered binfmt_misc before
docker run --rm --privileged multiarch/qemu-user-static:register --reset

15
package-lock.json generated
View File

@@ -1404,6 +1404,21 @@
}
}
},
"@ngneat/content-loader": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@ngneat/content-loader/-/content-loader-5.0.0.tgz",
"integrity": "sha512-XrS53rsiJoQIOy2BwmOHkvgPv0a5cTzXbbM+/3IpgezPFdNqDunpZW+AciWQffVOfgbmL+7cYp1DVb6WM15LhQ==",
"requires": {
"tslib": "^2.0.0"
},
"dependencies": {
"tslib": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
"integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
}
}
},
"@ngtools/webpack": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.1.0.tgz",

View File

@@ -30,6 +30,7 @@
"@angular/platform-browser": "^9.1.0",
"@angular/platform-browser-dynamic": "^9.1.0",
"@angular/router": "^9.1.0",
"@ngneat/content-loader": "^5.0.0",
"core-js": "^2.4.1",
"file-saver": "^2.0.2",
"filesize": "^6.1.0",

View File

@@ -54,6 +54,7 @@ import { SettingsComponent } from './settings/settings.component';
import { MatChipsModule } from '@angular/material/chips';
import { NgxFileDropModule } from 'ngx-file-drop';
import { AvatarModule } from 'ngx-avatar';
import { ContentLoaderModule } from '@ngneat/content-loader';
import es from '@angular/common/locales/es';
import { AboutDialogComponent } from './dialogs/about-dialog/about-dialog.component';
@@ -152,7 +153,6 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible
MatMenuModule,
MatDialogModule,
MatSlideToggleModule,
MatMenuModule,
MatAutocompleteModule,
MatTabsModule,
MatTooltipModule,
@@ -164,6 +164,7 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible
ClipboardModule,
NgxFileDropModule,
AvatarModule,
ContentLoaderModule,
VgCoreModule,
VgControlsModule,
VgOverlayPlayModule,

View File

@@ -1,8 +1,8 @@
<div *ngIf="playlists && playlists.length > 0">
<div class="container">
<div class="row justify-content-center">
<div *ngFor="let playlist of playlists; let i = index" [ngClass]="[ postsService.card_size === 'small' ? 'col-2 mb-2 mt-2 file-col' : '', postsService.card_size === 'medium' ? 'col-6 col-lg-4 mb-2 mt-2 file-col' : '' ]">
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" (goToFile)="goToPlaylist($event)" [file_obj]="playlist" [is_playlist]="true" (editPlaylist)="editPlaylistDialog($event)" (deleteFile)="deletePlaylist($event)"></app-unified-file-card>
<div *ngFor="let playlist of playlists; let i = index" class="mb-2 mt-2" [ngClass]="[ postsService.card_size === 'small' ? 'col-2 small-col' : '', postsService.card_size === 'medium' ? 'col-6 col-lg-4 medium-col' : '', postsService.card_size === 'large' ? 'col-12 large-col' : '' ]">
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" (goToFile)="goToPlaylist($event)" [file_obj]="playlist" [is_playlist]="true" (editPlaylist)="editPlaylistDialog($event)" (deleteFile)="deletePlaylist($event)" [loading]="false"></app-unified-file-card>
</div>
</div>
</div>

View File

@@ -5,6 +5,14 @@
right: 15px;
}
.file-col {
.large-col {
max-width: 320px;
}
.medium-col {
max-width: 240px;
}
.small-col {
max-width: 240px;
}

View File

@@ -1,4 +1,4 @@
<div class="container-fluid">
<div class="container-fluid" style="max-width: 941px;">
<div class="row">
<div class="col-12 order-2 col-sm-4 order-sm-1 d-flex justify-content-center">
<div>
@@ -17,7 +17,7 @@
</div>
</div>
<div class="col-12 order-1 col-sm-4 order-sm-2 d-flex justify-content-center">
<h4 style="text-align: center">My videos</h4>
<h4 class="my-videos-title" i18n="My videos title">My videos</h4>
</div>
<div class="col-12 order-3 col-sm-4 order-sm-3 d-flex justify-content-center">
<mat-form-field [ngClass]="searchIsFocused ? 'search-bar-focused' : 'search-bar-unfocused'" class="search-bar" color="accent">
@@ -30,9 +30,16 @@
<div>
<div class="container">
<div class="row justify-content-center">
<div *ngFor="let file of filtered_files; let i = index" [ngClass]="[ postsService.card_size === 'small' ? 'col-2 mb-2 mt-2 file-col' : '', postsService.card_size === 'medium' ? 'col-6 col-lg-4 mb-2 mt-2 file-col' : '' ]">
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" (goToFile)="goToFile($event)" (goToSubscription)="goToSubscription($event)" [file_obj]="file" [use_youtubedl_archive]="postsService.config['Downloader']['use_youtubedl_archive']" (deleteFile)="deleteFile($event)"></app-unified-file-card>
</div>
<ng-container *ngIf="normal_files_received">
<div *ngFor="let file of filtered_files; let i = index" class="mb-2 mt-2" [ngClass]="[ postsService.card_size === 'small' ? 'col-2 small-col' : '', postsService.card_size === 'medium' ? 'col-6 col-lg-4 medium-col' : '', postsService.card_size === 'large' ? 'col-12 large-col' : '' ]">
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" (goToFile)="goToFile($event)" (goToSubscription)="goToSubscription($event)" [file_obj]="file" [use_youtubedl_archive]="postsService.config['Downloader']['use_youtubedl_archive']" [loading]="false" (deleteFile)="deleteFile($event)"></app-unified-file-card>
</div>
</ng-container>
<ng-container *ngIf="!normal_files_received && loading_files && loading_files.length > 0">
<div *ngFor="let file of loading_files; let i = index" class="mb-2 mt-2" [ngClass]="[ postsService.card_size === 'small' ? 'col-2 small-col' : '', postsService.card_size === 'medium' ? 'col-6 col-lg-4 medium-col' : '', postsService.card_size === 'large' ? 'col-12 large-col' : '' ]">
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" [loading]="true" [theme]="postsService.theme"></app-unified-file-card>
</div>
</ng-container>
</div>
</div>
</div>

View File

@@ -1,4 +1,12 @@
.file-col {
.large-col {
max-width: 320px;
}
.medium-col {
max-width: 240px;
}
.small-col {
max-width: 240px;
}
@@ -37,4 +45,16 @@
display: inline-block;
position: absolute;
top: 10px;
}
.my-videos-title {
text-align: center;
position: relative;
top: 12px;
}
@media (max-width: 576px) {
.my-videos-title {
top: 0px;
}
}

View File

@@ -9,6 +9,9 @@ import { Router } from '@angular/router';
})
export class RecentVideosComponent implements OnInit {
cached_file_count = 0;
loading_files = null;
normal_files_received = false;
subscription_files_received = false;
files: any[] = null;
@@ -47,7 +50,14 @@ export class RecentVideosComponent implements OnInit {
};
filterProperty = this.filterProperties['upload_date'];
constructor(public postsService: PostsService, private router: Router) { }
constructor(public postsService: PostsService, private router: Router) {
// get cached file count
if (localStorage.getItem('cached_file_count')) {
this.cached_file_count = +localStorage.getItem('cached_file_count');
this.loading_files = Array(this.cached_file_count).fill(0);
console.log(this.loading_files);
}
}
ngOnInit(): void {
this.postsService.service_initialized.subscribe(init => {
@@ -114,6 +124,11 @@ export class RecentVideosComponent implements OnInit {
this.filtered_files = this.files;
}
this.filterByProperty(this.filterProperty['property']);
// set cached file count for future use, note that we convert the amount of files to a string
localStorage.setItem('cached_file_count', '' + this.files.length);
this.normal_files_received = true;
});
}

View File

@@ -1,8 +1,9 @@
<div (mouseover)="elevated=true" (mouseout)="elevated=false" style="position: relative; width: fit-content;">
<div class="download-time"><mat-icon class="audio-video-icon">{{(file_obj.type === 'audio' || file_obj.isAudio) ? 'audiotrack' : 'movie'}}</mat-icon>&nbsp;&nbsp;{{file_obj.registered | date:'shortDate'}}</div>
<button [matMenuTriggerFor]="action_menu" class="menuButton" mat-icon-button><mat-icon>more_vert</mat-icon></button>
<div *ngIf="!loading" class="download-time"><mat-icon class="audio-video-icon">{{(file_obj.type === 'audio' || file_obj.isAudio) ? 'audiotrack' : 'movie'}}</mat-icon>&nbsp;&nbsp;{{file_obj.registered | date:'shortDate'}}</div>
<div *ngIf="loading" class="download-time" style="width: 75%; margin-top: 5px;"><content-loader [primaryColor]="theme.ghost_primary" [secondaryColor]="theme.ghost_secondary" width="250" height="30"><svg:rect x="0" y="0" rx="3" ry="3" width="250" height="30" /></content-loader></div>
<button [disabled]="loading" [matMenuTriggerFor]="action_menu" class="menuButton" mat-icon-button><mat-icon>more_vert</mat-icon></button>
<mat-menu #action_menu="matMenu">
<ng-container *ngIf="!is_playlist">
<ng-container *ngIf="!is_playlist && !loading">
<button (click)="openFileInfoDialog()" mat-menu-item><mat-icon>info</mat-icon><ng-container i18n="Video info button">Info</ng-container></button>
<button (click)="navigateToSubscription()" mat-menu-item *ngIf="file_obj.sub_id"><mat-icon>{{file_obj.isAudio ? 'library_music' : 'video_library'}}</mat-icon>&nbsp;<ng-container i18n="Go to subscription menu item">Go to subscription</ng-container></button>
<mat-divider></mat-divider>
@@ -15,17 +16,20 @@
<button *ngIf="!file_obj.sub_id" (click)="emitDeleteFile()" mat-menu-item><mat-icon>delete</mat-icon><ng-container i18n="Delete video button">Delete</ng-container></button>
<button *ngIf="!file_obj.sub_id && use_youtubedl_archive" (click)="emitDeleteFile(true)" mat-menu-item><mat-icon>delete_forever</mat-icon><ng-container i18n="Delete and blacklist video button">Delete and blacklist</ng-container></button>
</ng-container>
<ng-container *ngIf="is_playlist">
<ng-container *ngIf="is_playlist && !loading">
<button (click)="emitEditPlaylist()" mat-menu-item><mat-icon>edit</mat-icon><ng-container i18n="Playlist edit button">Edit</ng-container></button>
<mat-divider></mat-divider>
<button (click)="emitDeleteFile()" mat-menu-item><mat-icon>delete_forever</mat-icon><ng-container i18n="Delete playlist">Delete</ng-container></button>
</ng-container>
<ng-container *ngIf="loading">
<button mat-menu-item>Placeholder</button>
</ng-container>
</mat-menu>
<mat-card [matTooltip]="null" (click)="navigateToFile()" matRipple class="file-mat-card" [ngClass]="{'small-mat-card': card_size === 'small', 'file-mat-card': card_size === 'medium', 'mat-elevation-z4': !elevated, 'mat-elevation-z8': elevated}">
<mat-card [matTooltip]="null" (click)="navigateToFile()" matRipple class="file-mat-card" [ngClass]="{'small-mat-card': card_size === 'small', 'file-mat-card': card_size === 'medium', 'large-mat-card': card_size === 'large', 'mat-elevation-z4': !elevated, 'mat-elevation-z8': elevated}">
<div style="padding:5px">
<div *ngIf="file_obj.thumbnailURL" class="img-div">
<div *ngIf="!loading && file_obj.thumbnailURL" class="img-div">
<div style="position: relative">
<img [ngClass]="{'image-small': card_size === 'small', 'image': card_size === 'medium'}" [src]="file_obj.thumbnailURL" alt="Thumbnail">
<img [ngClass]="{'image-small': card_size === 'small', 'image': card_size === 'medium', 'image-large': card_size === 'large'}" [src]="file_obj.thumbnailURL" alt="Thumbnail">
<div class="duration-time">
{{file_length}}
</div>
@@ -33,7 +37,12 @@
</div>
<span [ngClass]="{'max-two-lines': card_size !== 'small', 'max-one-line': card_size === 'small' }"><strong>{{!is_playlist ? file_obj.title : file_obj.name}}</strong></span>
<div *ngIf="loading" class="img-div">
<content-loader [primaryColor]="theme.ghost_primary" [secondaryColor]="theme.ghost_secondary" width="100" height="55"><svg:rect x="0" y="0" rx="0" ry="0" width="100" height="55" /></content-loader>
</div>
<span *ngIf="!loading" [ngClass]="{'max-two-lines': card_size !== 'small', 'max-one-line': card_size === 'small' }">{{card_size === 'large' && file_obj.uploader ? file_obj.uploader + ' - ' : ''}}<strong>{{!is_playlist ? file_obj.title : file_obj.name}}</strong></span>
<span *ngIf="loading" class="title-loading"><content-loader [primaryColor]="theme.ghost_primary" [secondaryColor]="theme.ghost_secondary" width="250" height="30"><svg:rect x="0" y="0" rx="3" ry="3" width="250" height="30" /></content-loader></span>
</div>
</mat-card>
</div>

View File

@@ -1,3 +1,10 @@
.large-mat-card {
width: 300px;
height: 250px;
padding: 0px;
cursor: pointer;
}
.file-mat-card {
width: 200px;
height: 200px;
@@ -26,6 +33,12 @@
justify-content: center;
}
.image-large {
width: 300px;
height: 167.5px;
object-fit: cover;
}
.image {
width: 200px;
height: 112.5px;
@@ -104,6 +117,12 @@
top: 6px;
}
.title-loading {
width: 93%;
position: absolute;
bottom: 1px;
}
@media (max-width: 576px){
// .example-card {

View File

@@ -16,6 +16,8 @@ export class UnifiedFileCardComponent implements OnInit {
type = null;
elevated = false;
@Input() loading = true;
@Input() theme = null;
@Input() file_obj = null;
@Input() card_size = 'medium';
@Input() use_youtubedl_archive = false;
@@ -36,7 +38,9 @@ export class UnifiedFileCardComponent implements OnInit {
constructor(private dialog: MatDialog) { }
ngOnInit(): void {
this.file_length = fancyTimeFormat(this.file_obj.duration);
if (!this.loading) {
this.file_length = fancyTimeFormat(this.file_obj.duration);
}
}
emitDeleteFile(blacklistMode = false) {

View File

@@ -40,7 +40,7 @@
<br/>
<mat-form-field placeholder="Card size">
<mat-select [(ngModel)]="card_size" (selectionChange)="cardSizeOptionChanged($event.value)">
<mat-option value="large" [disabled]="true">
<mat-option value="large">
Large
</mat-option>
<mat-option value="medium">

View File

@@ -3,6 +3,8 @@ const THEMES_CONFIG = {
'key': 'default',
'background_color': 'ghostwhite',
'alternate_color': 'gray',
'ghost_primary': '#f9f9f9',
'ghost_secondary': '#ecebeb',
'css_label': 'default-theme',
'social_theme': 'material-light'
},
@@ -10,12 +12,16 @@ const THEMES_CONFIG = {
'key': 'dark',
'background_color': '#141414',
'alternate_color': '#695959',
'ghost_primary': '#444444',
'ghost_secondary': '#141414',
'css_label': 'dark-theme',
'social_theme': 'material-dark'
},
'light': {
'key': 'light',
'background_color': 'white',
'ghost_primary': '#f9f9f9',
'ghost_secondary': '#ecebeb',
'css_label': 'light-theme',
'social_theme': 'material-light'
}