Skip to content

Commit

Permalink
Added ability to add file to playlist using the context menu
Browse files Browse the repository at this point in the history
  • Loading branch information
Tzahi12345 committed Jul 27, 2021
1 parent 7174ef5 commit 92413bd
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 37 deletions.
47 changes: 28 additions & 19 deletions backend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -754,20 +754,6 @@ function generateEnvVarConfigItem(key) {
return {key: key, value: process['env'][key]};
}

function getThumbnailMp3(name)
{
var obj = utils.getJSONMp3(name, audioFolderPath);
var thumbnailLink = obj.thumbnail;
return thumbnailLink;
}

function getThumbnailMp4(name)
{
var obj = utils.getJSONMp4(name, videoFolderPath);
var thumbnailLink = obj.thumbnail;
return thumbnailLink;
}

function getFileSizeMp3(name)
{
var jsonPath = audioFolderPath+name+".mp3.info.json";
Expand Down Expand Up @@ -1061,7 +1047,7 @@ async function downloadFileByURL_exec(url, type, options, sessionID = null) {
// create playlist
const playlist_name = file_objs.map(file_obj => file_obj.title).join(', ');
const duration = file_objs.reduce((a, b) => a + utils.durationStringToNumber(b.duration), 0);
container = await db_api.createPlaylist(playlist_name, file_objs.map(file_obj => file_obj.uid), type, file_objs[0]['thumbnailURL'], options.user);
container = await db_api.createPlaylist(playlist_name, file_objs.map(file_obj => file_obj.uid), type, options.user);
} else if (file_objs.length === 1) {
container = file_objs[0];
} else {
Expand Down Expand Up @@ -2181,9 +2167,8 @@ app.post('/api/createPlaylist', optionalJwt, async (req, res) => {
let playlistName = req.body.playlistName;
let uids = req.body.uids;
let type = req.body.type;
let thumbnailURL = req.body.thumbnailURL;

const new_playlist = await db_api.createPlaylist(playlistName, uids, type, thumbnailURL, req.isAuthenticated() ? req.user.uid : null);
const new_playlist = await db_api.createPlaylist(playlistName, uids, type, req.isAuthenticated() ? req.user.uid : null);

res.send({
new_playlist: new_playlist,
Expand Down Expand Up @@ -2216,8 +2201,18 @@ app.post('/api/getPlaylist', optionalJwt, async (req, res) => {
});
});

app.post('/api/getPlaylists', optionalJwt, async (req, res) => {
const uuid = req.isAuthenticated() ? req.user.uid : null;

const playlists = await db_api.getRecords('playlists', {user_uid: uuid});

res.send({
playlists: playlists
});
});

app.post('/api/updatePlaylistFiles', optionalJwt, async (req, res) => {
let playlistID = req.body.playlistID;
let playlistID = req.body.playlist_id;
let uids = req.body.uids;

let success = false;
Expand All @@ -2238,6 +2233,20 @@ app.post('/api/updatePlaylistFiles', optionalJwt, async (req, res) => {
})
});

app.post('/api/addFileToPlaylist', optionalJwt, async (req, res) => {
let playlist_id = req.body.playlist_id;
let file_uid = req.body.file_uid;

const playlist = await db_api.getRecord('playlists', {id: playlist_id});

playlist.uids.push(file_uid);

let success = await db_api.updatePlaylist(playlist);
res.send({
success: success
});
});

app.post('/api/updatePlaylist', optionalJwt, async (req, res) => {
let playlist = req.body.playlist;
let success = await db_api.updatePlaylist(playlist, req.user && req.user.uid);
Expand All @@ -2247,7 +2256,7 @@ app.post('/api/updatePlaylist', optionalJwt, async (req, res) => {
});

app.post('/api/deletePlaylist', optionalJwt, async (req, res) => {
let playlistID = req.body.playlistID;
let playlistID = req.body.playlist_id;

let success = null;
try {
Expand Down
23 changes: 13 additions & 10 deletions backend/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,23 +411,26 @@ exports.addMetadataPropertyToDB = async (property_key) => {
}
}

exports.createPlaylist = async (playlist_name, uids, type, thumbnail_url, user_uid = null) => {
exports.createPlaylist = async (playlist_name, uids, type, user_uid = null) => {
const first_video = await exports.getVideo(uids[0]);
const thumbnailToUse = first_video['thumbnailURL'];

let new_playlist = {
name: playlist_name,
uids: uids,
id: uuid(),
thumbnailURL: thumbnail_url,
thumbnailURL: thumbnailToUse,
type: type,
registered: Date.now(),
randomize_order: false
};

const duration = await exports.calculatePlaylistDuration(new_playlist, user_uid);
new_playlist.duration = duration;

new_playlist.user_uid = user_uid ? user_uid : undefined;

await exports.insertRecordIntoTable('playlists', new_playlist);

const duration = await exports.calculatePlaylistDuration(new_playlist);
await exports.updateRecord('playlists', {id: new_playlist.id}, {duration: duration});

return new_playlist;
}
Expand Down Expand Up @@ -463,10 +466,10 @@ exports.getPlaylist = async (playlist_id, user_uid = null, require_sharing = fal
return playlist;
}

exports.updatePlaylist = async (playlist, user_uid = null) => {
exports.updatePlaylist = async (playlist) => {
let playlistID = playlist.id;

const duration = await exports.calculatePlaylistDuration(playlist, user_uid);
const duration = await exports.calculatePlaylistDuration(playlist);
playlist.duration = duration;

return await exports.updateRecord('playlists', {id: playlistID}, playlist);
Expand All @@ -486,12 +489,12 @@ exports.setPlaylistProperty = async (playlist_id, assignment_obj, user_uid = nul
return success;
}

exports.calculatePlaylistDuration = async (playlist, uuid, playlist_file_objs = null) => {
exports.calculatePlaylistDuration = async (playlist, playlist_file_objs = null) => {
if (!playlist_file_objs) {
playlist_file_objs = [];
for (let i = 0; i < playlist['uids'].length; i++) {
const uid = playlist['uids'][i];
const file_obj = await exports.getVideo(uid, uuid);
const file_obj = await exports.getVideo(uid);
if (file_obj) playlist_file_objs.push(file_obj);
}
}
Expand Down Expand Up @@ -588,7 +591,7 @@ exports.getVideoUIDByID = async (file_id, uuid = null) => {
return file_obj ? file_obj['uid'] : null;
}

exports.getVideo = async (file_uid, uuid = null, sub_id = null) => {
exports.getVideo = async (file_uid) => {
return await exports.getRecord('files', {uid: file_uid});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,17 @@ export class CustomPlaylistsComponent implements OnInit {
this.getAllPlaylists();
}
});

this.postsService.playlists_changed.subscribe(changed => {
if (changed) {
this.getAllPlaylists();
}
});
}

getAllPlaylists() {
this.playlists_received = false;
// must call getAllFiles as we need to get category playlists as well
this.postsService.getAllFiles().subscribe(res => {
this.playlists = res['playlists'];
this.playlists_received = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ <h4 class="my-videos-title" i18n="My videos title">My videos</h4>
<div class="row justify-content-center">
<ng-container *ngIf="normal_files_received && paged_data">
<div *ngFor="let file of paged_data; let i = index" class="mb-2 mt-2 d-flex justify-content-center" [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" [locale]="postsService.locale" (goToFile)="goToFile($event)" (goToSubscription)="goToSubscription($event)" [file_obj]="file" [use_youtubedl_archive]="postsService.config['Downloader']['use_youtubedl_archive']" [loading]="false" (deleteFile)="deleteFile($event)" [baseStreamPath]="postsService.path" [jwtString]="postsService.isLoggedIn ? '?jwt=' + this.postsService.token : ''"></app-unified-file-card>
<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 ? '?jwt=' + this.postsService.token : ''"></app-unified-file-card>
</div>
<div *ngIf="filtered_files.length === 0">
<ng-container i18n="No videos found">No videos found.</ng-container>
Expand Down
38 changes: 38 additions & 0 deletions src/app/components/recent-videos/recent-videos.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export class RecentVideosComponent implements OnInit {
}
};
filterProperty = this.filterProperties['upload_date'];

playlists = null;

pageSize = 10;
paged_data = null;
Expand All @@ -68,14 +70,27 @@ export class RecentVideosComponent implements OnInit {
ngOnInit(): void {
if (this.postsService.initialized) {
this.getAllFiles();
this.getAllPlaylists();
}

this.postsService.service_initialized.subscribe(init => {
if (init) {
this.getAllFiles();
this.getAllPlaylists();
}
});

this.postsService.files_changed.subscribe(changed => {
if (changed) {
this.getAllFiles();
}
});

this.postsService.playlists_changed.subscribe(changed => {
if (changed) {
this.getAllPlaylists();
}
});

// set filter property to cached
const cached_filter_property = localStorage.getItem('filter_property');
Expand All @@ -84,6 +99,12 @@ export class RecentVideosComponent implements OnInit {
}
}

getAllPlaylists() {
this.postsService.getPlaylists().subscribe(res => {
this.playlists = res['playlists'];
});
}

// search

onSearchInputChanged(newvalue) {
Expand Down Expand Up @@ -288,6 +309,23 @@ export class RecentVideosComponent implements OnInit {
this.filterByProperty(this.filterProperty['property']);
}

addFileToPlaylist(info_obj) {
const file = info_obj['file'];
const playlist_id = info_obj['playlist_id'];
const playlist = this.playlists.find(potential_playlist => potential_playlist['id'] === playlist_id);
this.postsService.addFileToPlaylist(playlist_id, file['uid']).subscribe(res => {
if (res['success']) {
this.postsService.openSnackBar(`Successfully added ${file.title} to ${playlist.title}!`);
this.postsService.playlists_changed.next(true);
} else {
this.postsService.openSnackBar(`Failed to add ${file.title} to ${playlist.title}! Unknown error.`);
}
}, err => {
console.error(err);
this.postsService.openSnackBar(`Failed to add ${file.title} to ${playlist.title}! See browser console for error.`);
});
}

// sorting and filtering

sortFiles(a, b) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
<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>
<button *ngIf="availablePlaylists" [matMenuTriggerFor]="addtoplaylist" mat-menu-item><mat-icon>playlist_add</mat-icon>&nbsp;<ng-container i18n="Add to playlist menu item">Add to playlist</ng-container></button>
<mat-menu #addtoplaylist="matMenu">
<button *ngFor="let playlist of availablePlaylists" [disabled]="playlist.uids?.includes(file_obj.uid)" (click)="emitAddFileToPlaylist(playlist.id)" mat-menu-item>{{playlist.name}}</button>
</mat-menu>
<mat-divider></mat-divider>
<button *ngIf="file_obj.sub_id" (click)="emitDeleteFile()" mat-menu-item>
<mat-icon>restore</mat-icon><ng-container i18n="Delete and redownload subscription video button">Delete and redownload</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ export class UnifiedFileCardComponent implements OnInit {
@Input() locale = null;
@Input() baseStreamPath = null;
@Input() jwtString = null;
@Input() availablePlaylists = null;
@Output() goToFile = new EventEmitter<any>();
@Output() goToSubscription = new EventEmitter<any>();
@Output() deleteFile = new EventEmitter<any>();
@Output() addFileToPlaylist = new EventEmitter<any>();
@Output() editPlaylist = new EventEmitter<any>();


Expand Down Expand Up @@ -86,6 +88,13 @@ export class UnifiedFileCardComponent implements OnInit {
});
}

emitAddFileToPlaylist(playlist_id) {
this.addFileToPlaylist.emit({
file: this.file_obj,
playlist_id: playlist_id
});
}

navigateToFile(event) {
this.goToFile.emit({file: this.file_obj, event: event});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export class ModifyPlaylistComponent implements OnInit {
this.playlist_updated = true;
this.postsService.openSnackBar('Playlist updated successfully.');
this.getPlaylist();
this.postsService.playlists_changed.next(true);
});
}

Expand Down
4 changes: 1 addition & 3 deletions src/app/main/main.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -951,8 +951,6 @@ export class MainComponent implements OnInit {
}

reloadRecentVideos() {
if (this.recentVideos) {
this.recentVideos.getAllFiles();
}
this.postsService.files_changed.next(true);
}
}
21 changes: 17 additions & 4 deletions src/app/posts.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export class PostsService implements CanActivate {
settings_changed = new BehaviorSubject<boolean>(false);
open_create_default_admin_dialog = new BehaviorSubject<boolean>(false);

files_changed = new BehaviorSubject<boolean>(false);
playlists_changed = new BehaviorSubject<boolean>(false);

// app status
initialized = false;

Expand Down Expand Up @@ -334,18 +337,28 @@ export class PostsService implements CanActivate {
include_file_metadata: include_file_metadata}, this.httpOptions);
}

getPlaylists() {
return this.http.post(this.path + 'getPlaylists', {}, this.httpOptions);
}

updatePlaylist(playlist) {
return this.http.post(this.path + 'updatePlaylist', {playlist: playlist}, this.httpOptions);
}

updatePlaylistFiles(playlistID, fileNames, type) {
return this.http.post(this.path + 'updatePlaylistFiles', {playlistID: playlistID,
updatePlaylistFiles(playlist_id, fileNames, type) {
return this.http.post(this.path + 'updatePlaylistFiles', {playlist_id: playlist_id,
fileNames: fileNames,
type: type}, this.httpOptions);
}

removePlaylist(playlistID, type) {
return this.http.post(this.path + 'deletePlaylist', {playlistID: playlistID, type: type}, this.httpOptions);
addFileToPlaylist(playlist_id, file_uid) {
return this.http.post(this.path + 'addFileToPlaylist', {playlist_id: playlist_id,
file_uid: file_uid},
this.httpOptions);
}

removePlaylist(playlist_id, type) {
return this.http.post(this.path + 'deletePlaylist', {playlist_id: playlist_id, type: type}, this.httpOptions);
}

// categories
Expand Down

0 comments on commit 92413bd

Please sign in to comment.