From 4f693d4eda5d28230d1112d96def19cda198abfc Mon Sep 17 00:00:00 2001 From: Isaac Abadi Date: Mon, 14 Dec 2020 18:19:50 -0500 Subject: [PATCH] Added description to player component and simplified the database by un-splitting videos and playlists by type --- backend/app.js | 150 +++++++++--------- backend/authentication/auth.js | 66 +++----- backend/db.js | 20 +-- backend/utils.js | 3 +- src/app/app.module.ts | 8 +- .../see-more/see-more.component.html | 11 ++ .../see-more/see-more.component.scss | 7 + .../see-more/see-more.component.spec.ts | 25 +++ .../components/see-more/see-more.component.ts | 60 +++++++ src/app/player/player.component.html | 30 ++-- 10 files changed, 235 insertions(+), 145 deletions(-) create mode 100644 src/app/components/see-more/see-more.component.html create mode 100644 src/app/components/see-more/see-more.component.scss create mode 100644 src/app/components/see-more/see-more.component.spec.ts create mode 100644 src/app/components/see-more/see-more.component.ts diff --git a/backend/app.js b/backend/app.js index 148e94c..b2d6446 100644 --- a/backend/app.js +++ b/backend/app.js @@ -13,7 +13,7 @@ var express = require("express"); var bodyParser = require("body-parser"); var archiver = require('archiver'); var unzipper = require('unzipper'); -var db_api = require('./db') +var db_api = require('./db'); var utils = require('./utils') var mergeFiles = require('merge-files'); const low = require('lowdb') @@ -87,14 +87,8 @@ categories_api.initialize(db, users_db, logger, db_api); // Set some defaults db.defaults( { - playlists: { - audio: [], - video: [] - }, - files: { - audio: [], - video: [] - }, + playlists: [], + files: [], configWriteFlag: false, downloads: {}, subscriptions: [], @@ -218,10 +212,12 @@ async function checkMigrations() { // 4.1->4.2 migration - const add_description_migration_complete = false; // db.get('add_description_migration_complete').value(); + const add_description_migration_complete = db.get('add_description_migration_complete').value(); if (!add_description_migration_complete) { logger.info('Beginning migration: 4.1->4.2+') - const success = await addMetadataPropertyToDB('description'); + let success = await simplifyDBFileStructure(); + success = success && await addMetadataPropertyToDB('view_count'); + success = success && await addMetadataPropertyToDB('description'); if (success) { logger.info('4.1->4.2+ migration complete!'); } else { logger.error('Migration failed: 4.1->4.2+'); } } @@ -229,6 +225,7 @@ async function checkMigrations() { return true; } +/* async function runFilesToDBMigration() { try { let mp3s = await getMp3s(); @@ -260,6 +257,37 @@ async function runFilesToDBMigration() { return false; } } +*/ + +async function simplifyDBFileStructure() { + let users = users_db.get('users').value(); + for (let i = 0; i < users.length; i++) { + const user = users[i]; + if (user['files']['video'] !== undefined && user['files']['audio'] !== undefined) { + const user_files = user['files']['video'].concat(user['files']['audio']); + const user_db_path = users_db.get('users').find({uid: user['uid']}); + user_db_path.assign({files: user_files}).write(); + } + if (user['playlists']['video'] !== undefined && user['playlists']['audio'] !== undefined) { + const user_playlists = user['playlists']['video'].concat(user['playlists']['audio']); + const user_db_path = users_db.get('users').find({uid: user['uid']}); + user_db_path.assign({playlists: user_playlists}).write(); + } + } + + if (db.get('files.video').value() !== undefined && db.get('files.audio').value() !== undefined) { + const files = db.get('files.video').value().concat(db.get('files.audio')); + db.assign({files: files}).write(); + } + + if (db.get('playlists.video').value() !== undefined && db.get('playlists.audio').value() !== undefined) { + const playlists = db.get('playlists.video').value().concat(db.get('playlists.audio')); + db.assign({playlists: playlists}).write(); + } + + + return true; +} async function addMetadataPropertyToDB(property_key) { try { @@ -592,6 +620,9 @@ async function loadConfig() { // creates archive path if missing await fs.ensureDir(archivePath); + // check migrations + await checkMigrations(); + // now this is done here due to youtube-dl's repo takedown await startYoutubeDL(); @@ -606,9 +637,6 @@ async function loadConfig() { db_api.importUnregisteredFiles(); - // check migrations - await checkMigrations(); - // load in previous downloads downloads = db.get('downloads').value(); @@ -1994,7 +2022,7 @@ async function addThumbnails(files) { // gets all download mp3s app.get('/api/getMp3s', optionalJwt, async function(req, res) { - var mp3s = db.get('files.audio').value(); // getMp3s(); + var mp3s = db.get('files').chain().find({isAudio: true}).value(); // getMp3s(); var playlists = db.get('playlists.audio').value(); const is_authenticated = req.isAuthenticated(); if (is_authenticated) { @@ -2020,8 +2048,8 @@ app.get('/api/getMp3s', optionalJwt, async function(req, res) { // gets all download mp4s app.get('/api/getMp4s', optionalJwt, async function(req, res) { - var mp4s = db.get('files.video').value(); // getMp4s(); - var playlists = db.get('playlists.video').value(); + var mp4s = db.get('files').chain().find({isAudio: false}).value(); // getMp4s(); + var playlists = db.get('playlists').value(); const is_authenticated = req.isAuthenticated(); if (is_authenticated) { @@ -2052,21 +2080,11 @@ app.post('/api/getFile', optionalJwt, function (req, res) { var file = null; if (req.isAuthenticated()) { - file = auth_api.getUserVideo(req.user.uid, uid, type); + file = auth_api.getUserVideo(req.user.uid, uid); } else if (uuid) { - file = auth_api.getUserVideo(uuid, uid, type, true); + file = auth_api.getUserVideo(uuid, uid, true); } else { - if (!type) { - file = db.get('files.audio').find({uid: uid}).value(); - if (!file) { - file = db.get('files.video').find({uid: uid}).value(); - if (file) type = 'video'; - } else { - type = 'audio'; - } - } - - if (!file && type) file = db.get(`files.${type}`).find({uid: uid}).value(); + file = db.get('files').find({uid: uid}).value(); } // check if chat exists for twitch videos @@ -2086,32 +2104,20 @@ app.post('/api/getFile', optionalJwt, function (req, res) { app.post('/api/getAllFiles', optionalJwt, async function (req, res) { // these are returned - let files = []; - let playlists = []; - let subscription_files = []; + let files = null; + let playlists = null; - let videos = null; - let audios = null; - let audio_playlists = null; - let video_playlists = null; let subscriptions = config_api.getConfigItem('ytdl_allow_subscriptions') ? (subscriptions_api.getAllSubscriptions(req.isAuthenticated() ? req.user.uid : null)) : []; // get basic info depending on multi-user mode being enabled if (req.isAuthenticated()) { - videos = auth_api.getUserVideos(req.user.uid, 'video'); - audios = auth_api.getUserVideos(req.user.uid, 'audio'); - audio_playlists = auth_api.getUserPlaylists(req.user.uid, 'audio'); - video_playlists = auth_api.getUserPlaylists(req.user.uid, 'video'); + files = auth_api.getUserVideos(req.user.uid); + playlists = auth_api.getUserPlaylists(req.user.uid); } else { - videos = db.get('files.audio').value(); - audios = db.get('files.video').value(); - audio_playlists = db.get('playlists.audio').value(); - video_playlists = db.get('playlists.video').value(); + files = db.get('files').value(); + playlists = db.get('playlists').value(); } - files = videos.concat(audios); - playlists = video_playlists.concat(audio_playlists); - // loop through subscriptions and add videos for (let i = 0; i < subscriptions.length; i++) { sub = subscriptions[i]; @@ -2187,14 +2193,13 @@ app.post('/api/downloadTwitchChatByVODID', optionalJwt, async (req, res) => { // video sharing app.post('/api/enableSharing', optionalJwt, function(req, res) { - var type = req.body.type; var uid = req.body.uid; var is_playlist = req.body.is_playlist; let success = false; // multi-user mode if (req.isAuthenticated()) { // if multi user mode, use this method instead - success = auth_api.changeSharingMode(req.user.uid, uid, type, is_playlist, true); + success = auth_api.changeSharingMode(req.user.uid, uid, is_playlist, true); res.send({success: success}); return; } @@ -2203,12 +2208,12 @@ app.post('/api/enableSharing', optionalJwt, function(req, res) { try { success = true; if (!is_playlist && type !== 'subscription') { - db.get(`files.${type}`) + db.get(`files`) .find({uid: uid}) .assign({sharingEnabled: true}) .write(); } else if (is_playlist) { - db.get(`playlists.${type}`) + db.get(`playlists`) .find({id: uid}) .assign({sharingEnabled: true}) .write(); @@ -2237,7 +2242,7 @@ app.post('/api/disableSharing', optionalJwt, function(req, res) { // multi-user mode if (req.isAuthenticated()) { // if multi user mode, use this method instead - success = auth_api.changeSharingMode(req.user.uid, uid, type, is_playlist, false); + success = auth_api.changeSharingMode(req.user.uid, uid, is_playlist, false); res.send({success: success}); return; } @@ -2246,12 +2251,12 @@ app.post('/api/disableSharing', optionalJwt, function(req, res) { try { success = true; if (!is_playlist && type !== 'subscription') { - db.get(`files.${type}`) + db.get(`files`) .find({uid: uid}) .assign({sharingEnabled: false}) .write(); } else if (is_playlist) { - db.get(`playlists.${type}`) + db.get(`playlists`) .find({id: uid}) .assign({sharingEnabled: false}) .write(); @@ -2544,7 +2549,7 @@ app.post('/api/createPlaylist', optionalJwt, async (req, res) => { if (req.isAuthenticated()) { auth_api.addPlaylist(req.user.uid, new_playlist, type); } else { - db.get(`playlists.${type}`) + db.get(`playlists`) .push(new_playlist) .write(); } @@ -2558,26 +2563,15 @@ app.post('/api/createPlaylist', optionalJwt, async (req, res) => { app.post('/api/getPlaylist', optionalJwt, async (req, res) => { let playlistID = req.body.playlistID; - let type = req.body.type; let uuid = req.body.uuid; let playlist = null; if (req.isAuthenticated()) { - playlist = auth_api.getUserPlaylist(uuid ? uuid : req.user.uid, playlistID, type); + playlist = auth_api.getUserPlaylist(uuid ? uuid : req.user.uid, playlistID); type = playlist.type; } else { - if (!type) { - playlist = db.get('playlists.audio').find({id: playlistID}).value(); - if (!playlist) { - playlist = db.get('playlists.video').find({id: playlistID}).value(); - if (playlist) type = 'video'; - } else { - type = 'audio'; - } - } - - if (!playlist) playlist = db.get(`playlists.${type}`).find({id: playlistID}).value(); + playlist = db.get(`playlists`).find({id: playlistID}).value(); } res.send({ @@ -2590,14 +2584,13 @@ app.post('/api/getPlaylist', optionalJwt, async (req, res) => { app.post('/api/updatePlaylistFiles', optionalJwt, async (req, res) => { let playlistID = req.body.playlistID; let fileNames = req.body.fileNames; - let type = req.body.type; let success = false; try { if (req.isAuthenticated()) { - auth_api.updatePlaylistFiles(req.user.uid, playlistID, fileNames, type); + auth_api.updatePlaylistFiles(req.user.uid, playlistID, fileNames); } else { - db.get(`playlists.${type}`) + db.get(`playlists`) .find({id: playlistID}) .assign({fileNames: fileNames}) .write(); @@ -2623,15 +2616,14 @@ app.post('/api/updatePlaylist', optionalJwt, async (req, res) => { app.post('/api/deletePlaylist', optionalJwt, async (req, res) => { let playlistID = req.body.playlistID; - let type = req.body.type; let success = null; try { if (req.isAuthenticated()) { - auth_api.removePlaylist(req.user.uid, playlistID, type); + auth_api.removePlaylist(req.user.uid, playlistID); } else { // removes playlist from playlists - db.get(`playlists.${type}`) + db.get(`playlists`) .remove({id: playlistID}) .write(); } @@ -2653,23 +2645,23 @@ app.post('/api/deleteFile', optionalJwt, async (req, res) => { var blacklistMode = req.body.blacklistMode; if (req.isAuthenticated()) { - let success = auth_api.deleteUserFile(req.user.uid, uid, type, blacklistMode); + let success = auth_api.deleteUserFile(req.user.uid, uid, blacklistMode); res.send(success); return; } - var file_obj = db.get(`files.${type}`).find({uid: uid}).value(); + var file_obj = db.get(`files`).find({uid: uid}).value(); var name = file_obj.id; var fullpath = file_obj ? file_obj.path : null; var wasDeleted = false; if (await fs.pathExists(fullpath)) { wasDeleted = type === 'audio' ? await deleteAudioFile(name, path.basename(fullpath), blacklistMode) : await deleteVideoFile(name, path.basename(fullpath), blacklistMode); - db.get('files.video').remove({uid: uid}).write(); + db.get('files').remove({uid: uid}).write(); // wasDeleted = true; res.send(wasDeleted); } else if (video_obj) { - db.get('files.video').remove({uid: uid}).write(); + db.get('files').remove({uid: uid}).write(); wasDeleted = true; res.send(wasDeleted); } else { diff --git a/backend/authentication/auth.js b/backend/authentication/auth.js index 9fdc7e7..3c77edd 100644 --- a/backend/authentication/auth.js +++ b/backend/authentication/auth.js @@ -281,24 +281,13 @@ exports.adminExists = function() { // video stuff -exports.getUserVideos = function(user_uid, type) { +exports.getUserVideos = function(user_uid) { const user = users_db.get('users').find({uid: user_uid}).value(); - return user['files'][type]; + return user['files']; } -exports.getUserVideo = function(user_uid, file_uid, type, requireSharing = false) { - let file = null; - if (!type) { - file = users_db.get('users').find({uid: user_uid}).get(`files.audio`).find({uid: file_uid}).value(); - if (!file) { - file = users_db.get('users').find({uid: user_uid}).get(`files.video`).find({uid: file_uid}).value(); - if (file) type = 'video'; - } else { - type = 'audio'; - } - } - - if (!file && type) file = users_db.get('users').find({uid: user_uid}).get(`files.${type}`).find({uid: file_uid}).value(); +exports.getUserVideo = function(user_uid, file_uid, requireSharing = false) { + let file = users_db.get('users').find({uid: user_uid}).get(`files`).find({uid: file_uid}).value(); // prevent unauthorized users from accessing the file info if (file && !file['sharingEnabled'] && requireSharing) file = null; @@ -306,38 +295,28 @@ exports.getUserVideo = function(user_uid, file_uid, type, requireSharing = false return file; } -exports.addPlaylist = function(user_uid, new_playlist, type) { - users_db.get('users').find({uid: user_uid}).get(`playlists.${type}`).push(new_playlist).write(); +exports.addPlaylist = function(user_uid, new_playlist) { + users_db.get('users').find({uid: user_uid}).get(`playlists`).push(new_playlist).write(); return true; } -exports.updatePlaylistFiles = function(user_uid, playlistID, new_filenames, type) { - users_db.get('users').find({uid: user_uid}).get(`playlists.${type}`).find({id: playlistID}).assign({fileNames: new_filenames}); +exports.updatePlaylistFiles = function(user_uid, playlistID, new_filenames) { + users_db.get('users').find({uid: user_uid}).get(`playlists`).find({id: playlistID}).assign({fileNames: new_filenames}); return true; } -exports.removePlaylist = function(user_uid, playlistID, type) { - users_db.get('users').find({uid: user_uid}).get(`playlists.${type}`).remove({id: playlistID}).write(); +exports.removePlaylist = function(user_uid, playlistID) { + users_db.get('users').find({uid: user_uid}).get(`playlists`).remove({id: playlistID}).write(); return true; } -exports.getUserPlaylists = function(user_uid, type) { +exports.getUserPlaylists = function(user_uid) { const user = users_db.get('users').find({uid: user_uid}).value(); - return user['playlists'][type]; + return user['playlists']; } -exports.getUserPlaylist = function(user_uid, playlistID, type, requireSharing = false) { - let playlist = null; - if (!type) { - playlist = users_db.get('users').find({uid: user_uid}).get(`playlists.audio`).find({id: playlistID}).value(); - if (!playlist) { - playlist = users_db.get('users').find({uid: user_uid}).get(`playlists.video`).find({id: playlistID}).value(); - if (playlist) type = 'video'; - } else { - type = 'audio'; - } - } - if (!playlist) playlist = users_db.get('users').find({uid: user_uid}).get(`playlists.${type}`).find({id: playlistID}).value(); +exports.getUserPlaylist = function(user_uid, playlistID, requireSharing = false) { + let playlist = users_db.get('users').find({uid: user_uid}).get(`playlists`).find({id: playlistID}).value(); // prevent unauthorized users from accessing the file info if (requireSharing && !playlist['sharingEnabled']) playlist = null; @@ -345,21 +324,22 @@ exports.getUserPlaylist = function(user_uid, playlistID, type, requireSharing = return playlist; } -exports.registerUserFile = function(user_uid, file_object, type) { - users_db.get('users').find({uid: user_uid}).get(`files.${type}`) +exports.registerUserFile = function(user_uid, file_object) { + users_db.get('users').find({uid: user_uid}).get(`files`) .remove({ path: file_object['path'] }).write(); - users_db.get('users').find({uid: user_uid}).get(`files.${type}`) + users_db.get('users').find({uid: user_uid}).get(`files`) .push(file_object) .write(); } -exports.deleteUserFile = async function(user_uid, file_uid, type, blacklistMode = false) { +exports.deleteUserFile = async function(user_uid, file_uid, blacklistMode = false) { let success = false; - const file_obj = users_db.get('users').find({uid: user_uid}).get(`files.${type}`).find({uid: file_uid}).value(); + const file_obj = users_db.get('users').find({uid: user_uid}).get(`files`).find({uid: file_uid}).value(); if (file_obj) { + const type = file_obj.isAudio ? 'audio' : 'video'; const usersFileFolder = config_api.getConfigItem('ytdl_users_base_path'); const ext = type === 'audio' ? '.mp3' : '.mp4'; @@ -375,7 +355,7 @@ exports.deleteUserFile = async function(user_uid, file_uid, type, blacklistMode } const full_path = path.join(usersFileFolder, user_uid, type, file_obj.id + ext); - users_db.get('users').find({uid: user_uid}).get(`files.${type}`) + users_db.get('users').find({uid: user_uid}).get(`files`) .remove({ uid: file_uid }).write(); @@ -424,11 +404,11 @@ exports.deleteUserFile = async function(user_uid, file_uid, type, blacklistMode return success; } -exports.changeSharingMode = function(user_uid, file_uid, type, is_playlist, enabled) { +exports.changeSharingMode = function(user_uid, file_uid, is_playlist, enabled) { let success = false; const user_db_obj = users_db.get('users').find({uid: user_uid}); if (user_db_obj.value()) { - const file_db_obj = is_playlist ? user_db_obj.get(`playlists.${type}`).find({id: file_uid}) : user_db_obj.get(`files.${type}`).find({uid: file_uid}); + const file_db_obj = is_playlist ? user_db_obj.get(`playlists`).find({id: file_uid}) : user_db_obj.get(`files`).find({uid: file_uid}); if (file_db_obj.value()) { success = true; file_db_obj.assign({sharingEnabled: enabled}).write(); diff --git a/backend/db.js b/backend/db.js index 9436715..f95b43f 100644 --- a/backend/db.js +++ b/backend/db.js @@ -32,9 +32,9 @@ function registerFileDB(file_path, type, multiUserMode = null, sub = null, custo if (!sub) { if (multiUserMode) { const user_uid = multiUserMode.user; - db_path = users_db.get('users').find({uid: user_uid}).get(`files.${type}`); + db_path = users_db.get('users').find({uid: user_uid}).get(`files`); } else { - db_path = db.get(`files.${type}`) + db_path = db.get(`files`); } } else { if (multiUserMode) { @@ -94,18 +94,18 @@ function generateFileObject(id, type, customPath = null, sub = null) { var thumbnail = jsonobj.thumbnail; var duration = jsonobj.duration; var isaudio = type === 'audio'; - var file_obj = new utils.File(id, title, thumbnail, isaudio, duration, url, uploader, size, file_path, upload_date); + var description = jsonobj.description; + var file_obj = new utils.File(id, title, thumbnail, isaudio, duration, url, uploader, size, file_path, upload_date, description); return file_obj; } function updatePlaylist(playlist, user_uid) { let playlistID = playlist.id; - let type = playlist.type; let db_loc = null; if (user_uid) { - db_loc = users_db.get('users').find({uid: user_uid}).get(`playlists.${type}`).find({id: playlistID}); + db_loc = users_db.get('users').find({uid: user_uid}).get(`playlists`).find({id: playlistID}); } else { - db_loc = db.get(`playlists.${type}`).find({id: playlistID}); + db_loc = db.get(`playlists`).find({id: playlistID}); } db_loc.assign(playlist).write(); return true; @@ -132,14 +132,14 @@ function getFileDirectoriesAndDBs() { // add user's audio dir to check list dirs_to_check.push({ basePath: path.join(usersFileFolder, user.uid, 'audio'), - dbPath: users_db.get('users').find({uid: user.uid}).get('files.audio'), + dbPath: users_db.get('users').find({uid: user.uid}).get('files'), type: 'audio' }); // add user's video dir to check list dirs_to_check.push({ basePath: path.join(usersFileFolder, user.uid, 'video'), - dbPath: users_db.get('users').find({uid: user.uid}).get('files.video'), + dbPath: users_db.get('users').find({uid: user.uid}).get('files'), type: 'video' }); } @@ -153,14 +153,14 @@ function getFileDirectoriesAndDBs() { // add audio dir to check list dirs_to_check.push({ basePath: audioFolderPath, - dbPath: db.get('files.audio'), + dbPath: db.get('files'), type: 'audio' }); // add video dir to check list dirs_to_check.push({ basePath: videoFolderPath, - dbPath: db.get('files.video'), + dbPath: db.get('files'), type: 'video' }); } diff --git a/backend/utils.js b/backend/utils.js index 33b877a..988a112 100644 --- a/backend/utils.js +++ b/backend/utils.js @@ -189,7 +189,7 @@ async function recFindByExt(base,ext,files,result) // objects -function File(id, title, thumbnailURL, isAudio, duration, url, uploader, size, path, upload_date) { +function File(id, title, thumbnailURL, isAudio, duration, url, uploader, size, path, upload_date, description) { this.id = id; this.title = title; this.thumbnailURL = thumbnailURL; @@ -200,6 +200,7 @@ function File(id, title, thumbnailURL, isAudio, duration, url, uploader, size, p this.size = size; this.path = path; this.upload_date = upload_date; + this.description = description; } module.exports = { diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 72c2658..3f9a119 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -81,6 +81,7 @@ import { EditSubscriptionDialogComponent } from './dialogs/edit-subscription-dia import { CustomPlaylistsComponent } from './components/custom-playlists/custom-playlists.component'; import { EditCategoryDialogComponent } from './dialogs/edit-category-dialog/edit-category-dialog.component'; import { TwitchChatComponent } from './components/twitch-chat/twitch-chat.component'; +import { LinkifyPipe, SeeMoreComponent } from './components/see-more/see-more.component'; registerLocaleData(es, 'es'); @@ -107,6 +108,7 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible VideoInfoDialogComponent, ArgModifierDialogComponent, HighlightPipe, + LinkifyPipe, UpdaterComponent, UpdateProgressDialogComponent, ShareMediaDialogComponent, @@ -127,7 +129,8 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible EditSubscriptionDialogComponent, CustomPlaylistsComponent, EditCategoryDialogComponent, - TwitchChatComponent + TwitchChatComponent, + SeeMoreComponent ], imports: [ CommonModule, @@ -188,7 +191,8 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible PostsService ], exports: [ - HighlightPipe + HighlightPipe, + LinkifyPipe ], bootstrap: [AppComponent] }) diff --git a/src/app/components/see-more/see-more.component.html b/src/app/components/see-more/see-more.component.html new file mode 100644 index 0000000..297d820 --- /dev/null +++ b/src/app/components/see-more/see-more.component.html @@ -0,0 +1,11 @@ + + + + + See more. + + + See less. + + + \ No newline at end of file diff --git a/src/app/components/see-more/see-more.component.scss b/src/app/components/see-more/see-more.component.scss new file mode 100644 index 0000000..1843c11 --- /dev/null +++ b/src/app/components/see-more/see-more.component.scss @@ -0,0 +1,7 @@ +.text { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + word-wrap: break-word; + } \ No newline at end of file diff --git a/src/app/components/see-more/see-more.component.spec.ts b/src/app/components/see-more/see-more.component.spec.ts new file mode 100644 index 0000000..608bee6 --- /dev/null +++ b/src/app/components/see-more/see-more.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SeeMoreComponent } from './see-more.component'; + +describe('SeeMoreComponent', () => { + let component: SeeMoreComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SeeMoreComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SeeMoreComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/see-more/see-more.component.ts b/src/app/components/see-more/see-more.component.ts new file mode 100644 index 0000000..8573cb9 --- /dev/null +++ b/src/app/components/see-more/see-more.component.ts @@ -0,0 +1,60 @@ +import { Component, Input, OnInit, Pipe, PipeTransform } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; + +@Pipe({ name: 'linkify' }) +export class LinkifyPipe implements PipeTransform { + + constructor(private _domSanitizer: DomSanitizer) {} + + transform(value: any, args?: any): any { + return this._domSanitizer.bypassSecurityTrustHtml(this.stylize(value)); + } + + // Modify this method according to your custom logic + private stylize(text: string): string { + let stylizedText: string = ''; + if (text && text.length > 0) { + for (let line of text.split("\n")) { + for (let t of line.split(" ")) { + if (t.startsWith("http") && t.length>7) { + stylizedText += `${t} `; + } + else + stylizedText += t + " "; + } + stylizedText += '
'; + } + return stylizedText; + } + else return text; + } + +} + +@Component({ + selector: 'app-see-more', + templateUrl: './see-more.component.html', + providers: [LinkifyPipe], + styleUrls: ['./see-more.component.scss'] +}) +export class SeeMoreComponent implements OnInit { + + see_more_active = false; + + @Input() text = ''; + @Input() line_limit = 2; + + constructor() { } + + ngOnInit(): void { + } + + toggleSeeMore() { + this.see_more_active = !this.see_more_active; + } + + parseText() { + return this.text.replace(/(http.*?\s)/, "$1") + } + +} diff --git a/src/app/player/player.component.html b/src/app/player/player.component.html index 73ea9eb..a328561 100644 --- a/src/app/player/player.component.html +++ b/src/app/player/player.component.html @@ -8,14 +8,28 @@ -
+
-
- {{file_obj['local_play_count'] ? file_obj['local_play_count'] : 0}} views +
+ {{db_file['local_view_count'] ? db_file['local_view_count'] : 0}} views
-
- +
+ +

+ +

+
+ +

+ No description available. +

+
+
+
+
+ +
@@ -25,15 +39,11 @@ {{playlist_item.label}}
- + - -
- -