mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-03-20 03:30:55 +03:00
Created unified file card component, recent videos component (not done) and started scaffolding work on the backend
This commit is contained in:
@@ -2046,6 +2046,24 @@ app.post('/api/getFile', optionalJwt, function (req, res) {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/getAllFiles', optionalJwt, function (req, res) {
|
||||
files = null;
|
||||
playlists = null;
|
||||
if (req.isAuthenticated()) {
|
||||
const videos = auth_api.getUserVideos(req.user.uid, 'video');
|
||||
const audios = auth_api.getUserVideos(req.user.uid, 'audio');
|
||||
const audio_playlists = null;
|
||||
const video_playlists = null;
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
res.send({
|
||||
files: files,
|
||||
playlists: playlists
|
||||
})
|
||||
});
|
||||
|
||||
// video sharing
|
||||
app.post('/api/enableSharing', optionalJwt, function(req, res) {
|
||||
var type = req.body.type;
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
<a *ngIf="postsService.config && postsService.config.Advanced.multi_user_mode && !postsService.isLoggedIn" mat-list-item (click)="sidenav.close()" routerLink='/login'><ng-container i18n="Navigation menu Login Page title">Login</ng-container></a>
|
||||
<a *ngIf="postsService.config && allowSubscriptions && (!postsService.config.Advanced.multi_user_mode || (postsService.isLoggedIn && postsService.permissions.includes('subscriptions')))" mat-list-item (click)="sidenav.close()" routerLink='/subscriptions'><ng-container i18n="Navigation menu Subscriptions Page title">Subscriptions</ng-container></a>
|
||||
<a *ngIf="postsService.config && enableDownloadsManager && (!postsService.config.Advanced.multi_user_mode || (postsService.isLoggedIn && postsService.permissions.includes('downloads_manager')))" mat-list-item (click)="sidenav.close()" routerLink='/downloads'><ng-container i18n="Navigation menu Downloads Page title">Downloads</ng-container></a>
|
||||
<ng-container *ngIf="postsService.config && allowSubscriptions && subscriptions && (!postsService.config.Advanced.multi_user_mode || (postsService.isLoggedIn && postsService.permissions.includes('subscriptions')))">
|
||||
<mat-divider></mat-divider>
|
||||
<a *ngFor="let subscription of subscriptions" mat-list-item (click)="sidenav.close()" [routerLink]="['/subscription', { id: subscription.id }]"><ngx-avatar [style.margin-right]="'10px'" size="32" [name]="subscription.name"></ngx-avatar><ng-container i18n="Navigation menu Downloads Page title">{{subscription.name}}</ng-container></a>
|
||||
</ng-container>
|
||||
</mat-nav-list>
|
||||
</mat-sidenav>
|
||||
<mat-sidenav-content [style.background]="postsService.theme ? postsService.theme.background_color : null">
|
||||
|
||||
@@ -46,6 +46,8 @@ export class AppComponent implements OnInit {
|
||||
@ViewChild('hamburgerMenu', { read: ElementRef }) hamburgerMenuButton: ElementRef;
|
||||
navigator: string = null;
|
||||
|
||||
subscriptions = null;
|
||||
|
||||
constructor(public postsService: PostsService, public snackBar: MatSnackBar, private dialog: MatDialog,
|
||||
public router: Router, public overlayContainer: OverlayContainer, private elementRef: ElementRef) {
|
||||
|
||||
@@ -86,6 +88,13 @@ export class AppComponent implements OnInit {
|
||||
if (!localStorage.getItem('theme')) {
|
||||
this.setTheme(themingExists ? this.defaultTheme : 'default');
|
||||
}
|
||||
|
||||
// gets the subscriptions
|
||||
if (this.allowSubscriptions) {
|
||||
this.postsService.getAllSubscriptions().subscribe(res => {
|
||||
this.subscriptions = res['subscriptions'];
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// theme stuff
|
||||
@@ -162,6 +171,11 @@ onSetTheme(theme, old_theme) {
|
||||
}
|
||||
|
||||
|
||||
getSubscriptions() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
goBack() {
|
||||
if (!this.navigator) {
|
||||
this.router.navigate(['/home']);
|
||||
|
||||
@@ -53,6 +53,7 @@ import { SubscriptionInfoDialogComponent } from './dialogs/subscription-info-dia
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { NgxFileDropModule } from 'ngx-file-drop';
|
||||
import { AvatarModule } from 'ngx-avatar';
|
||||
|
||||
import es from '@angular/common/locales/es';
|
||||
import { AboutDialogComponent } from './dialogs/about-dialog/about-dialog.component';
|
||||
@@ -73,6 +74,8 @@ import { CookiesUploaderDialogComponent } from './dialogs/cookies-uploader-dialo
|
||||
import { LogsViewerComponent } from './components/logs-viewer/logs-viewer.component';
|
||||
import { ModifyPlaylistComponent } from './dialogs/modify-playlist/modify-playlist.component';
|
||||
import { ConfirmDialogComponent } from './dialogs/confirm-dialog/confirm-dialog.component';
|
||||
import { UnifiedFileCardComponent } from './components/unified-file-card/unified-file-card.component';
|
||||
import { RecentVideosComponent } from './components/recent-videos/recent-videos.component';
|
||||
|
||||
registerLocaleData(es, 'es');
|
||||
|
||||
@@ -113,7 +116,9 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible
|
||||
CookiesUploaderDialogComponent,
|
||||
LogsViewerComponent,
|
||||
ModifyPlaylistComponent,
|
||||
ConfirmDialogComponent
|
||||
ConfirmDialogComponent,
|
||||
UnifiedFileCardComponent,
|
||||
RecentVideosComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@@ -154,6 +159,7 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible
|
||||
DragDropModule,
|
||||
ClipboardModule,
|
||||
NgxFileDropModule,
|
||||
AvatarModule,
|
||||
VgCoreModule,
|
||||
VgControlsModule,
|
||||
VgOverlayPlayModule,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div *ngFor="let file of files" class="col-6 col-lg-4 mb-2 mt-2 file-col">
|
||||
<app-unified-file-card [file_obj]="file"></app-unified-file-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
.file-col {
|
||||
max-width: 240px;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RecentVideosComponent } from './recent-videos.component';
|
||||
|
||||
describe('RecentVideosComponent', () => {
|
||||
let component: RecentVideosComponent;
|
||||
let fixture: ComponentFixture<RecentVideosComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ RecentVideosComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RecentVideosComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
29
src/app/components/recent-videos/recent-videos.component.ts
Normal file
29
src/app/components/recent-videos/recent-videos.component.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PostsService } from 'app/posts.services';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recent-videos',
|
||||
templateUrl: './recent-videos.component.html',
|
||||
styleUrls: ['./recent-videos.component.scss']
|
||||
})
|
||||
export class RecentVideosComponent implements OnInit {
|
||||
|
||||
normal_files_received = false;
|
||||
subscription_files_received = false;
|
||||
files: any[] = null;
|
||||
|
||||
constructor(private postsService: PostsService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
getAllFiles() {
|
||||
|
||||
}
|
||||
|
||||
sortFiles(a, b) {
|
||||
// uses the 'registered' flag as the timestamp
|
||||
const result = b.registered - a.registered;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<div style="position: relative; width: fit-content;">
|
||||
<div class="duration-time">
|
||||
<ng-container i18n="Video duration label">Length:</ng-container> {{file_length}}
|
||||
</div>
|
||||
<button [matMenuTriggerFor]="action_menu" class="menuButton" mat-icon-button><mat-icon>more_vert</mat-icon></button>
|
||||
<mat-menu #action_menu="matMenu">
|
||||
<button (click)="openFileInfoDialog()" mat-menu-item><mat-icon>info</mat-icon><ng-container i18n="Video info button">Info</ng-container></button>
|
||||
<button (click)="deleteFile()" 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)="deleteFile(true)" mat-menu-item *ngIf="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)="navigateToFile()" matRipple class="example-card mat-elevation-z6">
|
||||
<div style="padding:5px">
|
||||
<div *ngIf="fileThumbnail" class="img-div">
|
||||
<img class="image" [src]="file_thumbnail" alt="Thumbnail">
|
||||
</div>
|
||||
|
||||
<span class="max-two-lines"><strong>{{file_title}}</strong></span>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
@@ -0,0 +1,76 @@
|
||||
.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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UnifiedFileCardComponent } from './unified-file-card.component';
|
||||
|
||||
describe('UnifiedFileCardComponent', () => {
|
||||
let component: UnifiedFileCardComponent;
|
||||
let fixture: ComponentFixture<UnifiedFileCardComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ UnifiedFileCardComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UnifiedFileCardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-unified-file-card',
|
||||
templateUrl: './unified-file-card.component.html',
|
||||
styleUrls: ['./unified-file-card.component.scss']
|
||||
})
|
||||
export class UnifiedFileCardComponent implements OnInit {
|
||||
|
||||
// required info
|
||||
file_title = '';
|
||||
file_length = '';
|
||||
file_thumbnail = '';
|
||||
type = null;
|
||||
use_youtubedl_archive = false;
|
||||
|
||||
isSubscriptionFile: boolean = null;
|
||||
|
||||
@Input() file_obj = null;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.file_length = fancyTimeFormat(this.file_obj.duration);
|
||||
}
|
||||
|
||||
deleteFile(blacklistMode = false) {
|
||||
|
||||
}
|
||||
|
||||
navigateToFile() {
|
||||
|
||||
}
|
||||
|
||||
openFileInfoDialog() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -108,4 +108,4 @@ function fancyTimeFormat(time) {
|
||||
ret += '' + mins + ':' + (secs < 10 ? '0' : '');
|
||||
ret += '' + secs;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PostsService } from 'app/posts.services';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-subscription',
|
||||
@@ -43,9 +43,26 @@ export class SubscriptionComponent implements OnInit {
|
||||
filterProperty = this.filterProperties['upload_date'];
|
||||
downloading = false;
|
||||
|
||||
initialized = false;
|
||||
|
||||
constructor(private postsService: PostsService, private route: ActivatedRoute, private router: Router) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.route.paramMap.subscribe((params: ParamMap) => {
|
||||
this.id = params.get('id');
|
||||
this.postsService.service_initialized.subscribe(init => {
|
||||
if (init) {
|
||||
this.initialized = true;
|
||||
this.getConfig();
|
||||
this.getSubscription();
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.initialized) {
|
||||
this.getConfig();
|
||||
this.getSubscription();
|
||||
}
|
||||
});
|
||||
if (this.route.snapshot.paramMap.get('id')) {
|
||||
this.id = this.route.snapshot.paramMap.get('id');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user