mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-03-07 12:00:01 +03:00
Subscription file cards are now replaced with unified file cards
GetAllFiles can now filter by sub_id Improved API models and added request body docs for GetAllFiles
This commit is contained in:
@@ -97,6 +97,11 @@ paths:
|
||||
summary: Get all files
|
||||
description: Gets all files and playlists stored in the db
|
||||
operationId: get-getAllFiles
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GetAllFilesRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
@@ -1724,6 +1729,41 @@ components:
|
||||
description: All video playlists
|
||||
items:
|
||||
$ref: '#/components/schemas/Playlist'
|
||||
GetAllFilesRequest:
|
||||
type: object
|
||||
properties:
|
||||
sort:
|
||||
$ref: '#/components/schemas/Sort'
|
||||
range:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
description: Two elements allowed, start index and end index
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
text_search:
|
||||
type: string
|
||||
description: Filter files by title
|
||||
file_type_filter:
|
||||
$ref: '#/components/schemas/FileTypeFilter'
|
||||
sub_id:
|
||||
type: string
|
||||
description: Include if you want to filter by subscription
|
||||
Sort:
|
||||
type: object
|
||||
properties:
|
||||
by:
|
||||
type: string
|
||||
description: Property to sort by
|
||||
order:
|
||||
type: number
|
||||
description: 1 for ascending, -1 for descending
|
||||
FileTypeFilter:
|
||||
type: string
|
||||
enum:
|
||||
- audio_only
|
||||
- video_only
|
||||
- both
|
||||
GetAllFilesResponse:
|
||||
required:
|
||||
- files
|
||||
|
||||
@@ -912,11 +912,11 @@ app.post('/api/getFile', optionalJwt, async function (req, res) {
|
||||
app.post('/api/getAllFiles', optionalJwt, async function (req, res) {
|
||||
// these are returned
|
||||
let files = null;
|
||||
let playlists = null;
|
||||
let sort = req.body.sort;
|
||||
let range = req.body.range;
|
||||
let text_search = req.body.text_search;
|
||||
let file_type_filter = req.body.file_type_filter;
|
||||
const sort = req.body.sort;
|
||||
const range = req.body.range;
|
||||
const text_search = req.body.text_search;
|
||||
const file_type_filter = req.body.file_type_filter;
|
||||
const sub_id = req.body.sub_id;
|
||||
const uuid = req.isAuthenticated() ? req.user.uid : null;
|
||||
|
||||
const filter_obj = {user_uid: uuid};
|
||||
@@ -929,6 +929,10 @@ app.post('/api/getAllFiles', optionalJwt, async function (req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sub_id) {
|
||||
filter_obj['sub_id'] = sub_id;
|
||||
}
|
||||
|
||||
if (file_type_filter === 'audio_only') filter_obj['isAudio'] = true;
|
||||
else if (file_type_filter === 'video_only') filter_obj['isAudio'] = false;
|
||||
|
||||
|
||||
@@ -40,11 +40,13 @@ export type { DownloadTwitchChatByVODIDRequest } from './models/DownloadTwitchCh
|
||||
export type { DownloadTwitchChatByVODIDResponse } from './models/DownloadTwitchChatByVODIDResponse';
|
||||
export type { DownloadVideosForSubscriptionRequest } from './models/DownloadVideosForSubscriptionRequest';
|
||||
export { FileType } from './models/FileType';
|
||||
export { FileTypeFilter } from './models/FileTypeFilter';
|
||||
export type { GenerateArgsResponse } from './models/GenerateArgsResponse';
|
||||
export type { GenerateNewApiKeyResponse } from './models/GenerateNewApiKeyResponse';
|
||||
export type { GetAllCategoriesResponse } from './models/GetAllCategoriesResponse';
|
||||
export type { GetAllDownloadsRequest } from './models/GetAllDownloadsRequest';
|
||||
export type { GetAllDownloadsResponse } from './models/GetAllDownloadsResponse';
|
||||
export type { GetAllFilesRequest } from './models/GetAllFilesRequest';
|
||||
export type { GetAllFilesResponse } from './models/GetAllFilesResponse';
|
||||
export type { GetAllSubscriptionsResponse } from './models/GetAllSubscriptionsResponse';
|
||||
export type { GetAllTasksResponse } from './models/GetAllTasksResponse';
|
||||
@@ -82,6 +84,7 @@ export type { RestoreDBBackupRequest } from './models/RestoreDBBackupRequest';
|
||||
export { Schedule } from './models/Schedule';
|
||||
export type { SetConfigRequest } from './models/SetConfigRequest';
|
||||
export type { SharingToggle } from './models/SharingToggle';
|
||||
export type { Sort } from './models/Sort';
|
||||
export type { SubscribeRequest } from './models/SubscribeRequest';
|
||||
export type { SubscribeResponse } from './models/SubscribeResponse';
|
||||
export type { Subscription } from './models/Subscription';
|
||||
|
||||
9
src/api-types/models/FileTypeFilter.ts
Normal file
9
src/api-types/models/FileTypeFilter.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export enum FileTypeFilter {
|
||||
AUDIO_ONLY = 'audio_only',
|
||||
VIDEO_ONLY = 'video_only',
|
||||
BOTH = 'both',
|
||||
}
|
||||
20
src/api-types/models/GetAllFilesRequest.ts
Normal file
20
src/api-types/models/GetAllFilesRequest.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { FileTypeFilter } from './FileTypeFilter';
|
||||
import type { Sort } from './Sort';
|
||||
|
||||
export type GetAllFilesRequest = {
|
||||
sort?: Sort;
|
||||
range?: Array<number>;
|
||||
/**
|
||||
* Filter files by title
|
||||
*/
|
||||
text_search?: string;
|
||||
file_type_filter?: FileTypeFilter;
|
||||
/**
|
||||
* Include if you want to filter by subscription
|
||||
*/
|
||||
sub_id?: string;
|
||||
};
|
||||
14
src/api-types/models/Sort.ts
Normal file
14
src/api-types/models/Sort.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type Sort = {
|
||||
/**
|
||||
* Property to sort by
|
||||
*/
|
||||
by?: string;
|
||||
/**
|
||||
* 1 for ascending, -1 for descending
|
||||
*/
|
||||
order?: number;
|
||||
};
|
||||
@@ -49,7 +49,6 @@ import { CreatePlaylistComponent } from './create-playlist/create-playlist.compo
|
||||
import { SubscriptionsComponent } from './subscriptions/subscriptions.component';
|
||||
import { SubscribeDialogComponent } from './dialogs/subscribe-dialog/subscribe-dialog.component';
|
||||
import { SubscriptionComponent } from './subscription//subscription/subscription.component';
|
||||
import { SubscriptionFileCardComponent } from './subscription/subscription-file-card/subscription-file-card.component';
|
||||
import { SubscriptionInfoDialogComponent } from './dialogs/subscription-info-dialog/subscription-info-dialog.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
@@ -102,7 +101,6 @@ registerLocaleData(es, 'es');
|
||||
SubscriptionsComponent,
|
||||
SubscribeDialogComponent,
|
||||
SubscriptionComponent,
|
||||
SubscriptionFileCardComponent,
|
||||
SubscriptionInfoDialogComponent,
|
||||
SettingsComponent,
|
||||
AboutDialogComponent,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 order-1 col-sm-4 order-sm-2 d-flex justify-content-center">
|
||||
<h4 class="my-videos-title" i18n="My videos title">My videos</h4>
|
||||
<h4 class="my-videos-title" i18n="My files title">My files</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">
|
||||
@@ -35,7 +35,7 @@
|
||||
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" [locale]="postsService.locale" (goToFile)="goToFile($event)" (goToSubscription)="goToSubscription($event)" [file_obj]="file" [use_youtubedl_archive]="postsService.config['Downloader']['use_youtubedl_archive']" [availablePlaylists]="playlists" (addFileToPlaylist)="addFileToPlaylist($event)" [loading]="false" (deleteFile)="deleteFile($event)" [baseStreamPath]="postsService.path" [jwtString]="postsService.isLoggedIn ? this.postsService.token : ''"></app-unified-file-card>
|
||||
</div>
|
||||
<div *ngIf="paged_data.length === 0">
|
||||
<ng-container i18n="No videos found">No videos found.</ng-container>
|
||||
<ng-container i18n="No files found">No files found.</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!normal_files_received && loading_files && loading_files.length > 0">
|
||||
@@ -46,7 +46,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div *ngIf="usePaginator">
|
||||
<div style="position: absolute; margin-left: 8px; margin-top: 5px; scale: 0.8">
|
||||
<mat-form-field>
|
||||
<mat-label><ng-container i18n="File type">File type</ng-container></mat-label>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { Component, Input, OnInit, ViewChild } from '@angular/core';
|
||||
import { PostsService } from 'app/posts.services';
|
||||
import { Router } from '@angular/router';
|
||||
import { FileType } from '../../../api-types';
|
||||
import { FileType, FileTypeFilter } from '../../../api-types';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { Subject } from 'rxjs';
|
||||
import { distinctUntilChanged } from 'rxjs/operators';
|
||||
@@ -13,6 +13,9 @@ import { distinctUntilChanged } from 'rxjs/operators';
|
||||
})
|
||||
export class RecentVideosComponent implements OnInit {
|
||||
|
||||
@Input() usePaginator = true;
|
||||
@Input() sub_id = null;
|
||||
|
||||
cached_file_count = 0;
|
||||
loading_files = null;
|
||||
|
||||
@@ -104,7 +107,7 @@ export class RecentVideosComponent implements OnInit {
|
||||
|
||||
// set file type filter to cached value
|
||||
const cached_file_type_filter = localStorage.getItem('file_type_filter');
|
||||
if (cached_file_type_filter) {
|
||||
if (this.usePaginator && cached_file_type_filter) {
|
||||
this.fileTypeFilter = cached_file_type_filter;
|
||||
}
|
||||
|
||||
@@ -163,7 +166,7 @@ export class RecentVideosComponent implements OnInit {
|
||||
const current_file_index = (this.paginator?.pageIndex ? this.paginator.pageIndex : 0)*this.pageSize;
|
||||
const sort = {by: this.filterProperty['property'], order: this.descendingMode ? -1 : 1};
|
||||
const range = [current_file_index, current_file_index + this.pageSize];
|
||||
this.postsService.getAllFiles(sort, range, this.search_mode ? this.search_text : null, this.fileTypeFilter).subscribe(res => {
|
||||
this.postsService.getAllFiles(sort, range, this.search_mode ? this.search_text : null, this.fileTypeFilter as FileTypeFilter, this.sub_id).subscribe(res => {
|
||||
this.file_count = res['file_count'];
|
||||
this.paged_data = res['files'];
|
||||
for (let i = 0; i < this.paged_data.length; i++) {
|
||||
|
||||
@@ -97,7 +97,10 @@ import {
|
||||
Schedule,
|
||||
ClearDownloadsRequest,
|
||||
Category,
|
||||
UpdateFileRequest
|
||||
UpdateFileRequest,
|
||||
Sort,
|
||||
FileTypeFilter,
|
||||
GetAllFilesRequest
|
||||
} from '../api-types';
|
||||
import { isoLangs } from './settings/locales_list';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
@@ -355,8 +358,9 @@ export class PostsService implements CanActivate {
|
||||
return this.http.post<GetFileResponse>(this.path + 'getFile', body, this.httpOptions);
|
||||
}
|
||||
|
||||
getAllFiles(sort, range, text_search, file_type_filter) {
|
||||
return this.http.post<GetAllFilesResponse>(this.path + 'getAllFiles', {sort: sort, range: range, text_search: text_search, file_type_filter: file_type_filter}, this.httpOptions);
|
||||
getAllFiles(sort: Sort, range: number[], text_search: string, file_type_filter: FileTypeFilter, sub_id: string) {
|
||||
const body: GetAllFilesRequest = {sort: sort, range: range, text_search: text_search, file_type_filter: file_type_filter, sub_id: sub_id};
|
||||
return this.http.post<GetAllFilesResponse>(this.path + 'getAllFiles', body, this.httpOptions);
|
||||
}
|
||||
|
||||
updateFile(uid: string, change_obj: Object) {
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<div style="position: relative; width: fit-content;">
|
||||
<div class="duration-time">
|
||||
<ng-container i18n="Video duration label">Length:</ng-container> {{formattedDuration}}
|
||||
</div>
|
||||
<button [matMenuTriggerFor]="action_menu" class="menuButton" mat-icon-button><mat-icon>more_vert</mat-icon></button>
|
||||
<mat-menu #action_menu="matMenu">
|
||||
<button (click)="openSubscriptionInfoDialog()" mat-menu-item><mat-icon>info</mat-icon><ng-container i18n="Subscription video info button">Info</ng-container></button>
|
||||
<button (click)="deleteAndRedownload()" mat-menu-item><mat-icon>restore</mat-icon><ng-container i18n="Delete and redownload subscription video button">Delete and redownload</ng-container></button>
|
||||
<button (click)="deleteForever()" mat-menu-item *ngIf="sub.archive && use_youtubedl_archive"><mat-icon>delete_forever</mat-icon><ng-container i18n="Delete forever subscription video button">Delete forever</ng-container></button>
|
||||
</mat-menu>
|
||||
<mat-card (click)="goToFile()" matRipple class="example-card mat-elevation-z6">
|
||||
<div style="padding:5px">
|
||||
<div *ngIf="!image_errored && file.thumbnailURL" class="img-div">
|
||||
<img class="image" (error)="onImgError($event)" [src]="file.thumbnailURL" alt="Thumbnail">
|
||||
</div>
|
||||
|
||||
<span class="max-two-lines"><strong>{{file.title}}</strong></span>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
@@ -1,76 +0,0 @@
|
||||
.example-card {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
padding: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menuButton {
|
||||
right: 0px;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
|
||||
}
|
||||
|
||||
/* Coerce the <span> icon container away from display:inline */
|
||||
.mat-icon-button .mat-button-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 200px;
|
||||
height: 112.5px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.example-full-width-height {
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
|
||||
.centered {
|
||||
margin: 0 auto;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.img-div {
|
||||
max-height: 80px;
|
||||
padding: 0px;
|
||||
margin: 32px 0px 0px -5px;
|
||||
width: calc(100% + 5px + 5px);
|
||||
}
|
||||
|
||||
.max-two-lines {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
max-height: 2.4em;
|
||||
line-height: 1.2em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
bottom: 5px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.duration-time {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 5px;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
@media (max-width: 576px){
|
||||
|
||||
.example-card {
|
||||
width: 175px !important;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 175px;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { SubscriptionFileCardComponent } from './subscription-file-card.component';
|
||||
|
||||
describe('SubscriptionFileCardComponent', () => {
|
||||
let component: SubscriptionFileCardComponent;
|
||||
let fixture: ComponentFixture<SubscriptionFileCardComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SubscriptionFileCardComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SubscriptionFileCardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,98 +0,0 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { Router } from '@angular/router';
|
||||
import { PostsService } from 'app/posts.services';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { VideoInfoDialogComponent } from 'app/dialogs/video-info-dialog/video-info-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-subscription-file-card',
|
||||
templateUrl: './subscription-file-card.component.html',
|
||||
styleUrls: ['./subscription-file-card.component.scss']
|
||||
})
|
||||
export class SubscriptionFileCardComponent implements OnInit {
|
||||
image_errored = false;
|
||||
image_loaded = false;
|
||||
|
||||
formattedDuration = null;
|
||||
|
||||
@Input() file;
|
||||
@Input() sub;
|
||||
@Input() use_youtubedl_archive = false;
|
||||
|
||||
@Output() goToFileEmit = new EventEmitter<any>();
|
||||
@Output() reloadSubscription = new EventEmitter<boolean>();
|
||||
|
||||
constructor(private snackBar: MatSnackBar, private postsService: PostsService, private dialog: MatDialog) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.file.duration) {
|
||||
this.formattedDuration = fancyTimeFormat(this.file.duration);
|
||||
}
|
||||
}
|
||||
|
||||
onImgError(event) {
|
||||
this.image_errored = true;
|
||||
}
|
||||
|
||||
imageLoaded(loaded) {
|
||||
this.image_loaded = true;
|
||||
}
|
||||
|
||||
goToFile() {
|
||||
const emit_obj = {
|
||||
uid: this.file.uid,
|
||||
url: this.file.requested_formats ? this.file.requested_formats[0].url : this.file.url
|
||||
}
|
||||
this.goToFileEmit.emit(emit_obj);
|
||||
}
|
||||
|
||||
openSubscriptionInfoDialog() {
|
||||
const dialogRef = this.dialog.open(VideoInfoDialogComponent, {
|
||||
data: {
|
||||
file: this.file,
|
||||
},
|
||||
minWidth: '50vw'
|
||||
});
|
||||
}
|
||||
|
||||
deleteAndRedownload() {
|
||||
this.postsService.deleteSubscriptionFile(this.sub, this.file.id, false, this.file.uid).subscribe(res => {
|
||||
this.reloadSubscription.emit(true);
|
||||
this.openSnackBar(`Successfully deleted file: '${this.file.id}'`, 'Dismiss.');
|
||||
});
|
||||
}
|
||||
|
||||
deleteForever() {
|
||||
this.postsService.deleteSubscriptionFile(this.sub, this.file.id, true, this.file.uid).subscribe(res => {
|
||||
this.reloadSubscription.emit(true);
|
||||
this.openSnackBar(`Successfully deleted file: '${this.file.id}'`, 'Dismiss.');
|
||||
});
|
||||
}
|
||||
|
||||
public openSnackBar(message: string, action: string) {
|
||||
this.snackBar.open(message, action, {
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function fancyTimeFormat(time) {
|
||||
// Hours, minutes and seconds
|
||||
const hrs = ~~(time / 3600);
|
||||
const mins = ~~((time % 3600) / 60);
|
||||
const secs = ~~time % 60;
|
||||
|
||||
// Output like "1:01" or "4:03:59" or "123:03:59"
|
||||
let ret = '';
|
||||
|
||||
if (hrs > 0) {
|
||||
ret += '' + hrs + ':' + (mins < 10 ? '0' : '');
|
||||
}
|
||||
|
||||
ret += '' + mins + ':' + (secs < 10 ? '0' : '');
|
||||
ret += '' + secs;
|
||||
return ret;
|
||||
}
|
||||
@@ -10,38 +10,7 @@
|
||||
<br/>
|
||||
|
||||
<div *ngIf="subscription">
|
||||
<div class="flex-grid">
|
||||
<div class="filter-select-parent">
|
||||
<div style="display: inline-block;">
|
||||
<mat-select style="width: 110px;" [(ngModel)]="this.filterProperty" (selectionChange)="filterOptionChanged($event.value)">
|
||||
<mat-option *ngFor="let filterOption of filterProperties | keyvalue" [value]="filterOption.value">
|
||||
{{filterOption['value']['label']}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
<div style="display: inline-block;">
|
||||
<button (click)="toggleModeChange()" mat-icon-button><mat-icon>{{descendingMode ? 'arrow_downward' : 'arrow_upward'}}</mat-icon></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
</div>
|
||||
<div class="col">
|
||||
<h4 i18n="Subscription videos title" style="text-align: center; margin-bottom: 20px;">Videos</h4>
|
||||
</div>
|
||||
<div style="top: -12px;" class="col">
|
||||
<mat-form-field [ngClass]="searchIsFocused ? 'search-bar-focused' : 'search-bar-unfocused'" class="search-bar" color="accent">
|
||||
<input (focus)="searchIsFocused = true" (blur)="searchIsFocused = false" class="search-input" type="text" placeholder="Search" i18n-placeholder="Subscription videos search placeholder" [(ngModel)]="search_text" (ngModelChange)="onSearchInputChanged($event)" matInput>
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div *ngFor="let file of filtered_files" class="col-6 col-lg-4 mb-2 mt-2 sub-file-col">
|
||||
<app-subscription-file-card (reloadSubscription)="getSubscription()" (goToFileEmit)="goToFile($event)" [file]="file" [sub]="subscription" [use_youtubedl_archive]="use_youtubedl_archive"></app-subscription-file-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<app-recent-videos [sub_id]="subscription.id" [usePaginator]="false"></app-recent-videos>
|
||||
</div>
|
||||
<button class="edit-button" color="primary" (click)="editSubscription()" [disabled]="downloading" mat-fab><mat-icon class="save-icon">edit</mat-icon></button>
|
||||
<button class="watch-button" color="primary" (click)="watchSubscription()" mat-fab><mat-icon class="save-icon">video_library</mat-icon></button>
|
||||
|
||||
@@ -100,22 +100,12 @@ export class SubscriptionComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
getConfig(): void {
|
||||
this.use_youtubedl_archive = this.postsService.config['Downloader']['use_youtubedl_archive'];
|
||||
}
|
||||
|
||||
goToFile(emit_obj) {
|
||||
const uid = emit_obj['uid'];
|
||||
const url = emit_obj['url'];
|
||||
localStorage.setItem('player_navigator', this.router.url);
|
||||
if (this.subscription.streamingOnly) {
|
||||
this.router.navigate(['/player', {uid: uid, url: url}]);
|
||||
} else {
|
||||
this.router.navigate(['/player', {uid: uid}]);
|
||||
}
|
||||
}
|
||||
|
||||
onSearchInputChanged(newvalue) {
|
||||
onSearchInputChanged(newvalue: string): void {
|
||||
if (newvalue.length > 0) {
|
||||
this.search_mode = true;
|
||||
this.filterFiles(newvalue);
|
||||
@@ -129,7 +119,7 @@ export class SubscriptionComponent implements OnInit, OnDestroy {
|
||||
this.filtered_files = this.files.filter(option => option.id.toLowerCase().includes(filterValue));
|
||||
}
|
||||
|
||||
filterByProperty(prop) {
|
||||
filterByProperty(prop: string): void {
|
||||
if (this.descendingMode) {
|
||||
this.filtered_files = this.filtered_files.sort((a, b) => (a[prop] > b[prop] ? -1 : 1));
|
||||
} else {
|
||||
@@ -142,17 +132,12 @@ export class SubscriptionComponent implements OnInit, OnDestroy {
|
||||
localStorage.setItem('filter_property', value['key']);
|
||||
}
|
||||
|
||||
toggleModeChange() {
|
||||
toggleModeChange(): void {
|
||||
this.descendingMode = !this.descendingMode;
|
||||
this.filterByProperty(this.filterProperty['property']);
|
||||
}
|
||||
|
||||
downloadContent() {
|
||||
const fileNames = [];
|
||||
for (let i = 0; i < this.files.length; i++) {
|
||||
fileNames.push(this.files[i].path);
|
||||
}
|
||||
|
||||
downloadContent(): void {
|
||||
this.downloading = true;
|
||||
this.postsService.downloadSubFromServer(this.subscription.id).subscribe(res => {
|
||||
this.downloading = false;
|
||||
@@ -164,7 +149,7 @@ export class SubscriptionComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
editSubscription() {
|
||||
editSubscription(): void {
|
||||
this.dialog.open(EditSubscriptionDialogComponent, {
|
||||
data: {
|
||||
sub: this.postsService.getSubscriptionByID(this.subscription.id)
|
||||
@@ -172,7 +157,7 @@ export class SubscriptionComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
watchSubscription() {
|
||||
watchSubscription(): void {
|
||||
this.router.navigate(['/player', {sub_id: this.subscription.id}])
|
||||
}
|
||||
|
||||
|
||||
@@ -592,10 +592,6 @@
|
||||
<context context-type="sourcefile">src/app/components/recent-videos/recent-videos.component.html</context>
|
||||
<context context-type="linenumber">24</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/subscription/subscription/subscription.component.html</context>
|
||||
<context context-type="linenumber">33</context>
|
||||
</context-group>
|
||||
<note priority="1" from="description">search field description</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="746f64ddd9001ac456327cd9a3d5152203a4b93c" datatype="html">
|
||||
@@ -682,21 +678,21 @@
|
||||
</context-group>
|
||||
<note priority="1" from="description">Edit role</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="d02888c485d3aeab6de628508f4a00312a722894" datatype="html">
|
||||
<source>My videos</source>
|
||||
<trans-unit id="52e0fa8ada52c3f29774a4508582fd98250b9f93" datatype="html">
|
||||
<source>My files</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/recent-videos/recent-videos.component.html</context>
|
||||
<context context-type="linenumber">20</context>
|
||||
</context-group>
|
||||
<note priority="1" from="description">My videos title</note>
|
||||
<note priority="1" from="description">My files title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="73423607944a694ce6f9e55cfee329681bb4d9f9" datatype="html">
|
||||
<source>No videos found.</source>
|
||||
<trans-unit id="6827066f436adfc56a142d5816a8be6113d73b01" datatype="html">
|
||||
<source>No files found.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/recent-videos/recent-videos.component.html</context>
|
||||
<context context-type="linenumber">38</context>
|
||||
</context-group>
|
||||
<note priority="1" from="description">No videos found</note>
|
||||
<note priority="1" from="description">No files found</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="b4e61d531b8db72449f043f122119da964f4fc54" datatype="html">
|
||||
<source>File type</source>
|
||||
@@ -1135,10 +1131,6 @@
|
||||
<context context-type="sourcefile">src/app/create-playlist/create-playlist.component.html</context>
|
||||
<context context-type="linenumber">20</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/subscription/subscription/subscription.component.html</context>
|
||||
<context context-type="linenumber">29</context>
|
||||
</context-group>
|
||||
<note priority="1" from="description">Videos title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="cec82c0a545f37420d55a9b6c45c20546e82f94e" datatype="html">
|
||||
|
||||
Reference in New Issue
Block a user