diff --git a/package.json b/package.json index 7cfb839c4..e19efb21f 100644 --- a/package.json +++ b/package.json @@ -1,61 +1,79 @@ { - "name": "FreeTube", - "productName": "FreeTube", - "version": "0.3.2", - "description": "An Open Source YouTube app for privacy.", - "main": "src/js/init.js", - "scripts": { - "start": "electron-forge start", - "package": "electron-forge package", - "make": "electron-forge make", - "publish": "electron-forge publish", - "make:all": "npm run make:mac && npm run make:linux:x86 && npm run make:linux:arm && npm run make:win", - "make:mac": "electron-forge make --platform=darwin", - "make:win": "electron-forge make --platform=win32", - "make:win:zip": "electron-forge make --platform=win32 --targets=zip", - "make:linux:x86": "electron-forge make --platform=linux --arch x64", - "make:linux:x86:zip": "electron-forge make --platform=linux --targets=zip --arch x64", - "make:linux:x86:deb": "electron-forge make --platform=linux --targets=deb --arch x64", - "make:linux:x86:rpm": "electron-forge make --platform=linux --targets=rpm --arch x64", - "make:linux:x86:snap": "electron-forge package && electron-installer-snap --src=out/FreeTube-linux-x64 --arch x64", - "make:linux:x86:flatpak": "electron-installer-flatpak --src out/FreeTube-linux-x64/ --dest out/make --arch x64", - "make:linux:x86:appimage": "electron-forge make --platform=linux --targets=electron-forge-maker-appimage --arch x64", - "make:linux:arm": "electron-forge make --platform=linux --arch arm64", - "make:linux:arm:zip": "electron-forge make --platform=linux --targets=zip --arch arm64", - "make:linux:arm:deb": "electron-forge make --platform=linux --targets=deb --arch arm64", - "make:linux:arm:rpm": "electron-forge make --platform=linux --targets=rpm --arch arm64", - "make:linux:arm:appimage": "electron-forge make --platform=linux --targets=electron-forge-maker-appimage --arch arm64" - }, - "keywords": [], - "author": { - "name": "PrestonN", - "email": "FreeTubeApp@protonmail.com", - "url": "https://github.com/FreeTubeApp/FreeTube" - }, - "license": "GPL-3.0-or-later", - "config": { - "forge": { - "make_targets": { - "win32": [ - "squirrel" - ], - "darwin": [ - "zip" - ], - "linux": [ - "deb", - "rpm", - "electron-forge-maker-appimage", - "zip" - ] - }, - "protocols": [ - { - "name": "freetube", - "role": "Viewer", - "schemes": [ - "freetube" - ] + "name": "FreeTube", + "productName": "FreeTube", + "version": "0.3.2", + "description": "An Open Source YouTube app for privacy.", + "main": "src/js/init.js", + "scripts": { + "start": "electron-forge start", + "package": "electron-forge package", + "make": "electron-forge make", + "publish": "electron-forge publish", + "make:all": "npm run make:mac && npm run make:linux:x86 && npm run make:linux:arm && npm run make:win", + "make:mac": "electron-forge make --platform=darwin", + "make:win": "electron-forge make --platform=win32", + "make:win:zip": "electron-forge make --platform=win32 --targets=zip", + "make:linux:x86": "electron-forge make --platform=linux --arch x64", + "make:linux:x86:zip": "electron-forge make --platform=linux --targets=zip --arch x64", + "make:linux:x86:deb": "electron-forge make --platform=linux --targets=deb --arch x64", + "make:linux:x86:rpm": "electron-forge make --platform=linux --targets=rpm --arch x64", + "make:linux:x86:snap": "electron-forge package && electron-installer-snap --src=out/FreeTube-linux-x64 --arch x64", + "make:linux:x86:flatpak": "electron-installer-flatpak --src out/FreeTube-linux-x64/ --dest out/make --arch x64", + "make:linux:x86:appimage": "electron-forge make --platform=linux --targets=electron-forge-maker-appimage --arch x64", + "make:linux:arm": "electron-forge make --platform=linux --arch arm64", + "make:linux:arm:zip": "electron-forge make --platform=linux --targets=zip --arch arm64", + "make:linux:arm:deb": "electron-forge make --platform=linux --targets=deb --arch arm64", + "make:linux:arm:rpm": "electron-forge make --platform=linux --targets=rpm --arch arm64", + "make:linux:arm:appimage": "electron-forge make --platform=linux --targets=electron-forge-maker-appimage --arch arm64" + }, + "keywords": [], + "author": { + "name": "PrestonN", + "email": "FreeTubeApp@protonmail.com", + "url": "https://github.com/FreeTubeApp/FreeTube" + }, + "license": "GPL-3.0-or-later", + "config": { + "forge": { + "make_targets": { + "win32": [ + "squirrel" + ], + "darwin": [ + "zip" + ], + "linux": [ + "deb", + "rpm", + "electron-forge-maker-appimage", + "zip" + ] + }, + "protocols": [ + { + "name": "freetube", + "role": "Viewer", + "schemes": [ + "freetube" + ] + } + ], + "electronPackagerConfig": { + "packageManager": "yarn", + "icon": "./src/icons/iconColor.icns" + }, + "electronWinstallerConfig": { + "name": "freetube", + "iconUrl": "https://raw.githubusercontent.com/FreeTubeApp/FreeTubeApp.github.io/master/images/iconColor.ico", + "setupIcon": "./src/icons/iconColor.ico" + }, + "electronInstallerDebian": { + "icon": "src/icons/iconColor.png" + }, + "repository": { + "type": "git", + "url": "https://github.com/FreeTubeApp/FreeTube" + } } }, "devDependencies": { diff --git a/src/index.html b/src/index.html index 6a2eacada..c23af68db 100644 --- a/src/index.html +++ b/src/index.html @@ -20,10 +20,21 @@
-
- Would you like to perform the function? -
Yes
-
No
+
+
+ Would you like to perform the function? +
Yes
+
No
+
+
+ + +
+
+ +   @@ -70,6 +81,7 @@
+ diff --git a/src/js/channels.js b/src/js/channels.js index 5d4012b8d..8970e4e82 100644 --- a/src/js/channels.js +++ b/src/js/channels.js @@ -62,7 +62,7 @@ function goToChannel(channelId) { maxResults: 50, order: 'date', }, function (data) { - const channelData = data.items[0]; + let grabDuration = getDuration(data.items); grabDuration.then((videoList) => { channelView.seen = true; @@ -72,8 +72,6 @@ function goToChannel(channelId) { videoList.items.forEach((video) => { displayVideo(video, 'channel'); }); - $('#main').html(rendered); - stopLoadingAnimation(); // Grab the channel's latest uploads. API forces a max of 50. youtubeAPI('search', { @@ -92,5 +90,7 @@ function goToChannel(channelId) { }); }); }); + }); }); -} \ No newline at end of file + }); +} diff --git a/src/js/history.js b/src/js/history.js index 806d53bfa..1df7585e9 100644 --- a/src/js/history.js +++ b/src/js/history.js @@ -1,53 +1,48 @@ /* - This file is part of FreeTube. - - FreeTube is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FreeTube is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FreeTube. If not, see . +This file is part of FreeTube. +FreeTube is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. +FreeTube is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with FreeTube. If not, see . */ /* - * File used for functions related to video history. - */ +* File used for functions related to video history. +*/ /** - * Add a video to the history database file - * - * @param {string} videoId - The video ID of the video to be saved. - * - * @return {Void} - */ -function addToHistory(videoId) { - const data = { - videoId: videoId, - timeWatched: new Date().getTime(), - }; - historyDb.insert(data, (err, newDoc) => {}); +* Add a video to the history database file +* +* @param {string} videoId - The video ID of the video to be saved. +* +* @return {Void} +*/ +function addToHistory(videoId){ + const data = { + videoId: videoId, + timeWatched: new Date().getTime(), + }; + historyDb.insert(data, (err, newDoc) => {}); } /** - * Remove a video from the history database file - * - * @param {string} videoId - The video ID of the video to be removed. - * - * @return {Void} - */ -function removeFromHistory(videoId) { - const data = { - videoId: videoId - }; - historyDb.remove(data, {}, (err, numRemoved) => {}); +* Remove a video from the history database file +* +* @param {string} videoId - The video ID of the video to be removed. +* +* @return {Void} +*/ +function removeFromHistory(videoId){ + const data = {videoId: videoId}; + historyDb.remove(data, {}, (err, numRemoved) => {}); } /** @@ -60,21 +55,22 @@ function showHistory(){ //startLoadingAnimation(); console.log('checking history'); - let videoList = ''; + let videoList = ''; - historyDb.find({}).sort({ - timeWatched: -1 - }).exec((err, docs) => { - if (docs.length > 49) { - // The YouTube API limits the search to 50 videos, so grab 50 most recent. - for (let i = 0; i < 49; i++) { - videoList = videoList + ',' + docs[i]['videoId']; - } - } else { - docs.forEach((video) => { - videoList = videoList + ',' + video['videoId']; - }); - } + historyDb.find({}).sort({ + timeWatched: -1 + }).exec((err, docs) => { + if(docs.length > 49){ + // The YouTube API limits the search to 50 videos, so grab 50 most recent. + for (let i = 0; i < 49; i++) { + videoList = videoList + ',' + docs[i]['videoId']; + } + } + else{ + docs.forEach((video) => { + videoList = videoList + ',' + video['videoId']; + }); + } youtubeAPI('videos', { part: 'snippet', @@ -91,4 +87,5 @@ function showHistory(){ }); }); }); -} \ No newline at end of file + }); +} diff --git a/src/js/models/commentThread.model.js b/src/js/models/commentThread.model.js index fef1105f9..436956b3d 100644 --- a/src/js/models/commentThread.model.js +++ b/src/js/models/commentThread.model.js @@ -17,19 +17,17 @@ -import { - comment -} from "./comment.model"; +import {comment} from "./comment.model"; /** * Entire Comment Threads for a Video */ export class commentThread { - videoId; - nextPageToken; - pageInfo = { - totalResults, - resultsPerPage + videoId: ?string; + nextPageToken: ?string; + pageInfo: { + totalResults: number, + resultsPerPage: number }; - items; -} \ No newline at end of file + items: comment[]; +} diff --git a/src/js/player.js b/src/js/player.js index 837b04331..f6dc35654 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -127,27 +127,25 @@ function playVideo(videoId) { if (typeof(info.player_response.captions.playerCaptionsTracklistRenderer.captionTracks) === 'object') { const videoSubtitles = info.player_response.captions.playerCaptionsTracklistRenderer.captionTracks; - if (subtitle.kind == 'asr') { - //subtitleUrl = subtitle.baseUrl; - return; - } + videoSubtitles.forEach((subtitle) => { + let subtitleUrl = 'https://www.youtube.com/api/timedtext?lang=' + subtitle.languageCode + '&fmt=vtt&name=&v=' + videoId; - videoHtml = videoHtml + ''; - }); - } + if (subtitle.kind == 'asr') { + //subtitleUrl = subtitle.baseUrl; + return; } - //videoHtml = videoHtml + ''; + videoHtml = videoHtml + ''; + }); } + } playerView.subtitleHtml = videoHtml; - } +} + const checkSubscription = isSubscribed(playerView.channelId); - checkSubscription.then((results) => { - const subscribeButton = document.getElementById('subscribeButton'); - checkSubscription.then((results) => { if (results === false) { if (subscribeButton != null) { @@ -181,10 +179,7 @@ function playVideo(videoId) { }); } - window.setTimeout(checkVideoUrls, 5000, video480p, video720p); - window.setTimeout(checkVideoUrls, 5000, playerView.video480p, playerView.video720p); - }); } @@ -225,6 +220,7 @@ function openMiniPlayer() { videoThumbnail: playerView.thumbnail, startTime: lastTime, }); + }); } /** @@ -340,4 +336,4 @@ function changeDurationBySeconds(seconds) { function changeDurationByPercentage(percentage) { const videoPlayer = $('.videoPlayer').get(0); videoPlayer.currentTime = videoPlayer.duration * percentage; -} \ No newline at end of file +} diff --git a/src/js/savedVideos.js b/src/js/savedVideos.js index 60fc29904..4a4fcef12 100644 --- a/src/js/savedVideos.js +++ b/src/js/savedVideos.js @@ -152,4 +152,5 @@ function showSavedVideos(){ }); }); }); -} \ No newline at end of file + }); +} diff --git a/src/js/settings.js b/src/js/settings.js index c4c74ce74..dbd64b56b 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -1,18 +1,15 @@ /* - This file is part of FreeTube. - - FreeTube is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FreeTube is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FreeTube. If not, see . +This file is part of FreeTube. +FreeTube is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. +FreeTube is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with FreeTube. If not, see . */ @@ -81,19 +78,17 @@ function checkDefaultSettings() { 'useTor': false }; - ft.log('Default Settings: ', settingDefaults); + console.log(settingDefaults); - for (let key in settingDefaults) { - settingsDb.find({ - _id: key - }, (err, docs) => { - if (jQuery.isEmptyObject(docs)) { - newSetting = { - _id: key, - value: settingDefaults[key] - }; + for (let key in settingDefaults){ + settingsDb.find({_id: key}, (err, docs) => { + if (jQuery.isEmptyObject(docs)) { + newSetting = { + _id: key, + value: settingDefaults[key] + }; - settingsDb.insert(newSetting); + settingsDb.insert(newSetting); if (key == 'theme'){ setTheme('light'); @@ -129,20 +124,25 @@ function checkDefaultSettings() { * @return {Void} */ function updateSettings() { - let themeSwitch = document.getElementById('themeSwitch').checked; - let torSwitch = document.getElementById('torSwitch').checked; - let key = document.getElementById('api-key').value; - let theme = 'light'; + let themeSwitch = document.getElementById('themeSwitch').checked; + let torSwitch = document.getElementById('torSwitch').checked; + let key = document.getElementById('api-key').value; + let theme = 'light'; - settingsView.apiKey = apiKeyBank[Math.floor(Math.random() * apiKeyBank.length)]; + if (apiKeyBank.indexOf(key) == -1 && key !== '') { + settingsView.apiKey = key; + } + else{ + settingsView.apiKey = apiKeyBank[Math.floor(Math.random() * apiKeyBank.length)]; + } - ft.log('(Is the theme switch checked) themeSwitch: ', themeSwitch); + console.log(themeSwitch); - if (themeSwitch === true) { - theme = 'dark'; - } + if (themeSwitch === true) { + theme = 'dark'; + } - ft.log('Theme: ', theme); + console.log(theme); // Update default theme settingsDb.update({ @@ -165,40 +165,14 @@ function updateSettings() { useTor = torSwitch; }); - if (key !== '') { - settingsDb.update({ - _id: 'theme' - }, { - value: theme - }, {}, function (err, numReplaced) { - ft.log('Error while updating theme: ', err); - ft.log('Number replaced: ', numReplaced); - }); - - // Update tor usage. - settingsDb.update({ - _id: 'useTor' - }, { - value: settingsView.apiKey - }, {}); - } - - if (key != '') { - settingsDb.update({ - _id: 'apiKey' - }, { - value: key - }, {}); - } else { - // To any third party devs that fork the project, please be ethical and change the API key. - settingsDb.update({ - _id: 'apiKey' - }, { - value: apiKey - }, {}); - } - - showToast('Settings have been saved.'); + // To any third party devs that fork the project, please be ethical and change the API key. + settingsDb.update({ + _id: 'apiKey' + }, { + value: settingsView.apiKey + }, {}); + + showToast('Settings have been saved.'); } /** @@ -209,13 +183,13 @@ function updateSettings() { * @return {Void} */ function toggleTheme(themeValue) { - if (themeValue.checked === true) { - setTheme('dark'); - currentTheme = 'dark'; - } else { - setTheme('light'); - currentTheme = 'light'; - } + if (themeValue.checked === true) { + setTheme('dark'); + currentTheme = 'dark'; + } else { + setTheme('light'); + currentTheme = 'light'; + } } /** @@ -226,86 +200,85 @@ function toggleTheme(themeValue) { * @return {Void} */ function setTheme(option) { - let cssFile; - const currentTheme = document.getElementsByTagName("link").item(1); + let cssFile; + const currentTheme = document.getElementsByTagName("link").item(1); - // Create a link element - const newTheme = document.createElement("link"); - newTheme.setAttribute("rel", "stylesheet"); - newTheme.setAttribute("type", "text/css"); + // Create a link element + const newTheme = document.createElement("link"); + newTheme.setAttribute("rel", "stylesheet"); + newTheme.setAttribute("type", "text/css"); - // Grab the css file to be used. - switch (option) { + // Grab the css file to be used. + switch (option) { case 'light': - cssFile = './style/lightTheme.css'; - document.getElementById('menuText').src = 'icons/textBlack.png'; - document.getElementById('menuIcon').src = 'icons/iconBlack.png'; - document.getElementById('menuButton').style.color = 'black'; - break; + cssFile = './style/lightTheme.css'; + document.getElementById('menuText').src = 'icons/textBlack.png'; + document.getElementById('menuIcon').src = 'icons/iconBlack.png'; + document.getElementById('menuButton').style.color = 'black'; + break; case 'dark': - cssFile = './style/darkTheme.css'; - document.getElementById('menuText').src = 'icons/textColor.png'; - document.getElementById('menuIcon').src = 'icons/iconColor.png'; - document.getElementById('menuButton').style.color = 'white'; - break; + cssFile = './style/darkTheme.css'; + document.getElementById('menuText').src = 'icons/textColor.png'; + document.getElementById('menuIcon').src = 'icons/iconColor.png'; + document.getElementById('menuButton').style.color = 'white'; + break; default: - // Default to the light theme - cssFile = './style/lightTheme.css'; - break; - } - newTheme.setAttribute("href", cssFile); + // Default to the light theme + cssFile = './style/lightTheme.css'; + break; + } + newTheme.setAttribute("href", cssFile); - // Replace the current theme with the new theme - document.getElementsByTagName("head").item(0).replaceChild(newTheme, currentTheme); + // Replace the current theme with the new theme + document.getElementsByTagName("head").item(0).replaceChild(newTheme, currentTheme); } /** - * Import Subscriptions from an OPML file. - * - * @param {string} subFile - The file location of the OPML file. - * - * @return {Void} - */ -function importOpmlSubs(json) { - if (!json[0]['folder'].includes('YouTube')) { - showToast('Invalid OPML File. Import is unsuccessful.'); - return; - } - - json.forEach((channel) => { - let channelId = channel['xmlurl'].replace('https://www.youtube.com/feeds/videos.xml?channel_id=', ''); - - addSubscription(channelId, false); - }); - window.setTimeout(displaySubs, 1000); - showToast('Subscriptions have been imported!'); +* Import Subscriptions from an OPML file. +* +* @param {string} subFile - The file location of the OPML file. +* +* @return {Void} +*/ +function importOpmlSubs(json){ + if(!json[0]['folder'].includes('YouTube')){ + showToast('Invalid OPML File. Import is unsuccessful.'); return; + } + + json.forEach((channel) => { + let channelId = channel['xmlurl'].replace('https://www.youtube.com/feeds/videos.xml?channel_id=', ''); + + addSubscription(channelId, false); + }); + window.setTimeout(displaySubs, 1000); + showToast('Subscriptions have been imported!'); + return; } /** - * Import a subscriptions file that the user provides. - * - * @return {Void} - */ -function importSubscriptions() { - const appDatabaseFile = localDataStorage + '/subscriptions.db'; +* Import a subscriptions file that the user provides. +* +* @return {Void} +*/ +function importSubscriptions(){ + const appDatabaseFile = localDataStorage + '/subscriptions.db'; - // Open user's file browser. Only show .db files. - dialog.showOpenDialog({ - properties: ['openFile'], - filters: [{ - name: 'Database File', - extensions: ['*'] - }, ] - }, function (fileLocation) { - if (typeof (fileLocation) === 'undefined') { - ft.log('Import Aborted'); - return; - } - ft.log('File Location: ', fileLocation); - let i = fileLocation[0].lastIndexOf('.'); - let fileType = (i < 0) ? '' : fileLocation[0].substr(i); - ft.log('File Type: ', fileType); + // Open user's file browser. Only show .db files. + dialog.showOpenDialog({ + properties: ['openFile'], + filters: [ + {name: 'Database File', extensions: ['*']}, + ] + }, function(fileLocation){ + if(typeof(fileLocation) === 'undefined'){ + console.log('Import Aborted'); + return; + } + console.log(fileLocation); + let i = fileLocation[0].lastIndexOf('.'); + let fileType = (i < 0) ? '' : fileLocation[0].substr(i); + console.log(fileType); fs.readFile(fileLocation[0], function(readErr, data){ if(readErr){ @@ -313,30 +286,31 @@ function importSubscriptions() { throw readErr; } - if (data.includes(" 0){ - console.log('Will not load subscriptions. Timer still on.'); - loadingView.seen = false; - return; - } - else{ - showToast('Refreshing Subscription List. Please wait...'); - checkSubscriptions = false; - } + function loadSubscriptions() { + if (checkSubscriptions === false && subscriptionView.videoList.length > 0){ + console.log('Will not load subscriptions. Timer still on.'); + loadingView.seen = false; + return; + } + else{ + showToast('Refreshing Subscription List. Please wait...'); + checkSubscriptions = false; + } - let videoList = []; + let videoList = []; - const subscriptions = returnSubscriptions(); + const subscriptions = returnSubscriptions(); - subscriptions.then((results) => { - let channelId = ''; - let videoList = []; + subscriptions.then((results) => { + let channelId = ''; + let videoList = []; - if (results.length > 0) { - let counter = 0; - - for (let i = 0; i < results.length; i++) { - channelId = results[i]['channelId']; + if (results.length > 0) { + let counter = 0; - youtubeAPI('search', { - part: 'snippet', - channelId: channelId, - type: 'video', - maxResults: 15, - order: 'date', - }, (data) => { + for (let i = 0; i < results.length; i++) { + channelId = results[i]['channelId']; - youtubeAPI('search', { - part: 'snippet', - channelId: channelId, - type: 'video', - maxResults: 15, - order: 'date', - }, (data) => { - console.log(data); - videoList = videoList.concat(data.items); - counter++; - progressView.progressWidth = (counter / results.length) * 100; - if (counter === results.length) { - videoList.sort((a, b) => { - const date1 = Date.parse(a.snippet.publishedAt); - const date2 = Date.parse(b.snippet.publishedAt); + youtubeAPI('search', { + part: 'snippet', + channelId: channelId, + type: 'video', + maxResults: 15, + order: 'date', + }, (data) => { + console.log(data); + videoList = videoList.concat(data.items); + counter++; + progressView.progressWidth = (counter / results.length) * 100; + if (counter === results.length) { + videoList.sort((a, b) => { + const date1 = Date.parse(a.snippet.publishedAt); + const date2 = Date.parse(b.snippet.publishedAt); - return date2.valueOf() - date1.valueOf(); - }); + return date2.valueOf() - date1.valueOf(); + }); - // The YouTube website limits the subscriptions to 100 before grabbing more so we only show 100 - // to keep the app running at a good speed. - if (videoList.length < 50) { - let grabDuration = getDuration(videoList.slice(0, 49)); + // The YouTube website limits the subscriptions to 100 before grabbing more so we only show 100 + // to keep the app running at a good speed. + if (videoList.length < 50) { + let grabDuration = getDuration(videoList.slice(0, 49)); - grabDuration.then((list) => { - subscriptionView.videoList = []; - list.items.forEach((video) => { - displayVideo(video, 'subscriptions'); - }); - loadingView.seen = false; - progressView.seen = false; - progressView.progressWidth = 0; - }); - } else { - console.log(videoList); - let finishedList = []; - let firstBatchDuration = getDuration(videoList.slice(0, 49)); + grabDuration.then((list) => { + subscriptionView.videoList = []; + list.items.forEach((video) => { + displayVideo(video, 'subscriptions'); + }); + loadingView.seen = false; + progressView.seen = false; + progressView.progressWidth = 0; + }); + } else { + console.log(videoList); + let finishedList = []; + let firstBatchDuration = getDuration(videoList.slice(0, 49)); - grabDuration.then((list) => { - list.items.forEach((video) => { - displayVideo(video); - }); - stopLoadingAnimation(); - }); - } else { + firstBatchDuration.then((list1) => { + finishedList = finishedList.concat(list1.items); + let secondBatchDuration = getDuration(videoList.slice(50, 99)); - secondBatchDuration.then((list2) => { - finishedList = finishedList.concat(list2.items); - console.log(finishedList); - subscriptionView.videoList = []; - finishedList.forEach((video) => { - displayVideo(video, 'subscriptions'); - }); - loadingView.seen = false; - progressView.seen = false; - progressView.progressWidth = 0; - subscriptionTimer = window.setTimeout(() => { - checkSubscriptions = true; - }, 60000); - }); - }); - } - } - } + secondBatchDuration.then((list2) => { + finishedList = finishedList.concat(list2.items); + console.log(finishedList); + subscriptionView.videoList = []; + finishedList.forEach((video) => { + displayVideo(video, 'subscriptions'); + }); + loadingView.seen = false; + progressView.seen = false; + progressView.progressWidth = 0; + subscriptionTimer = window.setTimeout(() => { + checkSubscriptions = true; + }, 60000); + }); + }); + } + } + } + ); + } - } else { - // User has no subscriptions. Display message. - loadingView.seen = false; - headerView.seen = false; - noSubscriptions.seen = true; - } - }); -} + } else { + // User has no subscriptions. Display message. + loadingView.seen = false; + headerView.seen = false; + noSubscriptions.seen = true; + } + }); + } /** * Get the list of subscriptions from the user's subscription database. @@ -281,4 +271,4 @@ function isSubscribed(channelId) { } }); }); -} \ No newline at end of file +} diff --git a/src/js/templates.js b/src/js/templates.js index 3ea33cc50..e0eba7eb9 100644 --- a/src/js/templates.js +++ b/src/js/templates.js @@ -180,6 +180,11 @@ let popularView = new Vue({ }, toggleSave: (videoId) => { addSavedVideo(videoId); + }, + copy: (site, videoId) => { + const url = 'https://' + site + '/watch?v=' + videoId; + clipboard.writeText(url); + showToast('URL has been copied to the clipboard'); } }, template: videoListTemplate diff --git a/src/js/videos.js b/src/js/videos.js index 028b62713..7f8c86648 100644 --- a/src/js/videos.js +++ b/src/js/videos.js @@ -220,7 +220,6 @@ function displayChannels(channels) { }, function (data) { ft.log('Channel Data: ', data); let items = data['items'].reverse(); - const videoListTemplate = require('./templates/channelList.html'); ft.log('Channel Items: ', items); @@ -240,6 +239,7 @@ function displayChannels(channels) { searchView.videoList = searchView.videoList.concat(channelData); }); + }); } function displayPlaylists(playlists) { @@ -343,6 +343,7 @@ function showVideoRecommendations(videoId) { playerView.recommendedVideoList = playerView.recommendedVideoList.concat(data); }); }); + }); } /** @@ -404,7 +405,7 @@ function parseSearchText(url = '') { * @return {string} - The formated string. Ex: 12:34:56 */ function parseVideoDuration(durationString) { - let match = durationString.match(/PT(\d+H)?(\d+M)?(\d+S)?/); + let match = durationString.match(/P.*T(\d+H)?(\d+M)?(\d+S)?/); let duration = ''; match = match.slice(1).map(function (x) { @@ -602,4 +603,4 @@ function checkVideoUrls(video480p, video720p) { } }); } -} \ No newline at end of file +}