Add Lock to profile switching and code cleanup

This commit is contained in:
PrestonN 2019-08-07 09:49:25 -04:00
parent eb10fee246
commit 456d1dfddc
32 changed files with 1471 additions and 1425 deletions

View File

@ -30,85 +30,86 @@
*/
function goToChannel(channelId) {
channelView.channelId = channelId;
channelView.channelSearchValue = '';
channelVideosView.page = 2;
channelView.channelId = channelId;
channelView.channelSearchValue = '';
channelVideosView.page = 2;
headerView.title = 'Latest Uploads';
hideViews();
loadingView.seen = true;
headerView.title = 'Latest Uploads';
hideViews();
loadingView.seen = true;
channelView.aboutTabSeen = false;
channelView.aboutTabSeen = false;
// Setting subButtonText here as Mustache templates are logic-less.
isSubscribed(channelId).then((subscribed) => {
channelView.subButtonText = (subscribed ? "UNSUBSCRIBE" : "SUBSCRIBE");
});
invidiousAPI('channels', channelId, {}, (data) => {
ft.log(data);
channelView.id = channelId;
channelView.name = data.author;
// Can't access url of undefined, check defined
data.authorBanners.length
? channelView.banner = data.authorBanners[0].url
: channelView.banner = undefined;
data.authorThumbnails.length >= 4
? channelView.icon = data.authorThumbnails[3].url
: channelView.icon = undefined
channelView.subCount = data.subCount.toLocaleString(); //toLocaleString adds commas as thousands separators
channelView.description = autolinker.link(data.description); //autolinker makes URLs clickable
channelVideosView.videoList = [];
channelView.featuredChannels = data.relatedChannels;
const views = [
aboutView,
headerView,
historyView,
popularView,
savedView,
searchView,
settingsView,
subscriptionView
]
if (seenAll(views, false)) {
channelVideosView.seen = true;
channelView.seen = true;
}
else {
return;
}
loadingView.seen = false;
data.latestVideos.forEach((video) => {
displayVideo(video, 'channel');
// Setting subButtonText here as Mustache templates are logic-less.
isSubscribed(channelId).then((subscribed) => {
channelView.subButtonText = (subscribed ? "UNSUBSCRIBE" : "SUBSCRIBE");
});
if (typeof(channelView.banner) === 'undefined') {
window.setTimeout(() => {$('.channelViewBanner').get(0).height = 200;}, 50);
}
}, (errorData) => {
showToast(errorData.responseJSON.error);
loadingView.seen = false;
});
invidiousAPI('channels', channelId, {}, (data) => {
ft.log(data);
invidiousAPI('channels/playlists', channelId, {}, (data) => {
ft.log(data);
channelView.id = channelId;
channelView.name = data.author;
channelPlaylistsView.videoList = [];
channelPlaylistsView.continuationString = data.continuation;
// Can't access url of undefined, check defined
data.authorBanners.length ?
channelView.banner = data.authorBanners[0].url :
channelView.banner = undefined;
data.playlists.forEach((playlist) => {
displayPlaylist(playlist, 'channelPlaylist');
data.authorThumbnails.length >= 4 ?
channelView.icon = data.authorThumbnails[3].url :
channelView.icon = undefined
channelView.subCount = data.subCount.toLocaleString(); //toLocaleString adds commas as thousands separators
channelView.description = autolinker.link(data.description); //autolinker makes URLs clickable
channelVideosView.videoList = [];
channelView.featuredChannels = data.relatedChannels;
const views = [
aboutView,
headerView,
historyView,
popularView,
savedView,
searchView,
settingsView,
subscriptionView
]
if (seenAll(views, false)) {
channelVideosView.seen = true;
channelView.seen = true;
} else {
return;
}
loadingView.seen = false;
data.latestVideos.forEach((video) => {
displayVideo(video, 'channel');
});
if (typeof (channelView.banner) === 'undefined') {
window.setTimeout(() => {
$('.channelViewBanner').get(0).height = 200;
}, 50);
}
}, (errorData) => {
showToast(errorData.responseJSON.error);
loadingView.seen = false;
});
invidiousAPI('channels/playlists', channelId, {}, (data) => {
ft.log(data);
channelPlaylistsView.videoList = [];
channelPlaylistsView.continuationString = data.continuation;
data.playlists.forEach((playlist) => {
displayPlaylist(playlist, 'channelPlaylist');
});
});
});
}
/**
@ -117,37 +118,43 @@ function goToChannel(channelId) {
* @return {Void}
*/
function channelNextPage() {
showToast('Fetching results, please wait…');
showToast('Fetching results, please wait…');
let sortValue = document.getElementById('channelVideosSortValue').value;
let sortValue = document.getElementById('channelVideosSortValue').value;
invidiousAPI('channels/videos', channelView.channelId, {'sort_by': sortValue, 'page': channelVideosView.page }, (data) => {
ft.log(data);
data.forEach((video) => {
displayVideo(video, 'channel');
invidiousAPI('channels/videos', channelView.channelId, {
'sort_by': sortValue,
'page': channelVideosView.page
}, (data) => {
ft.log(data);
data.forEach((video) => {
displayVideo(video, 'channel');
});
});
});
channelVideosView.page = channelVideosView.page + 1;
channelVideosView.page = channelVideosView.page + 1;
}
function channelPlaylistNextPage() {
if (channelPlaylistsView.continuationString === null) {
showToast('There are no more playlists for this channel.');
return;
}
if (channelPlaylistsView.continuationString === null) {
showToast('There are no more playlists for this channel.');
return;
}
showToast('Fetching results, please wait…');
showToast('Fetching results, please wait…');
let sortValue = document.getElementById('channelVideosSortValue').value;
let sortValue = document.getElementById('channelVideosSortValue').value;
invidiousAPI('channels/playlists', channelView.channelId, {'sort_by': sortValue, 'continuation': channelPlaylistsView.continuationString }, (data) => {
ft.log(data);
channelPlaylistsView.continuationString = data.continuation;
data.playlists.forEach((playlist) => {
displayPlaylist(playlist, 'channelPlaylist');
invidiousAPI('channels/playlists', channelView.channelId, {
'sort_by': sortValue,
'continuation': channelPlaylistsView.continuationString
}, (data) => {
ft.log(data);
channelPlaylistsView.continuationString = data.continuation;
data.playlists.forEach((playlist) => {
displayPlaylist(playlist, 'channelPlaylist');
});
});
});
}
function channelSearchKeypress(e) {
@ -157,34 +164,34 @@ function channelSearchKeypress(e) {
}
function searchChannel() {
if (channelView.channelSearchValue === '') {
return;
}
if (channelView.channelSearchValue === '') {
return;
}
showToast('Fetching results, please wait…');
showToast('Fetching results, please wait…');
invidiousAPI('channels/search', channelView.channelId, {
q: channelView.channelSearchValue,
page: channelSearchView.page,
}, function (data) {
ft.log(data);
invidiousAPI('channels/search', channelView.channelId, {
q: channelView.channelSearchValue,
page: channelSearchView.page,
}, function (data) {
ft.log(data);
data.forEach((video) => {
switch (video.type) {
case 'video':
displayVideo(video, 'channelSearch');
break;
case 'playlist':
if (video.videoCount > 0) {
displayPlaylist(video, 'channelSearch');
data.forEach((video) => {
switch (video.type) {
case 'video':
displayVideo(video, 'channelSearch');
break;
case 'playlist':
if (video.videoCount > 0) {
displayPlaylist(video, 'channelSearch');
}
break;
default:
}
break;
default:
}
});
});
channelSearchView.page = channelSearchView.page + 1;
});
channelSearchView.page = channelSearchView.page + 1;
});
}
/**
@ -197,5 +204,7 @@ function searchChannel() {
* @example seenAll{[view1, view2]} => bool
*/
function seenAll(views, expected = true) {
return views.every(({ seen }) => seen === expected)
return views.every(({
seen
}) => seen === expected)
}

View File

@ -27,8 +27,8 @@ let ft = {};
* @returns {Void}
*/
ft.log = function (...data) {
if (typeof(settingsView) !== 'undefined' && !settingsView.debugMode) {
return;
if (typeof (settingsView) !== 'undefined' && !settingsView.debugMode) {
return;
}
let currentTime = new Date();
let time = currentTime.getDate() + "/" +

View File

@ -15,140 +15,147 @@ along with FreeTube. If not, see <http://www.gnu.org/licenses/>.
/*
* 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(data){
historyDb.findOne({ videoId: data.videoId }, function (err, doc) {
if(doc === null) {
historyDb.insert(data, (err, newDoc) => {});
let videoIndex = subscriptionView.fullVideoList.findIndex((video) => {
return video.videoId == data.videoId;
});
* Add a video to the history database file
*
* @param {string} videoId - The video ID of the video to be saved.
*
* @return {Void}
*/
function addToHistory(data) {
historyDb.findOne({
videoId: data.videoId
}, function (err, doc) {
if (doc === null) {
historyDb.insert(data, (err, newDoc) => {});
let videoIndex = subscriptionView.fullVideoList.findIndex((video) => {
return video.videoId == data.videoId;
});
if (videoIndex >= 0) {
subscriptionView.fullVideoList[videoIndex].watched = true;
addSubsToView(subscriptionView.fullVideoList);
}
} else {
historyDb.update(
{ videoId: data.videoId },
{
videoId: data.videoId,
author: data.author,
authorId: data.authorId,
published: data.published,
publishedText: data.publishedText,
description: data.description,
viewCount: data.viewCount,
title: data.title,
lengthSeconds: data.lengthSeconds,
videoThumbnails: data.videoThumbnails,
liveNow: false,
paid: false,
type: 'video',
timeWatched: data.timeWatched,
watchProgress: data.watchProgress,
}, {}, (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, toast = true){
const data = {videoId: videoId};
historyDb.remove(data, {}, (err, numRemoved) => {
if (toast) {
if (!err) {
showToast('Video removed from history');
}
}
});
}
/**
* Update the watch progress video from the history database file
*
* @param {string} videoId - The video ID of the video to be removed.
*
* @param {double} lengthSeconds - The amount of time the video has been watched in seconds.
*
* @return {Void}
*/
function updateWatchProgress(videoId, lengthSeconds){
historyDb.findOne({ videoId: videoId }, function (err, doc) {
if(doc !== null) {
historyDb.update(
{ videoId: videoId },
{
$set: { watchProgress: lengthSeconds }
}, {}, (err, newDoc) => {});
}
});
}
/**
* Show the videos within the history database.
*
* @return {Void}
*/
function showHistory(){
ft.log('checking history');
historyView.videoList = [];
historyDb.find({}).sort({
timeWatched: -1
}).exec((err, docs) => {
docs.forEach((video, index) => {
if (video.authorId === undefined) {
// History data is from old version of FreeTube, update data for future calls.
invidiousAPI('videos', video.videoId, {}, (data) => {
let publishedText = new Date(data.published * 1000);
publishedText = dateFormat(publishedText, "mmm dS, yyyy");
let videoData = {
videoId: video.videoId,
if (videoIndex >= 0) {
subscriptionView.fullVideoList[videoIndex].watched = true;
addSubsToView(subscriptionView.fullVideoList);
}
} else {
historyDb.update({
videoId: data.videoId
}, {
videoId: data.videoId,
author: data.author,
authorId: data.authorId,
published: data.published,
publishedText: publishedText,
publishedText: data.publishedText,
description: data.description,
viewCount: data.viewCount,
title: data.title,
lengthSeconds: data.lengthSeconds,
videoThumbnails: data.videoThumbnails[4].url,
author: data.author,
authorId: data.authorId,
videoThumbnails: data.videoThumbnails,
liveNow: false,
paid: false,
type: 'video',
timeWatched: video.timeWatched,
watchProgress: 0,
};
addToHistory(videoData);
videoData.position = index;
displayVideo(videoData, 'history');
}, () => {
removeFromHistory(video.videoId, false);
});
}
else{
video.position = index;
displayVideo(video, 'history');
timeWatched: data.timeWatched,
watchProgress: data.watchProgress,
}, {}, (err, newDoc) => {});
}
});
loadingView.seen = false;
});
}
/**
* 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, toast = true) {
const data = {
videoId: videoId
};
historyDb.remove(data, {}, (err, numRemoved) => {
if (toast) {
if (!err) {
showToast('Video removed from history');
}
}
});
}
/**
* Update the watch progress video from the history database file
*
* @param {string} videoId - The video ID of the video to be removed.
*
* @param {double} lengthSeconds - The amount of time the video has been watched in seconds.
*
* @return {Void}
*/
function updateWatchProgress(videoId, lengthSeconds) {
historyDb.findOne({
videoId: videoId
}, function (err, doc) {
if (doc !== null) {
historyDb.update({
videoId: videoId
}, {
$set: {
watchProgress: lengthSeconds
}
}, {}, (err, newDoc) => {});
}
});
}
/**
* Show the videos within the history database.
*
* @return {Void}
*/
function showHistory() {
ft.log('checking history');
historyView.videoList = [];
historyDb.find({}).sort({
timeWatched: -1
}).exec((err, docs) => {
docs.forEach((video, index) => {
if (video.authorId === undefined) {
// History data is from old version of FreeTube, update data for future calls.
invidiousAPI('videos', video.videoId, {}, (data) => {
let publishedText = new Date(data.published * 1000);
publishedText = dateFormat(publishedText, "mmm dS, yyyy");
let videoData = {
videoId: video.videoId,
published: data.published,
publishedText: publishedText,
description: data.description,
viewCount: data.viewCount,
title: data.title,
lengthSeconds: data.lengthSeconds,
videoThumbnails: data.videoThumbnails[4].url,
author: data.author,
authorId: data.authorId,
liveNow: false,
paid: false,
type: 'video',
timeWatched: video.timeWatched,
watchProgress: 0,
};
addToHistory(videoData);
videoData.position = index;
displayVideo(videoData, 'history');
}, () => {
removeFromHistory(video.videoId, false);
});
} else {
video.position = index;
displayVideo(video, 'history');
}
});
loadingView.seen = false;
});
}

View File

@ -23,50 +23,50 @@ let mouseTimeout; // Timeout for hiding the mouse cursor on video playback
let checkedSettings = false;
let miniPlayerView = new Vue({
el: '#miniPlayer',
data: {
videoId: '',
videoUrl: '',
videoTitle: '',
video360p: '',
valid360p: true,
video720p: '',
valid720p: true,
videoAudio: '',
validAudio: true,
videoDash: '',
validDash: true,
videoLive: '',
validLive: false,
subtitleHtml: '',
videoThumbnail: '',
defaultPlaybackRate: '',
quality: '',
volume: '',
currentTime: '',
playerSeen: true,
legacySeen: false,
autoplay: true,
enableSubtitles: false,
thumbnailInterval: 5,
},
methods: {
legacyFormats: () => {
checkedSettings = false;
miniPlayerView.legacySeen = true;
miniPlayerView.playerSeen = false;
el: '#miniPlayer',
data: {
videoId: '',
videoUrl: '',
videoTitle: '',
video360p: '',
valid360p: true,
video720p: '',
valid720p: true,
videoAudio: '',
validAudio: true,
videoDash: '',
validDash: true,
videoLive: '',
validLive: false,
subtitleHtml: '',
videoThumbnail: '',
defaultPlaybackRate: '',
quality: '',
volume: '',
currentTime: '',
playerSeen: true,
legacySeen: false,
autoplay: true,
enableSubtitles: false,
thumbnailInterval: 5,
},
dashFormats: () => {
checkedSettings = false;
miniPlayerView.legacySeen = false;
miniPlayerView.playerSeen = true;
methods: {
legacyFormats: () => {
checkedSettings = false;
miniPlayerView.legacySeen = true;
miniPlayerView.playerSeen = false;
},
dashFormats: () => {
checkedSettings = false;
miniPlayerView.legacySeen = false;
miniPlayerView.playerSeen = true;
},
embedPlayer: () => {
checkedSettings = false;
miniPlayerView.legacySeen = false;
miniPlayerView.playerSeen = false;
}
},
embedPlayer: () => {
checkedSettings = false;
miniPlayerView.legacySeen = false;
miniPlayerView.playerSeen = false;
}
},
});
/**
@ -97,7 +97,7 @@ function checkDashSettings() {
// Mediaelement.js for some reason calls onLoadStart() multiple times
// This check is here to force checkVideoSettings to only run once.
if (checkedSettings) {
return;
return;
}
checkedSettings = true;
@ -108,173 +108,168 @@ function checkDashSettings() {
let parseDash = true;
let quality = 'Auto';
let declarePlayer = function() {
if (!checkedDash) {
return;
}
let declarePlayer = function () {
if (!checkedDash) {
return;
}
if (miniPlayerView.validLive) {
quality = 'Live';
}
if (miniPlayerView.validLive) {
quality = 'Live';
}
let player = new MediaElementPlayer('player', {
features: ['playpause', 'current', 'progress', 'duration', 'volume', 'stop', 'speed', 'quality', 'loop', 'tracks', 'fullscreen', 'timerailthumbnails', 'title'],
speeds: ['2', '1.75', '1.5', '1.25', '1', '0.75', '0.5', '0.25'],
renderers: ['native_dash', 'native_hls', 'html5'],
defaultSpeed: miniPlayerView.defaultPlaybackRate,
autoGenerate: true,
autoDash: true,
autoHLS: false,
title: miniPlayerView.videoTitle,
qualityText: 'Quality',
defaultQuality: 'Auto',
stretching: 'responsive',
startVolume: miniPlayerView.volume,
timeRailThumbnailsSeconds: miniPlayerView.thumbnailInterval,
features: ['playpause', 'current', 'progress', 'duration', 'volume', 'stop', 'speed', 'quality', 'loop', 'tracks', 'fullscreen', 'timerailthumbnails', 'title'],
speeds: ['2', '1.75', '1.5', '1.25', '1', '0.75', '0.5', '0.25'],
renderers: ['native_dash', 'native_hls', 'html5'],
defaultSpeed: miniPlayerView.defaultPlaybackRate,
autoGenerate: true,
autoDash: true,
autoHLS: false,
title: miniPlayerView.videoTitle,
qualityText: 'Quality',
defaultQuality: 'Auto',
stretching: 'responsive',
startVolume: miniPlayerView.volume,
timeRailThumbnailsSeconds: miniPlayerView.thumbnailInterval,
success: function(mediaElement, originalNode, instance) {
ft.log(mediaElement,originalNode,instance);
success: function (mediaElement, originalNode, instance) {
ft.log(mediaElement, originalNode, instance);
if (miniPlayerView.autoplay) {
instance.play();
};
if (miniPlayerView.autoplay) {
instance.play();
};
window.setTimeout(() => {
if (miniPlayerView.enableSubtitles && typeof($('.mejs__captions-button').get(0)) !== 'undefined') {
window.setTimeout(() => {
if (miniPlayerView.enableSubtitles && typeof ($('.mejs__captions-button').get(0)) !== 'undefined') {
let captionOptions = $('.mejs__captions-selector-input').get();
captionOptions[1].click();
};
}, 2000);
let initializeSettings = function() {
let qualityOptions = $('.mejs__qualities-selector-input').get();
let initializeSettings = function () {
let qualityOptions = $('.mejs__qualities-selector-input').get();
if (qualityOptions.length < 2) {
// Other plugin hasn't finished making the qualities. Let's try again in a moment.
if (qualityOptions.length < 2) {
// Other plugin hasn't finished making the qualities. Let's try again in a moment.
window.setTimeout(initializeSettings, 500);
return;
}
window.setTimeout(initializeSettings, 500);
return;
}
if (typeof(miniPlayerView.currentTime) !== 'undefined') {
instance.currentTime = miniPlayerView.currentTime;
miniPlayerView.currentTime = undefined;
}
if (typeof (miniPlayerView.currentTime) !== 'undefined') {
instance.currentTime = miniPlayerView.currentTime;
miniPlayerView.currentTime = undefined;
}
let selectedOption = false;
qualityOptions.reverse().forEach((option, index) => {
if (option.value === miniPlayerView.quality || option.value === miniPlayerView.quality + 'p') {
option.click();
selectedOption = true;
}
});
let selectedOption = false;
qualityOptions.reverse().forEach((option, index) => {
if (option.value === miniPlayerView.quality || option.value === miniPlayerView.quality + 'p') {
option.click();
selectedOption = true;
}
});
if (selectedOption === false) {
// Assume user selected a higher quality as their default. Select the highest option available.
ft.log('Quality not available.');
ft.log(qualityOptions.reverse()[0]);
if (selectedOption === false) {
// Assume user selected a higher quality as their default. Select the highest option available.
ft.log('Quality not available.');
ft.log(qualityOptions.reverse()[0]);
qualityOptions.reverse()[0].click();
}
};
qualityOptions.reverse()[0].click();
}
};
initializeSettings();
},
initializeSettings();
},
error: function(error, originalNode, instance) {
ft.log(error);
ft.log(originalNode);
ft.log(instance);
checkedSettings = false;
miniPlayerView.currentTime = instance.currentTime;
miniPlayerView.legacyFormats();
}
error: function (error, originalNode, instance) {
ft.log(error);
ft.log(originalNode);
ft.log(instance);
checkedSettings = false;
miniPlayerView.currentTime = instance.currentTime;
miniPlayerView.legacyFormats();
}
});
};
if (miniPlayerView.validDash !== false) {
validateUrl(miniPlayerView.videoDash, (valid) => {
miniPlayerView.validDash = valid;
validateUrl(miniPlayerView.videoDash, (valid) => {
miniPlayerView.validDash = valid;
checkedDash = true;
declarePlayer();
});
} else if (miniPlayerView.validLive !== false) {
checkedDash = true;
declarePlayer();
});
}
else if (miniPlayerView.validLive !== false) {
checkedDash = true;
declarePlayer();
}
else {
miniPlayerView.legacyFormats();
} else {
miniPlayerView.legacyFormats();
}
return;
}
function checkLegacySettings() {
let legacyPlayer = document.getElementById('legacyPlayer');
let legacyPlayer = document.getElementById('legacyPlayer');
let checked720p = false;
let checked360p = false;
let checkedAudio = false;
let checked720p = false;
let checked360p = false;
let checkedAudio = false;
let declarePlayer = function() {
if (!checked720p || !checked360p || !checkedAudio) {
return;
let declarePlayer = function () {
if (!checked720p || !checked360p || !checkedAudio) {
return;
}
if (typeof (miniPlayerView.currentTime) !== 'undefined') {
legacyPlayer.currentTime = miniPlayerView.currentTime;
miniPlayerView.currentTime = undefined;
}
if (miniPlayerView.autoplay) {
legacyPlayer.play();
}
if (miniPlayerView.enableSubtitles) {
legacyPlayer.textTracks[0].mode = 'showing';
}
changeVideoSpeed(miniPlayerView.defaultPlaybackRate);
};
if (miniPlayerView.valid360p !== false) {
validateUrl(miniPlayerView.video360p, (valid) => {
miniPlayerView.valid360p = valid;
checked360p = true;
declarePlayer();
});
} else {
checked360p = true;
declarePlayer();
}
if (typeof(miniPlayerView.currentTime) !== 'undefined') {
legacyPlayer.currentTime = miniPlayerView.currentTime;
miniPlayerView.currentTime = undefined;
if (miniPlayerView.valid720p !== false) {
validateUrl(miniPlayerView.video720p, (valid) => {
miniPlayerView.valid720p = valid;
checked720p = true;
declarePlayer();
});
} else {
checked720p = true;
declarePlayer();
}
if (miniPlayerView.autoplay) {
legacyPlayer.play();
if (miniPlayerView.validAudio !== false) {
validateUrl(miniPlayerView.videoAudio, (valid) => {
miniPlayerView.validAudio = valid;
checkedAudio = true;
declarePlayer();
});
} else {
checkedAudio = true;
declarePlayer();
}
if (miniPlayerView.enableSubtitles) {
legacyPlayer.textTracks[0].mode = 'showing';
}
changeVideoSpeed(miniPlayerView.defaultPlaybackRate);
};
if (miniPlayerView.valid360p !== false) {
validateUrl(miniPlayerView.video360p, (valid) => {
miniPlayerView.valid360p = valid;
checked360p = true;
declarePlayer();
});
}
else {
checked360p = true;
declarePlayer();
}
if (miniPlayerView.valid720p !== false) {
validateUrl(miniPlayerView.video720p, (valid) => {
miniPlayerView.valid720p = valid;
checked720p = true;
declarePlayer();
});
}
else {
checked720p = true;
declarePlayer();
}
if (miniPlayerView.validAudio !== false) {
validateUrl(miniPlayerView.videoAudio, (valid) => {
miniPlayerView.validAudio = valid;
checkedAudio = true;
declarePlayer();
});
}
else {
checkedAudio = true;
declarePlayer();
}
return;
return;
}
function validateUrl(videoUrl, callback) {
@ -312,141 +307,148 @@ function validateUrl(videoUrl, callback) {
* @return {Void}
*/
function changeVideoSpeed(speed) {
if (miniPlayerView.legacySeen) {
$('#currentSpeed').html(speed);
$('.videoPlayer').get(0).playbackRate = speed;
}
else {
let speedOptions = $('.mejs__speed-selector-input').get();
speedOptions.forEach((option, index) => {
if (option.value == speed) {
option.click();
player.playbackRate = speed;
}
});
}
if (miniPlayerView.legacySeen) {
$('#currentSpeed').html(speed);
$('.videoPlayer').get(0).playbackRate = speed;
} else {
let speedOptions = $('.mejs__speed-selector-input').get();
speedOptions.forEach((option, index) => {
if (option.value == speed) {
option.click();
player.playbackRate = speed;
}
});
}
}
function hideConfirmFunction() {
return;
return;
}
electron.ipcRenderer.on('ping', function(event, message) {
console.log(message);
electron.ipcRenderer.on('ping', function (event, message) {
console.log(message);
miniPlayerView.videoId = message.videoId;
miniPlayerView.videoUrl = message.videoUrl;
miniPlayerView.videoTitle = message.videoTitle;
miniPlayerView.video360p = message.video360p;
miniPlayerView.valid360p = message.valid360p;
miniPlayerView.video720p = message.video720p;
miniPlayerView.valid720p = message.valid720p;
miniPlayerView.videoAudio = message.videoAudio;
miniPlayerView.validAudio = message.validAudio;
miniPlayerView.videoDash = message.videoDash;
miniPlayerView.validDash = message.validDash;
miniPlayerView.videoLive = message.videoLive;
miniPlayerView.validLive = message.validLive;
miniPlayerView.subtitleHtml = message.subtitleHtml;
miniPlayerView.videoThumbnail = message.videoThumbnail;
miniPlayerView.defaultPlaybackRate = message.defaultPlaybackRate;
miniPlayerView.quality = message.quality;
miniPlayerView.volume = message.volume;
miniPlayerView.currentTime = message.currentTime;
miniPlayerView.playerSeen = message.playerSeen;
miniPlayerView.legacySeen = message.legacySeen;
miniPlayerView.autoplay = message.autoplay;
miniPlayerView.enableSubtitles = message.enableSubtitles;
miniPlayerView.thumbnailInterval = message.thumbnailInterval;
miniPlayerView.videoId = message.videoId;
miniPlayerView.videoUrl = message.videoUrl;
miniPlayerView.videoTitle = message.videoTitle;
miniPlayerView.video360p = message.video360p;
miniPlayerView.valid360p = message.valid360p;
miniPlayerView.video720p = message.video720p;
miniPlayerView.valid720p = message.valid720p;
miniPlayerView.videoAudio = message.videoAudio;
miniPlayerView.validAudio = message.validAudio;
miniPlayerView.videoDash = message.videoDash;
miniPlayerView.validDash = message.validDash;
miniPlayerView.videoLive = message.videoLive;
miniPlayerView.validLive = message.validLive;
miniPlayerView.subtitleHtml = message.subtitleHtml;
miniPlayerView.videoThumbnail = message.videoThumbnail;
miniPlayerView.defaultPlaybackRate = message.defaultPlaybackRate;
miniPlayerView.quality = message.quality;
miniPlayerView.volume = message.volume;
miniPlayerView.currentTime = message.currentTime;
miniPlayerView.playerSeen = message.playerSeen;
miniPlayerView.legacySeen = message.legacySeen;
miniPlayerView.autoplay = message.autoplay;
miniPlayerView.enableSubtitles = message.enableSubtitles;
miniPlayerView.thumbnailInterval = message.thumbnailInterval;
window.setTimeout(checkDashSettings, 100);
window.setTimeout(checkDashSettings, 100);
});
electron.ipcRenderer.on('play360p', function(event, message) {
if (miniPlayerView.valid360p === false || miniPlayerView.legacySeen === false) {
return;
}
electron.ipcRenderer.on('play360p', function (event, message) {
if (miniPlayerView.valid360p === false || miniPlayerView.legacySeen === false) {
return;
}
let videoPlayer = $('.videoPlayer').get(0);
let videoPlayer = $('.videoPlayer').get(0);
videoPlayer.pause();
videoPlayer.pause();
let time = videoPlayer.currentTime;
let time = videoPlayer.currentTime;
console.log(time);
console.log(time);
miniPlayerView.videoUrl = miniPlayerView.video360p;
miniPlayerView.videoUrl = miniPlayerView.video360p;
setTimeout(() => {videoPlayer.currentTime = time; videoPlayer.play();}, 100);
setTimeout(() => {
videoPlayer.currentTime = time;
videoPlayer.play();
}, 100);
});
electron.ipcRenderer.on('play720p', function(event, message) {
if (miniPlayerView.valid720p === false || miniPlayerView.legacySeen === false) {
return;
}
electron.ipcRenderer.on('play720p', function (event, message) {
if (miniPlayerView.valid720p === false || miniPlayerView.legacySeen === false) {
return;
}
let videoPlayer = $('.videoPlayer').get(0);
let videoPlayer = $('.videoPlayer').get(0);
videoPlayer.pause();
videoPlayer.pause();
let time = videoPlayer.currentTime;
let time = videoPlayer.currentTime;
console.log(time);
console.log(time);
miniPlayerView.videoUrl = miniPlayerView.video720p;
miniPlayerView.videoUrl = miniPlayerView.video720p;
setTimeout(() => {videoPlayer.currentTime = time; videoPlayer.play();}, 100);
setTimeout(() => {
videoPlayer.currentTime = time;
videoPlayer.play();
}, 100);
});
electron.ipcRenderer.on('playAudio', function(event, message) {
if (miniPlayerView.validAudio === false || miniPlayerView.legacySeen === false) {
return;
}
electron.ipcRenderer.on('playAudio', function (event, message) {
if (miniPlayerView.validAudio === false || miniPlayerView.legacySeen === false) {
return;
}
let videoPlayer = $('.videoPlayer').get(0);
let videoPlayer = $('.videoPlayer').get(0);
videoPlayer.pause();
videoPlayer.pause();
let time = videoPlayer.currentTime;
let time = videoPlayer.currentTime;
console.log(time);
console.log(time);
miniPlayerView.videoUrl = miniPlayerView.videoAudio;
miniPlayerView.videoUrl = miniPlayerView.videoAudio;
setTimeout(() => {videoPlayer.currentTime = time; videoPlayer.play();}, 100);
setTimeout(() => {
videoPlayer.currentTime = time;
videoPlayer.play();
}, 100);
});
electron.ipcRenderer.on('videoSpeed', function(event, message) {
changeVideoSpeed(message);
electron.ipcRenderer.on('videoSpeed', function (event, message) {
changeVideoSpeed(message);
});
electron.ipcRenderer.on('videoLoop', function(event, message) {
let videoPlayer = $('.videoPlayer').get(0);
electron.ipcRenderer.on('videoLoop', function (event, message) {
let videoPlayer = $('.videoPlayer').get(0);
videoPlayer.loop = !videoPlayer.loop;
videoPlayer.loop = !videoPlayer.loop;
});
electron.ipcRenderer.on('dashPlayer', function(event, message) {
miniPlayerView.dashFormats();
electron.ipcRenderer.on('dashPlayer', function (event, message) {
miniPlayerView.dashFormats();
});
electron.ipcRenderer.on('legacyPlayer', function(event, message) {
miniPlayerView.legacyFormats();
electron.ipcRenderer.on('legacyPlayer', function (event, message) {
miniPlayerView.legacyFormats();
});
electron.ipcRenderer.on('youtubePlayer', function(event, message) {
miniPlayerView.embedPlayer();
electron.ipcRenderer.on('youtubePlayer', function (event, message) {
miniPlayerView.embedPlayer();
});
window.onbeforeunload = (e) => {
let lengthSeconds = 0;
let lengthSeconds = 0;
if (miniPlayerView.legacySeen === false) {
lengthSeconds = player.currentTime;
}
else {
lengthSeconds = $('.videoPlayer').get(0).currentTime;
}
if (miniPlayerView.legacySeen === false) {
lengthSeconds = player.currentTime;
} else {
lengthSeconds = $('.videoPlayer').get(0).currentTime;
}
updateWatchProgress(miniPlayerView.videoId, lengthSeconds);
updateWatchProgress(miniPlayerView.videoId, lengthSeconds);
};

View File

@ -52,7 +52,7 @@ function playVideo(videoId, playlistId = '') {
playerView.videoDash = invidiousInstance + '/api/manifest/dash/' + videoId + '.mpd';
if (settingsView.proxyVideos) {
playerView.videoDash = playerView.videoDash + '?local=true';
playerView.videoDash = playerView.videoDash + '?local=true';
}
playerView.embededHtml = "<iframe width='560' height='315' src='https://www.youtube-nocookie.com/embed/" + videoId + "?rel=0' frameborder='0' allow='autoplay; encrypted-media' allowfullscreen></iframe>";
@ -61,19 +61,19 @@ function playVideo(videoId, playlistId = '') {
let player;
switch (defaultPlayer) {
case 'dash':
playerView.playerSeen = true;
playerView.legacySeen = false;
break;
case 'legacy':
playerView.playerSeen = false;
playerView.legacySeen = true;
break;
case 'embed':
playerView.playerSeen = false;
playerView.legacySeen = false;
break;
default:
case 'dash':
playerView.playerSeen = true;
playerView.legacySeen = false;
break;
case 'legacy':
playerView.playerSeen = false;
playerView.legacySeen = true;
break;
case 'embed':
playerView.playerSeen = false;
playerView.legacySeen = false;
break;
default:
}
@ -124,14 +124,14 @@ function playVideo(videoId, playlistId = '') {
// Search through the returned object to get the 360p and 720p video URLs (If available)
Object.keys(videoUrls).forEach((key) => {
switch (videoUrls[key]['itag']) {
case '18':
playerView.video360p = decodeURIComponent(videoUrls[key]['url']);
// ft.log(playerView.video360p);
break;
case '22':
playerView.video720p = decodeURIComponent(videoUrls[key]['url']);
// ft.log(playerView.video720p);
break;
case '18':
playerView.video360p = decodeURIComponent(videoUrls[key]['url']);
// ft.log(playerView.video360p);
break;
case '22':
playerView.video720p = decodeURIComponent(videoUrls[key]['url']);
// ft.log(playerView.video720p);
break;
}
});
@ -143,7 +143,7 @@ function playVideo(videoId, playlistId = '') {
playerView.legacySeen = true;
}
if (typeof(playerView.videoAudio) === 'undefined') {
if (typeof (playerView.videoAudio) === 'undefined') {
ft.log(playerView.videoAudio);
playerView.validAudio = false;
}
@ -151,7 +151,7 @@ function playVideo(videoId, playlistId = '') {
let useEmbedPlayer = false;
// Default to the embeded player if the URLs cannot be found.
if (typeof(playerView.video720p) === 'undefined' && typeof(playerView.video360p) === 'undefined') {
if (typeof (playerView.video720p) === 'undefined' && typeof (playerView.video360p) === 'undefined') {
//useEmbedPlayer = true;
playerView.currentQuality = 'EMBED';
playerView.playerSeen = false;
@ -160,7 +160,7 @@ function playVideo(videoId, playlistId = '') {
playerView.video720p = '';
//useEmbedPlayer = true;
showToast('Unable to get video file. Reverting to embeded player.');
} else if (typeof(playerView.video720p) === 'undefined' && typeof(playerView.video360p) !== 'undefined') {
} else if (typeof (playerView.video720p) === 'undefined' && typeof (playerView.video360p) !== 'undefined') {
// Default to the 360p video if the 720p URL cannot be found.
ft.log('Found');
playerView.videoUrl = playerView.video360p;
@ -269,7 +269,7 @@ function playVideo(videoId, playlistId = '') {
playerView.recommendedVideoList = playerView.recommendedVideoList.concat(data);
});
if (typeof(data.captions) !== 'undefined') {
if (typeof (data.captions) !== 'undefined') {
data.captions.forEach((caption) => {
let subtitleUrl = invidiousInstance + caption.url;
@ -286,23 +286,23 @@ function playVideo(videoId, playlistId = '') {
// Search through the returned object to get the 360p and 720p video URLs (If available)
Object.keys(videoUrls).forEach((key) => {
switch (videoUrls[key]['itag']) {
case '18':
playerView.video360p = decodeURIComponent(videoUrls[key]['url']);
// ft.log(playerView.video360p);
break;
case '22':
playerView.video720p = decodeURIComponent(videoUrls[key]['url']);
// ft.log(playerView.video720p);
break;
case '18':
playerView.video360p = decodeURIComponent(videoUrls[key]['url']);
// ft.log(playerView.video360p);
break;
case '22':
playerView.video720p = decodeURIComponent(videoUrls[key]['url']);
// ft.log(playerView.video720p);
break;
}
});
if (typeof(playerView.video360p) === 'undefined') {
if (typeof (playerView.video360p) === 'undefined') {
playerView.video360p = '';
playerView.valid360p = false;
}
if (typeof(playerView.video720p) === 'undefined') {
if (typeof (playerView.video720p) === 'undefined') {
playerView.video720p = '';
playerView.valid720p = false;
}
@ -323,7 +323,7 @@ function playVideo(videoId, playlistId = '') {
playerView.legacySeen = true;
}
if (typeof(playerView.videoAudio) === 'undefined') {
if (typeof (playerView.videoAudio) === 'undefined') {
ft.log(playerView.videoAudio);
playerView.videoAudio = '';
playerView.validAudio = false;
@ -395,7 +395,7 @@ function playVideo(videoId, playlistId = '') {
if (rememberHistory === true) {
historyDb.findOne({
videoId: playerView.videoId
}, function(err, doc) {
}, function (err, doc) {
let watchProgress = 0;
if (doc !== null) {
@ -440,7 +440,7 @@ function openMiniPlayer() {
let videoPlayer;
// Grabs whatever the HTML is for the current video player. Done this way to grab
// the HTML5 player (with varying qualities) as well as the YouTube embeded player.
if (typeof(player) !== 'undefined') {
if (typeof (player) !== 'undefined') {
videoPlayer = player;
} else {
videoPlayer = $('.videoPlayer').get(0);
@ -630,14 +630,14 @@ function openMiniPlayer() {
};
miniPlayer.webContents.send('ping', playerData);
let tmpSize = [0,0];
let tmpSize = [0, 0];
miniPlayer.on('resize', (e)=>{
var size = miniPlayer.getSize()
if( Math.abs(size[0]-tmpSize[0]) > 2 || Math.abs(size[1]-tmpSize[1]) > 2){
miniPlayer.setSize(size[0], parseInt(size[0] * 9 / 16))
}
tmpSize = size;
miniPlayer.on('resize', (e) => {
var size = miniPlayer.getSize()
if (Math.abs(size[0] - tmpSize[0]) > 2 || Math.abs(size[1] - tmpSize[1]) > 2) {
miniPlayer.setSize(size[0], parseInt(size[0] * 9 / 16))
}
tmpSize = size;
});
});
@ -655,7 +655,7 @@ function clickMiniPlayer(videoId) {
showToast("Opening in mini player, Please wait.");
let playVideo = function(videoData) {
let playVideo = function (videoData) {
if (videoData.checked720p === false || videoData.checked360p === false || videoData.checkedAudio === false || videoData.checkedDash === false || videoData.checkedLive === false) {
return;
}
@ -813,14 +813,14 @@ function clickMiniPlayer(videoId) {
miniPlayer.webContents.send('ping', videoData);
showToast('Video has been opened in a new window.');
let tmpSize = [0,0];
let tmpSize = [0, 0];
miniPlayer.on('resize', (e)=>{
var size = miniPlayer.getSize()
if( Math.abs(size[0]-tmpSize[0]) > 2 || Math.abs(size[1]-tmpSize[1]) > 2){
miniPlayer.setSize(size[0], parseInt(size[0] * 9 / 16))
}
tmpSize = size;
miniPlayer.on('resize', (e) => {
var size = miniPlayer.getSize()
if (Math.abs(size[0] - tmpSize[0]) > 2 || Math.abs(size[1] - tmpSize[1]) > 2) {
miniPlayer.setSize(size[0], parseInt(size[0] * 9 / 16))
}
tmpSize = size;
});
});
@ -847,7 +847,7 @@ function clickMiniPlayer(videoId) {
}
};
let validateData = function(data) {
let validateData = function (data) {
let newData = data;
newData.checked720p = false;
newData.checked360p = false;
@ -903,7 +903,7 @@ function clickMiniPlayer(videoId) {
videoData.videoDash = invidiousInstance + '/api/manifest/dash/' + videoId + '.mpd?unique_res=1';
if (settingsView.proxyVideos) {
videoData.videoDash = videoData.videoDash + '&local=true';
videoData.videoDash = videoData.videoDash + '&local=true';
}
videoData.autoplay = autoplay;
@ -914,7 +914,7 @@ function clickMiniPlayer(videoId) {
historyDb.findOne({
videoId: videoData.videoId
}, function(err, doc) {
}, function (err, doc) {
if (doc !== null) {
videoData.currentTime = doc.watchProgress;
} else {
@ -939,12 +939,12 @@ function clickMiniPlayer(videoId) {
Object.keys(videoUrls).forEach((key) => {
switch (videoUrls[key]['itag']) {
case '18':
videoData.video360p = videoUrls[key]['url'];
break;
case '22':
videoData.video720p = videoUrls[key]['url'];
break;
case '18':
videoData.video360p = videoUrls[key]['url'];
break;
case '22':
videoData.video720p = videoUrls[key]['url'];
break;
}
});
@ -967,12 +967,12 @@ function clickMiniPlayer(videoId) {
Object.keys(videoUrls).forEach((key) => {
switch (videoUrls[key]['itag']) {
case '18':
videoData.video360p = videoUrls[key]['url'];
break;
case '22':
videoData.video720p = videoUrls[key]['url'];
break;
case '18':
videoData.video360p = videoUrls[key]['url'];
break;
case '22':
videoData.video720p = videoUrls[key]['url'];
break;
}
});
@ -988,7 +988,7 @@ function clickMiniPlayer(videoId) {
let videoHtml = '';
if (typeof(data.captions) !== 'undefined') {
if (typeof (data.captions) !== 'undefined') {
data.captions.forEach((caption) => {
let subtitleUrl = invidiousInstance + caption.url;
@ -1043,7 +1043,7 @@ function checkDashSettings() {
let parseDash = true;
let quality = 'Auto';
let declarePlayer = function() {
let declarePlayer = function () {
if (!checkedDash) {
return;
}
@ -1067,7 +1067,7 @@ function checkDashSettings() {
startVolume: currentVolume,
timeRailThumbnailsSeconds: playerView.thumbnailInterval,
success: function(mediaElement, originalNode, instance) {
success: function (mediaElement, originalNode, instance) {
ft.log(mediaElement, originalNode, instance);
if (autoplay) {
@ -1076,7 +1076,7 @@ function checkDashSettings() {
};
window.setTimeout(() => {
if (enableSubtitles && typeof($('.mejs__captions-button').get(0)) !== 'undefined') {
if (enableSubtitles && typeof ($('.mejs__captions-button').get(0)) !== 'undefined') {
let captionOptions = $('.mejs__captions-selector-input').get();
if (captionOptions.length > 1) {
captionOptions[1].click();
@ -1088,7 +1088,7 @@ function checkDashSettings() {
};
}, 2000);
let initializeSettings = function() {
let initializeSettings = function () {
let qualityOptions = $('.mejs__qualities-selector-input').get();
if (qualityOptions.length < 2) {
@ -1116,26 +1116,26 @@ function checkDashSettings() {
}
window.setTimeout(() => {
historyDb.findOne({
videoId: playerView.videoId
}, function(err, doc) {
if (doc !== null) {
console.log('History');
if (typeof(playerView.currentTime) !== 'undefined') {
instance.currentTime = playerView.currentTime;
playerView.currentTime = undefined;
} else if (doc.watchProgress < instance.duration - 5 && playerView.validLive === false) {
instance.currentTime = doc.watchProgress;
}
}
});
historyDb.findOne({
videoId: playerView.videoId
}, function (err, doc) {
if (doc !== null) {
console.log('History');
if (typeof (playerView.currentTime) !== 'undefined') {
instance.currentTime = playerView.currentTime;
playerView.currentTime = undefined;
} else if (doc.watchProgress < instance.duration - 5 && playerView.validLive === false) {
instance.currentTime = doc.watchProgress;
}
}
});
}, 200);
};
initializeSettings();
},
error: function(error, originalNode, instance) {
error: function (error, originalNode, instance) {
ft.log(error);
ft.log(originalNode);
ft.log(instance);
@ -1170,12 +1170,12 @@ function checkLegacySettings() {
let checked360p = false;
let checkedAudio = false;
let declarePlayer = function() {
let declarePlayer = function () {
if (!checked720p || !checked360p || !checkedAudio) {
return;
}
if (typeof(playerView.currentTime) !== 'undefined') {
if (typeof (playerView.currentTime) !== 'undefined') {
player.currentTime = playerView.currentTime;
}
@ -1188,9 +1188,9 @@ function checkLegacySettings() {
window.setTimeout(() => {
historyDb.findOne({
videoId: playerView.videoId
}, function(err, doc) {
}, function (err, doc) {
if (doc !== null) {
if (doc.watchProgress < player.duration - 5 && typeof(playerView.currentTime) === 'undefined') {
if (doc.watchProgress < player.duration - 5 && typeof (playerView.currentTime) === 'undefined') {
player.currentTime = doc.watchProgress;
}
@ -1244,10 +1244,10 @@ function checkLegacySettings() {
function playNext(timeLeft) {
if (playerView.playlistSeen && !settingsView.autoplayPlaylists) {
return;
return;
};
if (!playerView.playlistSeen && !settingsView.playNextVideo) {
return;
return;
}
const clearHtml = "<span class='link' onclick='stopPlayNext()'>Cancel</span>";
@ -1310,8 +1310,8 @@ function playNextVideo() {
return;
}
} else {
loadingView.seen = true;
playVideo(playerView.recommendedVideoList[0].id);
loadingView.seen = true;
playVideo(playerView.recommendedVideoList[0].id);
}
}

View File

@ -16,87 +16,88 @@
*/
function showPlaylist(playlistId) {
hideViews();
loadingView.seen = true;
hideViews();
loadingView.seen = true;
playlistView.videoList = [];
playlistView.videoList = [];
invidiousAPI('playlists', playlistId, {}, (data) => {
ft.log(data);
playlistView.playlistId = playlistId;
playlistView.channelName = data.author;
playlistView.channelId = data.authorId;
playlistView.channelThumbnail = data.authorThumbnails[3].url;
playlistView.title = data.title;
playlistView.videoCount = data.videoCount;
playlistView.viewCount = data.viewCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
playlistView.thumbnail = data.videos[Math.floor((Math.random() * data.videos.length) + 1)].videoThumbnails[0].url;
playlistView.description = data.descriptionHtml;
let dateString = new Date(data.updated * 1000);
dateString.setDate(dateString.getDate() + 1);
playlistView.lastUpdated = dateFormat(dateString, "mmm dS, yyyy");
let amountOfPages = Math.ceil(data.videoCount / 100);
ft.log(amountOfPages);
for (let i = 1; i <= amountOfPages; i++) {
invidiousAPI('playlists', playlistId, {page: i}, (data) => {
invidiousAPI('playlists', playlistId, {}, (data) => {
ft.log(data);
data.videos.forEach((video) => {
let videoData = {};
let time = video.lengthSeconds;
let hours = 0;
playlistView.playlistId = playlistId;
playlistView.channelName = data.author;
playlistView.channelId = data.authorId;
playlistView.channelThumbnail = data.authorThumbnails[3].url;
playlistView.title = data.title;
playlistView.videoCount = data.videoCount;
playlistView.viewCount = data.viewCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
playlistView.thumbnail = data.videos[Math.floor((Math.random() * data.videos.length) + 1)].videoThumbnails[0].url;
playlistView.description = data.descriptionHtml;
let dateString = new Date(data.updated * 1000);
dateString.setDate(dateString.getDate() + 1);
playlistView.lastUpdated = dateFormat(dateString, "mmm dS, yyyy");
if (time >= 3600) {
hours = Math.floor(time / 3600);
time = time - hours * 3600;
}
let amountOfPages = Math.ceil(data.videoCount / 100);
let minutes = Math.floor(time / 60);
let seconds = time - minutes * 60;
ft.log(amountOfPages);
if (seconds < 10) {
seconds = '0' + seconds;
}
for (let i = 1; i <= amountOfPages; i++) {
invidiousAPI('playlists', playlistId, {
page: i
}, (data) => {
ft.log(data);
data.videos.forEach((video) => {
let videoData = {};
if (minutes < 10 && hours > 0) {
minutes = '0' + minutes;
}
let time = video.lengthSeconds;
let hours = 0;
if (hours > 0) {
videoData.duration = hours + ":" + minutes + ":" + seconds;
} else {
videoData.duration = minutes + ":" + seconds;
}
if (time >= 3600) {
hours = Math.floor(time / 3600);
time = time - hours * 3600;
}
videoData.id = video.videoId;
videoData.title = video.title;
videoData.channelName = video.author;
videoData.channelId = video.authorId;
videoData.thumbnail = video.videoThumbnails[4].url;
let minutes = Math.floor(time / 60);
let seconds = time - minutes * 60;
playlistView.videoList[video.index] = videoData;
});
if (playlistView.seen !== false) {
playlistView.seen = false;
playlistView.seen = true;
if (seconds < 10) {
seconds = '0' + seconds;
}
if (minutes < 10 && hours > 0) {
minutes = '0' + minutes;
}
if (hours > 0) {
videoData.duration = hours + ":" + minutes + ":" + seconds;
} else {
videoData.duration = minutes + ":" + seconds;
}
videoData.id = video.videoId;
videoData.title = video.title;
videoData.channelName = video.author;
videoData.channelId = video.authorId;
videoData.thumbnail = video.videoThumbnails[4].url;
playlistView.videoList[video.index] = videoData;
});
if (playlistView.seen !== false) {
playlistView.seen = false;
playlistView.seen = true;
}
});
loadingView.seen = false;
playlistView.seen = true;
}
});
loadingView.seen = false;
playlistView.seen = true;
}
});
});
}
function togglePlaylist() {
if (playerView.playlistShowList !== false) {
playerView.playlistShowList = false;
}
else{
playerView.playlistShowList = true;
}
if (playerView.playlistShowList !== false) {
playerView.playlistShowList = false;
} else {
playerView.playlistShowList = true;
}
}

View File

@ -33,30 +33,30 @@ function addSavedVideo(videoId) {
checkIfSaved.then((saved) => {
if (saved === false) {
invidiousAPI('videos', videoId, {}, (data) => {
let publishedText = new Date(data.published * 1000);
publishedText = dateFormat(publishedText, "mmm dS, yyyy");
let videoData = {
videoId: videoId,
published: data.published,
publishedText: publishedText,
description: data.description,
viewCount: data.viewCount,
title: data.title,
lengthSeconds: data.lengthSeconds,
videoThumbnails: data.videoThumbnails[4].url,
author: data.author,
authorId: data.authorId,
liveNow: false,
paid: false,
type: 'video',
timeSaved: new Date().getTime(),
};
invidiousAPI('videos', videoId, {}, (data) => {
let publishedText = new Date(data.published * 1000);
publishedText = dateFormat(publishedText, "mmm dS, yyyy");
let videoData = {
videoId: videoId,
published: data.published,
publishedText: publishedText,
description: data.description,
viewCount: data.viewCount,
title: data.title,
lengthSeconds: data.lengthSeconds,
videoThumbnails: data.videoThumbnails[4].url,
author: data.author,
authorId: data.authorId,
liveNow: false,
paid: false,
type: 'video',
timeSaved: new Date().getTime(),
};
savedVidsDb.insert(videoData, (err, newDoc) => {
showToast('The video has been favorited!');
});
});
savedVidsDb.insert(videoData, (err, newDoc) => {
showToast('The video has been favorited!');
});
});
} else {
showToast('The video has already been favorited!')
}
@ -75,10 +75,10 @@ function removeSavedVideo(videoId, toast = true) {
videoId: videoId
}, {}, (err, numRemoved) => {
if (toast) {
showToast('Video has been removed from the favorites list.');
showToast('Video has been removed from the favorites list.');
}
if (savedView.seen === true) {
showSavedVideos();
showSavedVideos();
}
});
}
@ -144,40 +144,40 @@ function showSavedVideos() {
timeSaved: -1
}).exec((err, docs) => {
docs.forEach((video, index) => {
if (typeof(video.author) === 'undefined'){
invidiousAPI('videos', video.videoId, {}, (data) => {
let publishedText = new Date(data.published * 1000);
publishedText = dateFormat(publishedText, "mmm dS, yyyy");
let videoData = {
videoId: video.videoId,
published: data.published,
publishedText: publishedText,
description: data.description,
viewCount: data.viewCount,
title: data.title,
lengthSeconds: data.lengthSeconds,
videoThumbnails: data.videoThumbnails[4].url,
author: data.author,
authorId: data.authorId,
liveNow: false,
paid: false,
type: 'video',
};
if (typeof (video.author) === 'undefined') {
invidiousAPI('videos', video.videoId, {}, (data) => {
let publishedText = new Date(data.published * 1000);
publishedText = dateFormat(publishedText, "mmm dS, yyyy");
let videoData = {
videoId: video.videoId,
published: data.published,
publishedText: publishedText,
description: data.description,
viewCount: data.viewCount,
title: data.title,
lengthSeconds: data.lengthSeconds,
videoThumbnails: data.videoThumbnails[4].url,
author: data.author,
authorId: data.authorId,
liveNow: false,
paid: false,
type: 'video',
};
savedVidsDb.update(
{ videoId: data.videoId },
videoData, {}, (err, newDoc) => {});
savedVidsDb.update({
videoId: data.videoId
},
videoData, {}, (err, newDoc) => {});
videoData.position = index;
displayVideo(videoData, 'saved');
}, () => {
removeSavedVideo(video.videoId, false);
});
}
else {
video.position = index;
displayVideo(video, 'saved');
}
videoData.position = index;
displayVideo(videoData, 'saved');
}, () => {
removeSavedVideo(video.videoId, false);
});
} else {
video.position = index;
displayVideo(video, 'saved');
}
});
loadingView.seen = false;

View File

@ -181,12 +181,10 @@ function checkDefaultSettings() {
'distractionFreeMode': false,
'hideWatchedSubs': false,
'videoView': 'grid',
'profileList': [
{
'profileList': [{
name: 'All Channels',
color: randomColor
},
],
}, ],
'defaultProfile': 'All Channels',
};

View File

@ -97,11 +97,13 @@ function removeSubscription(channelId, profile = profileSelectView.activeProfile
value: profile
}
}
}, { multi: true },(err, numRemoved) => {
}, {
multi: true
}, (err, numRemoved) => {
// Refresh the list of subscriptions on the side navigation bar.
displaySubs();
if (displayToast) {
showToast('Removed channel from subscriptions.');
showToast('Removed channel from subscriptions.');
}
});
} else {
@ -111,7 +113,7 @@ function removeSubscription(channelId, profile = profileSelectView.activeProfile
// Refresh the list of subscriptions on the side navigation bar.
displaySubs();
if (displayToast) {
showToast('Removed channel from subscriptions.');
showToast('Removed channel from subscriptions.');
}
});
}
@ -203,9 +205,9 @@ function addSubsToView(videoList) {
}
if (profileSelectView.activeProfile.name !== 'All Channels') {
videoList = videoList.filter(a => {
return a.profile.map(x => x.value).indexOf(profileSelectView.activeProfile.name) !== -1
});
videoList = videoList.filter(a => {
return a.profile.map(x => x.value).indexOf(profileSelectView.activeProfile.name) !== -1
});
}
videoList.sort((a, b) => {
@ -233,6 +235,13 @@ function addSubsToView(videoList) {
checkSubscriptions = true;
}, 7200000);
let profileLockTimer = window.setInterval(() => {
if (videoList.length === subscriptionView.videoList.length || subscriptionView.videoList.length === 100) {
profileSelectView.profileLock = false;
clearInterval(profileLockTimer);
}
}, 500);
ft.log('Done');
}
@ -288,13 +297,14 @@ function displaySubs() {
channelName: 1
}).exec((err, subs) => {
let subFilter;
if (profileSelectView.activeProfile.name === 'All Channels' || typeof(profileSelectView.activeProfile.name) === 'undefined') {
subFilter = subs;
}
else {
subFilter = subs.filter(a => {
return a.profile.find((name) => {return name.value === profileSelectView.activeProfile.name });
});
if (profileSelectView.activeProfile.name === 'All Channels' || typeof (profileSelectView.activeProfile.name) === 'undefined') {
subFilter = subs;
} else {
subFilter = subs.filter(a => {
return a.profile.find((name) => {
return name.value === profileSelectView.activeProfile.name
});
});
}
subFilter.forEach((channel) => {

View File

@ -167,11 +167,11 @@ let searchSuggestionsView = new Vue({
suggestionList: [],
},
methods: {
newSearchTerm: (text) => {
document.getElementById('search').value = text;
getSearchSuggestion();
searchSuggestionsView.seen = false;
},
newSearchTerm: (text) => {
document.getElementById('search').value = text;
getSearchSuggestion();
searchSuggestionsView.seen = false;
},
},
template: searchSuggestionsViewTemplate
});
@ -573,22 +573,22 @@ let channelView = new Vue({
},
methods: {
videoTab: () => {
channelVideosView.seen = true;
channelView.aboutTabSeen = false;
channelPlaylistsView.seen = false;
channelSearchView.seen = false;
channelVideosView.seen = true;
channelView.aboutTabSeen = false;
channelPlaylistsView.seen = false;
channelSearchView.seen = false;
},
playlistTab: () => {
channelPlaylistsView.seen = true;
channelVideosView.seen = false;
channelView.aboutTabSeen = false;
channelSearchView.seen = false;
channelPlaylistsView.seen = true;
channelVideosView.seen = false;
channelView.aboutTabSeen = false;
channelSearchView.seen = false;
},
aboutTab: () => {
channelView.aboutTabSeen = true;
channelVideosView.seen = false;
channelPlaylistsView.seen = false;
channelSearchView.seen = false;
channelView.aboutTabSeen = true;
channelVideosView.seen = false;
channelPlaylistsView.seen = false;
channelSearchView.seen = false;
},
subscription: (channelId) => {
let channelData = {
@ -599,48 +599,62 @@ let channelView = new Vue({
toggleSubscription(channelData);
},
sort: () => {
if (channelVideosView.seen) {
channelVideosView.page = 1;
channelVideosView.videoList = [];
channelNextPage();
}
else {
// Playlist View is active
channelPlaylistsView.continuationString = '';
channelPlaylistsView.videoList = [];
channelPlaylistNextPage();
}
if (channelVideosView.seen) {
channelVideosView.page = 1;
channelVideosView.videoList = [];
channelNextPage();
} else {
// Playlist View is active
channelPlaylistsView.continuationString = '';
channelPlaylistsView.videoList = [];
channelPlaylistNextPage();
}
},
search: () => {
channelSearchView.page = 1;
channelSearchView.videoList = [];
channelView.aboutTabSeen = false;
channelVideosView.seen = false;
channelPlaylistsView.seen = false;
channelSearchView.seen = true;
searchChannel();
channelSearchView.page = 1;
channelSearchView.videoList = [];
channelView.aboutTabSeen = false;
channelVideosView.seen = false;
channelPlaylistsView.seen = false;
channelSearchView.seen = true;
searchChannel();
},
goToChannel: (channelId) => {
goToChannel(channelId);
goToChannel(channelId);
},
},
computed: {
sortOptions: () => {
if (channelVideosView.seen) {
return [
{value: 'newest', label: 'Newest'},
{value: 'oldest', label: 'Oldest'},
{value: 'popular', label: 'Most Popular'},
];
}
else {
return [
{value: 'newest', label: 'Newest'},
{value: 'oldest', label: 'Oldest'},
{value: 'last', label: 'Last Video Added'},
];
}
},
sortOptions: () => {
if (channelVideosView.seen) {
return [{
value: 'newest',
label: 'Newest'
},
{
value: 'oldest',
label: 'Oldest'
},
{
value: 'popular',
label: 'Most Popular'
},
];
} else {
return [{
value: 'newest',
label: 'Newest'
},
{
value: 'oldest',
label: 'Oldest'
},
{
value: 'last',
label: 'Last Video Added'
},
];
}
},
},
template: channelTemplate
});
@ -962,12 +976,10 @@ let backButtonView = new Vue({
// reset this.lastView
this.lastView = false;
}
else if (isSubManager) {
subscriptionManagerView.seen = true;
this.lastView = false;
}
else {
} else if (isSubManager) {
subscriptionManagerView.seen = true;
this.lastView = false;
} else {
// if not search then this.lastView has to be playlistView
// Change back to playlistView
@ -994,6 +1006,7 @@ let profileSelectView = new Vue({
activeProfileInitial: '',
activeProfileInitialColor: '#000000',
profileList: [],
profileLock: false,
},
methods: {
showSubscriptionManager: function () {
@ -1001,6 +1014,17 @@ let profileSelectView = new Vue({
subscriptionManagerView.seen = true;
},
setActiveProfile: function (index) {
if (profileSelectView.profileLock !== false) {
console.log('Lock is active');
window.setTimeout(() => {
profileSelectView.setActiveProfile(index);
}, 1000);
return;
}
profileSelectView.profileLock = true;
console.log('Set to true');
this.activeProfile = this.profileList[index];
this.activeProfileInitial = this.profileInitials[index];
this.activeProfileInitialColor = this.profileTextColor[index];
@ -1102,37 +1126,35 @@ let subscriptionManagerView = new Vue({
editProfileView.newProfileName = this.profileList[index].name;
editProfileView.newProfileColorText = this.profileList[index].color;
if (this.profileList[index].name === 'All Channels') {
// Sort alphabetically
subDb.find({
}).sort({
channelName: 1
}).exec((err, subs) => {
let list = [];
subs.forEach((sub) => {
sub.checked = false;
list.push(sub);
// Sort alphabetically
subDb.find({}).sort({
channelName: 1
}).exec((err, subs) => {
let list = [];
subs.forEach((sub) => {
sub.checked = false;
list.push(sub);
});
editProfileView.subscriptionList = list;
});
editProfileView.subscriptionList = list;
});
}
else {
// Sort alphabetically
subDb.find({
profile: {
$elemMatch: {
value: this.profileList[index].name
} else {
// Sort alphabetically
subDb.find({
profile: {
$elemMatch: {
value: this.profileList[index].name
}
}
}
}).sort({
channelName: 1
}).exec((err, subs) => {
let list = [];
subs.forEach((sub) => {
sub.checked = false;
list.push(sub);
}).sort({
channelName: 1
}).exec((err, subs) => {
let list = [];
subs.forEach((sub) => {
sub.checked = false;
list.push(sub);
});
editProfileView.subscriptionList = list;
});
editProfileView.subscriptionList = list;
});
}
}
editProfileView.seen = true;
@ -1200,8 +1222,8 @@ let editProfileView = new Vue({
},
defaultProfile: function () {
if (editProfileView.profileName === settingsView.defaultProfile) {
showToast('This profile is already set as your default.');
return;
showToast('This profile is already set as your default.');
return;
}
settingsDb.update({
@ -1280,8 +1302,8 @@ let editProfileView = new Vue({
},
updateProfile: function (updateView = true) {
if (this.newProfileName === '') {
showToast('Profile name cannot be blank.');
return;
showToast('Profile name cannot be blank.');
return;
}
let patt = new RegExp("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
@ -1578,8 +1600,8 @@ let editProfileView = new Vue({
let amountDeleted = 0;
if (this.amountSelected === 0) {
showToast('A channel must be selected before it can be deleted.');
return;
showToast('A channel must be selected before it can be deleted.');
return;
}
confirmFunction(confirmString, () => {
@ -1589,16 +1611,16 @@ let editProfileView = new Vue({
removeSubscription(channel.channelId, editProfileView.profileName, false);
let subViewListMap = subscriptionView.fullVideoList.map(x => x.author === channel.channelName);
let subViewListMap = subscriptionView.fullVideoList.map(x => x.author === channel.channelName);
for (let i = 0; i < subViewListMap.length; i++) {
if (subViewListMap[i]) {
let subProfileIndex = subscriptionView.fullVideoList[i].profile.findIndex(x => x.value === editProfileView.profileName);
subscriptionView.fullVideoList[i].profile.splice(subProfileIndex, 1);
}
for (let i = 0; i < subViewListMap.length; i++) {
if (subViewListMap[i]) {
let subProfileIndex = subscriptionView.fullVideoList[i].profile.findIndex(x => x.value === editProfileView.profileName);
subscriptionView.fullVideoList[i].profile.splice(subProfileIndex, 1);
}
}
amountDeleted++;
amountDeleted++;
}
});
@ -1608,7 +1630,7 @@ let editProfileView = new Vue({
addSubsToView(subscriptionView.fullVideoList);
showToast(amountDeleted + ' channel(s) have been deleted from this profile.');
this.subscriptionList = this.subscriptionList.filter(a => {
return !a.checked;
return !a.checked;
});
}, 500);
});
@ -1616,12 +1638,11 @@ let editProfileView = new Vue({
},
computed: {
newProfileColor: function () {
if (this.newProfileColorText[0] === '#') {
return this.newProfileColorText;
}
else {
return '#' + this.newProfileColorText;
}
if (this.newProfileColorText[0] === '#') {
return this.newProfileColorText;
} else {
return '#' + this.newProfileColorText;
}
},
isDefaultProfile: function () {
return settingsView.defaultProfile === this.profileName;

View File

@ -22,47 +22,47 @@
*/
function checkForNewUpdate() {
const requestUrl = 'https://api.github.com/repos/freetubeapp/freetube/releases';
const requestUrl = 'https://api.github.com/repos/freetubeapp/freetube/releases';
let success = function(data) {
let currentVersion = require('electron').remote.app.getVersion();
let versionNumber = data[0].tag_name.replace('v', '');
versionNumber = versionNumber.replace('-beta', '');
let success = function (data) {
let currentVersion = require('electron').remote.app.getVersion();
let versionNumber = data[0].tag_name.replace('v', '');
versionNumber = versionNumber.replace('-beta', '');
let blogRegexPattern = /\(.*\)/;
let blogRegexPattern = /\(.*\)/;
let blogUrl = blogRegexPattern.exec(data[0].body);
blogUrl = blogUrl[0].replace(/\(|\)/g, '');
let blogUrl = blogRegexPattern.exec(data[0].body);
blogUrl = blogUrl[0].replace(/\(|\)/g, '');
if (versionNumber > currentVersion) {
confirmFunction(data[0].name + ` is now available! Would you like to download the update? <a href="${blogUrl}">Changelog</a>`, openReleasePage);
if (versionNumber > currentVersion) {
confirmFunction(data[0].name + ` is now available! Would you like to download the update? <a href="${blogUrl}">Changelog</a>`, openReleasePage);
}
};
if (useTor) {
proxyRequest(() => {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
ft.log(xhr);
ft.log(textStatus);
ft.log(requestUrl);
});
})
} else {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
ft.log(xhr);
ft.log(textStatus);
ft.log(requestUrl);
});
}
};
if (useTor) {
proxyRequest(() => {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
ft.log(xhr);
ft.log(textStatus);
ft.log(requestUrl);
});
})
} else {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
ft.log(xhr);
ft.log(textStatus);
ft.log(requestUrl);
});
}
}
const openReleasePage = function () {

View File

@ -21,7 +21,7 @@ let trendingTimer;
let checkTrending = true;
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
];
/**
@ -66,20 +66,20 @@ function search(page = 1) {
ft.log(data);
data.forEach((video) => {
switch (video.type) {
switch (video.type) {
case 'video':
displayVideo(video, 'search');
break;
displayVideo(video, 'search');
break;
case 'channel':
displayChannel(video);
break;
displayChannel(video);
break;
case 'playlist':
if (video.videoCount > 0) {
displayPlaylist(video, 'search');
}
break;
if (video.videoCount > 0) {
displayPlaylist(video, 'search');
}
break;
default:
}
}
});
searchView.page = searchView.page + 1;
@ -88,9 +88,9 @@ function search(page = 1) {
}
function getSearchSuggestion() {
const query = document.getElementById('search').value;
const query = document.getElementById('search').value;
invidiousAPI('search/suggestions', '', {
invidiousAPI('search/suggestions', '', {
q: query,
}, function (data) {
searchSuggestionsView.suggestionList = data.suggestions;
@ -98,9 +98,9 @@ function getSearchSuggestion() {
}
function hideSearchSuggestion() {
if (!$('.searchSuggestions').is(':hover')) {
searchSuggestionsView.seen = false;
}
if (typeof ($('.searchSuggestions').get(0)) !== 'undefined' && !$('.searchSuggestions').is(':hover')) {
searchSuggestionsView.seen = false;
}
}
/**
@ -114,14 +114,14 @@ function hideSearchSuggestion() {
*/
function displayVideo(videoData, listType = '') {
if (videoData.paid) {
return;
return;
}
let video = {};
video.id = videoData.videoId;
if (videoData.type == 'playlist') {
video.isPlaylist = true;
video.isPlaylist = true;
}
historyDb.findOne({
@ -137,54 +137,51 @@ function displayVideo(videoData, listType = '') {
video.views = videoData.viewCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
let time = videoData.lengthSeconds;
if (videoData.liveNow === true || time < 0){
video.liveText = 'LIVE NOW';
video.duration = '';
video.publishedDate = '';
video.viewText = 'watching';
}
else{
let now = Date.now();
video.liveText = '';
if (videoData.liveNow === true || time < 0) {
video.liveText = 'LIVE NOW';
video.duration = '';
video.publishedDate = '';
video.viewText = 'watching';
} else {
let now = Date.now();
video.liveText = '';
if (video.views <= 1) {
video.viewText = 'view';
}
else{
video.viewText = 'views';
}
let published = new Date(videoData.published * 1000);
let hours = 0;
if (now < published.getTime()) {
video.publishedDate = 'Premieres on ' + published.toLocaleString();
}
else {
if (time >= 3600) {
hours = Math.floor(time / 3600);
time = time - hours * 3600;
}
let minutes = Math.floor(time / 60);
let seconds = time - minutes * 60;
if (seconds < 10) {
seconds = '0' + seconds;
}
if (minutes < 10 && hours > 0) {
minutes = '0' + minutes;
}
if (hours > 0) {
video.duration = hours + ":" + minutes + ":" + seconds;
if (video.views <= 1) {
video.viewText = 'view';
} else {
video.duration = minutes + ":" + seconds;
video.viewText = 'views';
}
video.publishedDate = videoData.publishedText;
}
let published = new Date(videoData.published * 1000);
let hours = 0;
if (now < published.getTime()) {
video.publishedDate = 'Premieres on ' + published.toLocaleString();
} else {
if (time >= 3600) {
hours = Math.floor(time / 3600);
time = time - hours * 3600;
}
let minutes = Math.floor(time / 60);
let seconds = time - minutes * 60;
if (seconds < 10) {
seconds = '0' + seconds;
}
if (minutes < 10 && hours > 0) {
minutes = '0' + minutes;
}
if (hours > 0) {
video.duration = hours + ":" + minutes + ":" + seconds;
} else {
video.duration = minutes + ":" + seconds;
}
video.publishedDate = videoData.publishedText;
}
}
// Include a remove icon in the list if the application is displaying the history list or saved videos.
@ -199,11 +196,10 @@ function displayVideo(videoData, listType = '') {
video.youtubeUrl = 'https://youtube.com/watch?v=' + video.id;
video.invidiousUrl = invidiousInstance + '/watch?v=' + video.id;
if (typeof(videoData.videoThumbnails) === 'string'){
video.thumbnail = videoData.videoThumbnails;
}
else {
video.thumbnail = videoData.videoThumbnails[4].url;
if (typeof (videoData.videoThumbnails) === 'string') {
video.thumbnail = videoData.videoThumbnails;
} else {
video.thumbnail = videoData.videoThumbnails[4].url;
}
video.title = videoData.title;
video.channelName = videoData.author;
@ -268,7 +264,7 @@ function displayPlaylist(playlist, listType) {
playListData.videoCount = playlist.videoCount;
if (playlist.videoCount === 0) {
return;
return;
}
playListData.isPlaylist = true;
@ -281,25 +277,24 @@ function displayPlaylist(playlist, listType) {
if (playlist.videoCount.length > 2) {
playListData.description = playlist.videos[0].title + "\r\n" + playlist.videos[1].title;
}
else {
playListData.description = playlist.videos[0].title;
playListData.description = playlist.videos[0].title + "\r\n" + playlist.videos[1].title;
} else {
playListData.description = playlist.videos[0].title;
}
if (playListData.channelName == 'YouTube' && playListData.title.includes('Mix')){
// Hide Mix playlists.
return;
if (playListData.channelName == 'YouTube' && playListData.title.includes('Mix')) {
// Hide Mix playlists.
return;
}
switch (listType) {
case 'channelPlaylist':
case 'channelPlaylist':
channelPlaylistsView.videoList = channelPlaylistsView.videoList.concat(playListData);
break;
case 'channelSearch':
case 'channelSearch':
channelSearchView.videoList = channelSearchView.videoList.concat(playListData);
break;
default:
default:
searchView.videoList = searchView.videoList.concat(playListData);
}
}
@ -357,13 +352,13 @@ function parseSearchText(url = '') {
* @return {Void}
*/
function showMostPopular() {
if (checkPopular === false && popularView.videoList.length > 0) {
ft.log('Will not load popular. Timer still on.');
loadingView.seen = false;
return;
} else {
checkPopular = false;
}
if (checkPopular === false && popularView.videoList.length > 0) {
ft.log('Will not load popular. Timer still on.');
loadingView.seen = false;
return;
} else {
checkPopular = false;
}
invidiousAPI('popular', '', {}, function (data) {
ft.log(data);
@ -395,7 +390,9 @@ function showTrending() {
checkTrending = false;
}
invidiousAPI('trending', '', {region: settingsView.region}, function (data) {
invidiousAPI('trending', '', {
region: settingsView.region
}, function (data) {
ft.log(data);
popularView.videoList = [];
@ -495,9 +492,8 @@ function checkVideoUrls(video360p, video720p, videoAudio) {
break;
}
});
}
else{
playerView.validAudio = false;
} else {
playerView.validAudio = false;
}
if (typeof (video360p) !== 'undefined') {
@ -518,14 +514,13 @@ function checkVideoUrls(video360p, video720p, videoAudio) {
default:
ft.log('360p is valid');
if (currentQuality === '720p' && typeof (video720p) === 'undefined') {
playerView.currentQuality = '360p';
playerView.currentQuality = '360p';
}
break;
}
});
}
else{
playerView.valid360p = false;
} else {
playerView.valid360p = false;
}
if (typeof (video720p) !== 'undefined') {
@ -536,7 +531,7 @@ function checkVideoUrls(video360p, video720p, videoAudio) {
showToast('Found valid URL for 720p, but returned a 404. Video type might be available in the future.');
playerView.valid720p = false;
if (typeof (valid360) !== 'undefined') {
playerView.currentQuality = '360p';
playerView.currentQuality = '360p';
}
break;
case 403:
@ -549,8 +544,7 @@ function checkVideoUrls(video360p, video720p, videoAudio) {
break;
}
});
}
else{
playerView.valid720p = false;
} else {
playerView.valid720p = false;
}
}

View File

@ -25,42 +25,41 @@
* @return {Void}
*/
function invidiousAPI(resource, id, params, success, fail = function(xhr){
if (typeof(xhr.responseJSON.error) !== 'undefined') {
showToast('Invidious API Error: ' + xhr.responseJSON.error);
}
else {
showToast('There was an error calling the Invidious API');
}
loadingView.seen = false;
function invidiousAPI(resource, id, params, success, fail = function (xhr) {
if (typeof (xhr.responseJSON.error) !== 'undefined') {
showToast('Invidious API Error: ' + xhr.responseJSON.error);
} else {
showToast('There was an error calling the Invidious API');
}
loadingView.seen = false;
}) {
let requestUrl = invidiousInstance + '/api/v1/' + resource + '/' + id + '?' + $.param(params);
let requestUrl = invidiousInstance + '/api/v1/' + resource + '/' + id + '?' + $.param(params);
if (useTor) {
if (useTor) {
proxyRequest(() => {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
ft.log(xhr);
ft.log(textStatus);
ft.log(requestUrl);
});
})
proxyRequest(() => {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
ft.log(xhr);
ft.log(textStatus);
ft.log(requestUrl);
});
})
} else {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
ft.log(xhr);
ft.log(textStatus);
ft.log(requestUrl);
});
}
} else {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
ft.log(xhr);
ft.log(textStatus);
ft.log(requestUrl);
});
}
}
/**
@ -76,14 +75,14 @@ function youtubedlGetInfo(videoId, callback) {
let url = 'https://youtube.com/watch?v=' + videoId;
let options = ['--all-subs', '--write-subs'];
ytdl.getInfo(url, options, function(err, info) {
if (err) {
showToast(err.message);
loadingView.seen = false;
ft.log(err);
ft.log(info);
return;
}
ytdl.getInfo(url, options, function (err, info) {
if (err) {
showToast(err.message);
loadingView.seen = false;
ft.log(err);
ft.log(info);
return;
}
ft.log('Success');
callback(info);

View File

@ -16,8 +16,8 @@
*/
.channelDefaultBanner {
width: 100%;
height: 200px;
width: 100%;
height: 200px;
}
.channelViewBanner {
@ -66,15 +66,15 @@
}
.channelTabOption {
display: inline-block;
padding: 15px;
font-size: 20px;
cursor: pointer;
margin-bottom: -8px;
-webkit-transition: background 0.2s ease-out;
-moz-transition: background 0.2s ease-out;
-o-transition: background 0.2s ease-out;
transition: background 0.2s ease-out;
display: inline-block;
padding: 15px;
font-size: 20px;
cursor: pointer;
margin-bottom: -8px;
-webkit-transition: background 0.2s ease-out;
-moz-transition: background 0.2s ease-out;
-o-transition: background 0.2s ease-out;
transition: background 0.2s ease-out;
}
.channelTabOption:hover {
@ -84,20 +84,20 @@
}
.channelVideosSortSelect {
float: right;
top: 10px;
margin-right: 10px;
float: right;
top: 10px;
margin-right: 10px;
}
.channelSearch {
float: left;
margin-left: 15px;
width: 300px;
float: left;
margin-left: 15px;
width: 300px;
}
.channelSearch input {
width: 100%;
margin: auto;
width: 100%;
margin: auto;
}
.channelViewDescription {
@ -105,11 +105,11 @@
}
.featuredChannel {
display: inline-block;
width: 120px;
display: inline-block;
width: 120px;
}
.featuredChannel img {
border-radius: 200px 200px 200px 200px;
-webkit-border-radius: 200px 200px 200px 200px;
border-radius: 200px 200px 200px 200px;
-webkit-border-radius: 200px 200px 200px 200px;
}

View File

@ -44,24 +44,24 @@ input[type=text] {
}
.select-text {
border-bottom: 1px solid #E0E0E0;
color: white;
border-bottom: 1px solid #E0E0E0;
color: white;
}
.select-text option {
color: black;
color: black;
}
.select-text:focus {
border-bottom: 1px solid #EEEEEE;
border-bottom: 1px solid #EEEEEE;
}
.select:after {
border-top: 6px solid #E0E0E0;
border-top: 6px solid #E0E0E0;
}
.select-label {
color: #F5F5F5;
color: #F5F5F5;
}
.searchBar ::-webkit-input-placeholder {
@ -69,12 +69,12 @@ input[type=text] {
}
.searchSuggestions {
background-color: #424242;
color: white;
background-color: #424242;
color: white;
}
.searchSuggestions p:hover {
background-color: #262626;
background-color: #262626;
}
.topNav {
@ -99,7 +99,7 @@ input[type=text] {
}
#searchFilter {
background-color: #424242;
background-color: #424242;
}
.jumpToInput {
@ -107,11 +107,11 @@ input[type=text] {
}
.settingsSlider span {
color: white;
color: white;
}
.card {
background-color: #424242;
background-color: #424242;
}
.message {
@ -123,7 +123,7 @@ input[type=text] {
}
.channelViewContainer {
background-color: #424242;
background-color: #424242;
}
.channelViewImage {
@ -284,7 +284,7 @@ input[type=text] {
}
#backButton {
color: white;
color: white;
}
#channelIcon {
@ -335,7 +335,7 @@ input[type=text] {
}
#miniPL {
background-color: #424242;
background-color: #424242;
}
#profileSelect {

View File

@ -40,19 +40,19 @@ body {
}
.select-text {
border-bottom: 1px solid rgba(0,0,0, 0.12);
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
.select-text:focus {
border-bottom: 1px solid rgba(0,0,0, 0);
border-bottom: 1px solid rgba(0, 0, 0, 0);
}
.select:after {
border-top: 6px solid rgba(0, 0, 0, 0.12);
border-top: 6px solid rgba(0, 0, 0, 0.12);
}
.select-label {
color: rgba(0,0,0, 0.26);
color: rgba(0, 0, 0, 0.26);
}
.searchBar ::-webkit-input-placeholder {
@ -60,11 +60,11 @@ body {
}
.searchSuggestions {
background-color: white;
background-color: white;
}
.searchSuggestions p:hover {
background-color: #e0e0e0;
background-color: #e0e0e0;
}
.topNav {
@ -85,7 +85,7 @@ body {
}
#searchFilter {
background-color: white;
background-color: white;
}
.jumpToInput {
@ -93,7 +93,7 @@ body {
}
.card {
background-color: #ffffff;
background-color: #ffffff;
}
.message {
@ -105,7 +105,7 @@ body {
}
.channelViewContainer {
background-color: white;
background-color: white;
}
.channelViewImage {
@ -242,7 +242,7 @@ body {
}
#backButton {
color: #000000;
color: #000000;
}
#channelIcon {
@ -271,7 +271,7 @@ body {
}
#miniPL {
background-color: white;
background-color: white;
}
#profileSelect {

View File

@ -333,30 +333,30 @@ a {
}
.searchSuggestions {
width: 100%;
height: 200px;
overflow-y: scroll;
margin-top: -5px;
-webkit-box-shadow: -15px 25px 50px -30px rgba(0, 0, 0, 0.75);
-moz-box-shadow: -15px 25px 50px -30px rgba(0, 0, 0, 0.75);
box-shadow: -15px 25px 50px -30px rgba(0, 0, 0, 0.75);
width: 100%;
height: 200px;
overflow-y: scroll;
margin-top: -5px;
-webkit-box-shadow: -15px 25px 50px -30px rgba(0, 0, 0, 0.75);
-moz-box-shadow: -15px 25px 50px -30px rgba(0, 0, 0, 0.75);
box-shadow: -15px 25px 50px -30px rgba(0, 0, 0, 0.75);
}
.searchSuggestions p {
height: 15px;
line-height: 15px;
padding: 15px;
margin: 0;
-webkit-transition: background 0.2s ease-out;
-moz-transition: background 0.2s ease-out;
-o-transition: background 0.2s ease-out;
transition: background 0.2s ease-out;
height: 15px;
line-height: 15px;
padding: 15px;
margin: 0;
-webkit-transition: background 0.2s ease-out;
-moz-transition: background 0.2s ease-out;
-o-transition: background 0.2s ease-out;
transition: background 0.2s ease-out;
}
.searchSuggestions p:hover {
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}
#searchFilter {

View File

@ -3,7 +3,7 @@ This file is to fix some of the resizing issues introduced when full screening t
*/
#player_native_dash {
max-height: 80vh;
max-height: 80vh;
}
.mejs__container {

View File

@ -1,37 +1,37 @@
.playlistSideView {
float: left;
position: fixed;
width: 30%;
height: 100%;
overflow-y: auto;
float: left;
position: fixed;
width: 30%;
height: 100%;
overflow-y: auto;
}
.playlistSideView img {
width: 100%;
width: 100%;
}
.playlistVideo {
height: 115px;
overflow: hidden;
height: 115px;
overflow: hidden;
}
.playlistVideoView {
float: right;
width: 58%;
float: right;
width: 58%;
}
.playlistVideoThumbnail {
width: 200px;
cursor: pointer;
width: 200px;
cursor: pointer;
}
.playlistVideoThumbnail img {
width: 100%;
cursor: pointer;
width: 100%;
cursor: pointer;
}
.playlistChannel {
height: 70px;
height: 70px;
}
.playlistChannel img {
@ -43,41 +43,41 @@
}
.playlistChannel h3 {
float: left;
position: relative;
cursor: pointer;
width: 200px;
margin-left: 10px;
top: 5px;
font-size: 15px;
float: left;
position: relative;
cursor: pointer;
width: 200px;
margin-left: 10px;
top: 5px;
font-size: 15px;
}
.playlistVideoSave {
background-color: black;
color: white;
opacity: 0.7;
padding: 4px;
position: relative;
left: 176px;
bottom: 117px;
cursor: pointer;
background-color: black;
color: white;
opacity: 0.7;
padding: 4px;
position: relative;
left: 176px;
bottom: 117px;
cursor: pointer;
}
.playlistVideoTitle {
position: relative;
bottom: 160px;
margin-left: 210px;
font-weight: bold;
width: 50%;
cursor: pointer;
position: relative;
bottom: 160px;
margin-left: 210px;
font-weight: bold;
width: 50%;
cursor: pointer;
}
.playlistChannelName {
position: relative;
bottom: 160px;
margin-left: 210px;
font-size: 12px;
cursor: pointer;
position: relative;
bottom: 160px;
margin-left: 210px;
font-size: 12px;
cursor: pointer;
}
.playlistVideoOptions {
@ -86,8 +86,8 @@
}
.playlistVideoOptions i {
padding: 10px;
cursor: pointer;
padding: 10px;
cursor: pointer;
}
.playlistVideoOptions ul {
@ -125,76 +125,76 @@
}
#miniPL {
width: 100%;
width: 100%;
}
.miniPLVideo {
width: 100%;
cursor: pointer;
height: 70px;
width: 100%;
cursor: pointer;
height: 70px;
}
.miniPLThumbnail {
width: 120px;
height: 80px;
margin-right: 5px;
float: left;
width: 120px;
height: 80px;
margin-right: 5px;
float: left;
}
.miniPLIndex {
float: left;
position: relative;
width: 15px;
top: 30px;
margin-right: 35px;
float: left;
position: relative;
width: 15px;
top: 30px;
margin-right: 35px;
}
.miniPLVideoTitle {
font-weight: bold;
font-weight: bold;
}
.miniPLVideoChannelName {
font-size: 12px;
position: relative;
bottom: 10px;
font-size: 12px;
position: relative;
bottom: 10px;
}
#miniPLTitle {
font-weight: bold;
font-size: 20px;
margin-left: 20px;
padding-top: 25px;
cursor: pointer;
font-weight: bold;
font-size: 20px;
margin-left: 20px;
padding-top: 25px;
cursor: pointer;
}
#miniPLChannelName {
font-size: 15px;
font-weight: normal;
font-size: 15px;
font-weight: normal;
}
#miniPLVideoList {
padding: 10px;
overflow: scroll;
height: 375px;
padding: 10px;
overflow: scroll;
height: 375px;
}
#miniPLLoop {
margin-left: 20px;
font-size: 20px;
cursor: pointer;
margin-left: 20px;
font-size: 20px;
cursor: pointer;
}
#miniPLShuffle {
margin-left: 20px;
font-size: 20px;
cursor: pointer;
margin-left: 20px;
font-size: 20px;
cursor: pointer;
}
#miniPLDropdown {
float: right;
cursor: pointer;
font-size: 20px;
position: relative;
top: 20px;
right: 15px;
float: right;
cursor: pointer;
font-size: 20px;
position: relative;
top: 20px;
right: 15px;
}

View File

@ -1,18 +1,18 @@
.videoDivider {
display: none;
display: none;
}
.inlineBlock {
width: 285px;
height: 285px;
overflow: hidden;
display: inline-block;
width: 285px;
height: 285px;
overflow: hidden;
display: inline-block;
}
.flexGrid {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
}
.video {
@ -29,20 +29,20 @@
}
.videoThumbnail img {
width: 100%;
width: 100%;
}
.videoThumbnail i {
color: white;
background-color: black;
padding: 6px;
opacity: 0.7;
position: relative;
color: white;
background-color: black;
padding: 6px;
opacity: 0.7;
position: relative;
}
.videoSave {
bottom: 159px;
left: 247px;
bottom: 159px;
left: 247px;
}
.channelThumbnail {
@ -70,9 +70,9 @@
}
.videoOptions i {
padding: 10px;
cursor: pointer;
margin-left: 118px;
padding: 10px;
cursor: pointer;
margin-left: 118px;
}
.videoOptions ul {
@ -128,7 +128,7 @@
}
.videoDescription {
display: none;
display: none;
}
.videoDuration {
@ -144,56 +144,56 @@
}
.videoWatched {
width: 100%;
height: 155px;
background-color: black;
color: white;
position: relative;
bottom: 187px;
opacity: 0.4;
pointer-events: none;
width: 100%;
height: 155px;
background-color: black;
color: white;
position: relative;
bottom: 187px;
opacity: 0.4;
pointer-events: none;
}
.watchedProgressBar {
background-color: #f44336;
height: 3px;
position: relative;
bottom: 190px;
opacity: 0.8;
background-color: #f44336;
height: 3px;
position: relative;
bottom: 190px;
opacity: 0.8;
}
.videoPlaylist {
float: right;
width: 45%;
position: relative;
bottom: 159px;
height: 155px;
background-color: black;
opacity: 0.7;
float: right;
width: 45%;
position: relative;
bottom: 159px;
height: 155px;
background-color: black;
opacity: 0.7;
}
.videoPlaylistTotals {
font-size: 20px;
position: relative;
left: 50px;
top: 40px;
color: white;
font-size: 20px;
position: relative;
left: 50px;
top: 40px;
color: white;
}
.videoPlaylistIcon {
font-size: 25px;
top: 70px;
left: 10px;
background-color: inherit;
opacity: 1;
bottom: 0px;
font-size: 25px;
top: 70px;
left: 10px;
background-color: inherit;
opacity: 1;
bottom: 0px;
}
.viewPlaylist {
position: relative;
left: 10px;
top: 60px;
cursor: pointer;
position: relative;
left: 10px;
top: 60px;
cursor: pointer;
}
.live {

View File

@ -24,20 +24,20 @@
}
.videoThumbnail img {
width: 100%;
width: 100%;
}
.videoThumbnail i {
color: white;
background-color: black;
padding: 6px;
opacity: 0.7;
position: relative;
color: white;
background-color: black;
padding: 6px;
opacity: 0.7;
position: relative;
}
.videoSave {
bottom: 159px;
left: 247px;
bottom: 159px;
left: 247px;
}
.channelThumbnail {
@ -61,8 +61,8 @@
}
.videoOptions i {
padding: 10px;
cursor: pointer;
padding: 10px;
cursor: pointer;
}
.videoOptions ul {
@ -141,56 +141,56 @@
}
.videoWatched {
width: 100%;
height: 155px;
background-color: black;
color: white;
position: relative;
bottom: 187px;
opacity: 0.4;
pointer-events: none;
width: 100%;
height: 155px;
background-color: black;
color: white;
position: relative;
bottom: 187px;
opacity: 0.4;
pointer-events: none;
}
.watchedProgressBar {
background-color: #f44336;
height: 3px;
position: relative;
bottom: 190px;
opacity: 0.8;
background-color: #f44336;
height: 3px;
position: relative;
bottom: 190px;
opacity: 0.8;
}
.videoPlaylist {
float: right;
width: 45%;
position: relative;
bottom: 159px;
height: 155px;
background-color: black;
opacity: 0.7;
float: right;
width: 45%;
position: relative;
bottom: 159px;
height: 155px;
background-color: black;
opacity: 0.7;
}
.videoPlaylistTotals {
font-size: 20px;
position: relative;
left: 50px;
top: 40px;
color: white;
font-size: 20px;
position: relative;
left: 50px;
top: 40px;
color: white;
}
.videoPlaylistIcon {
font-size: 25px;
top: 70px;
left: 10px;
background-color: inherit;
opacity: 1;
bottom: 0px;
font-size: 25px;
top: 70px;
left: 10px;
background-color: inherit;
opacity: 1;
bottom: 0px;
}
.viewPlaylist {
position: relative;
left: 10px;
top: 60px;
cursor: pointer;
position: relative;
left: 10px;
top: 60px;
cursor: pointer;
}
.live {

View File

@ -1,58 +1,58 @@
<div v-if='seen' class='channelViewContainer'>
<img class='channelViewBanner' :src='banner' />
<br />
<div class='channelViewTitle'>
<img class='channelViewImage' :src='icon' />
<span class='channelViewName'>{{name}}</span>
<img class='channelViewBanner' :src='banner' />
<br />
<span class='channelViewSubs'>{{subCount}} Subscribers</span>
<div id='subscribeButton' class='channelSubButton' v-on:click='subscription(id);'>
{{subButtonText}}
<div class='channelViewTitle'>
<img class='channelViewImage' :src='icon' />
<span class='channelViewName'>{{name}}</span>
<br />
<span class='channelViewSubs'>{{subCount}} Subscribers</span>
<div id='subscribeButton' class='channelSubButton' v-on:click='subscription(id);'>
{{subButtonText}}
</div>
</div>
</div>
<br />
<br />
<div class="select channelVideosSortSelect" v-if='!aboutTabSeen'>
<select id='channelVideosSortValue' class="select-text" v-on:change='sort' >
<option v-for='option in sortOptions' :value='option.value'>{{option.label}}</option>
</select>
<span class="select-highlight"></span>
<span class="select-bar"></span>
<label class="select-label">Sort By</label>
</div>
<div class="input-text-settings channelSearch">
<label for="channelSearchInput">Search Channel</label>
<input type="text" id="channelSearchInput" onkeyup="channelSearchKeypress(event)" name="set-name" v-model="channelSearchValue" />
<span class='searchButton' v-on:click='search'><i class="fas fa-arrow-right" style='position: relative; float: right; right: 5px; bottom: 30px; cursor: pointer' title='Search'></i></span>
</div>
<br />
<br />
<br />
<br />
<br />
<div v-on:click='videoTab' class='channelTabOption'>
VIDEOS
</div>
<div v-on:click='playlistTab' class='channelTabOption'>
PLAYLISTS
</div>
<div v-on:click='aboutTab' class='channelTabOption'>
ABOUT
</div>
<div v-if='aboutTabSeen'>
<hr />
<div class='channelViewDescription'>
<span v-html='description'></span>
<br />
<br />
<div class="select channelVideosSortSelect" v-if='!aboutTabSeen'>
<select id='channelVideosSortValue' class="select-text" v-on:change='sort'>
<option v-for='option in sortOptions' :value='option.value'>{{option.label}}</option>
</select>
<span class="select-highlight"></span>
<span class="select-bar"></span>
<label class="select-label">Sort By</label>
</div>
<div class="input-text-settings channelSearch">
<label for="channelSearchInput">Search Channel</label>
<input type="text" id="channelSearchInput" onkeyup="channelSearchKeypress(event)" name="set-name" v-model="channelSearchValue" />
<span class='searchButton' v-on:click='search'><i class="fas fa-arrow-right" style='position: relative; float: right; right: 5px; bottom: 30px; cursor: pointer' title='Search'></i></span>
</div>
<br />
<br />
<br />
<br />
<br />
<div v-on:click='videoTab' class='channelTabOption'>
VIDEOS
</div>
<div v-on:click='playlistTab' class='channelTabOption'>
PLAYLISTS
</div>
<div v-on:click='aboutTab' class='channelTabOption'>
ABOUT
</div>
<div v-if='aboutTabSeen'>
<hr />
<div class='channelViewDescription'>
<span v-html='description'></span>
</div>
<hr />
<br />
<div v-if='featuredChannels.length > 0' class='center'>
<h2>Featured Channels</h2>
<div class='profileEditPadding' v-for='channel in featuredChannels' v-on:click='goToChannel(channel.authorId)'>
<img class='profileEdit' :src='channel.authorThumbnails[3].url' style='cursor: pointer;' />
<div class='profileEditName'><span>{{channel.author}}</span></div>
</div>
</div>
</div>
<hr />
<br />
<div v-if='featuredChannels.length > 0' class='center'>
<h2>Featured Channels</h2>
<div class='profileEditPadding' v-for='channel in featuredChannels' v-on:click='goToChannel(channel.authorId)'>
<img class='profileEdit' :src='channel.authorThumbnails[3].url' style='cursor: pointer;' />
<div class='profileEditName'><span>{{channel.author}}</span></div>
</div>
</div>
</div>
<hr />
</div>

View File

@ -20,12 +20,12 @@
<div onclick='goToChannel("{{authorId}}")' style="float:left;margin-right: 1em; width:48px">
<img class="userIcon" src="{{authorThumbnail}}" alt="" class="user-icon" />
</div>
<div class="comment-data">
<p onclick='goToChannel("{{authorId}}")' style='cursor: pointer; margin-left: 65px; font-weight: bold;'>{{author}}</p>
<p style="margin-bottom: 0; margin-left: 65px; word-break: break-word;">{{authorComment}}</p>
<p style="font-size:80%; padding: 0; margin-left: 65px;">{{published}}</p>
<div class="comment-data">
<p onclick='goToChannel("{{authorId}}")' style='cursor: pointer; margin-left: 65px; font-weight: bold;'>{{author}}</p>
<p style="margin-bottom: 0; margin-left: 65px; word-break: break-word;">{{authorComment}}</p>
<p style="font-size:80%; padding: 0; margin-left: 65px;">{{published}}</p>
</div>
</div>
</div>
<br/>
<div class="line"></div>
<br />
<div class="line"></div>
{{/comments}}

View File

@ -1,48 +1,48 @@
<div v-if='seen'>
<div v-if='!isNewProfile' class='card'>
<div v-if="subscriptionList.length === 0" >
<h2>Subscription List for {{profileName}} Profile</h2>
<h4>This profile is empty. Add subscriptions to this profile to manage them.</h4>
</div>
<div v-else >
<h2>Subscription List for {{profileName}} Profile</h2>
<h3>{{amountSelected}} Selected</h3>
<br />
<div class='profileEditPadding' v-on:click='channel.checked = !channel.checked' v-for='channel in subscriptionList'>
<div class='profileEdit' :style="{ backgroundImage: 'url(' + channel.channelThumbnail + ')' }" style='cursor: pointer; background-size: contain;'>
</div>
<div v-if='channel.checked' class='profileEditSelected'><i class='fas fa-check'></i></div>
<div class='profileEditName'><span>{{channel.channelName}}</span></div>
<div v-if="subscriptionList.length === 0">
<h2>Subscription List for {{profileName}} Profile</h2>
<h4>This profile is empty. Add subscriptions to this profile to manage them.</h4>
</div>
<br /><br /><br />
<div class='center'>
<div v-on:click='selectAll' class='settingsButton'>
SELECT ALL
<div v-else>
<h2>Subscription List for {{profileName}} Profile</h2>
<h3>{{amountSelected}} Selected</h3>
<br />
<div class='profileEditPadding' v-on:click='channel.checked = !channel.checked' v-for='channel in subscriptionList'>
<div class='profileEdit' :style="{ backgroundImage: 'url(' + channel.channelThumbnail + ')' }" style='cursor: pointer; background-size: contain;'>
</div>
<div v-if='channel.checked' class='profileEditSelected'><i class='fas fa-check'></i></div>
<div class='profileEditName'><span>{{channel.channelName}}</span></div>
</div>
<div v-on:click='selectNone' class='settingsButton'>
SELECT NONE
<br /><br /><br />
<div class='center'>
<div v-on:click='selectAll' class='settingsButton'>
SELECT ALL
</div>
<div v-on:click='selectNone' class='settingsButton'>
SELECT NONE
</div>
<div v-if="profileName !== 'All Channels'" v-on:click='move' class='settingsButton'>
MOVE SELECTED TO
</div>
<div v-on:click='copy' class='settingsButton'>
COPY SELECTED TO
</div>
<div v-on:click='deleteChannel' style='color: #f44336' class='settingsButton'>
DELETE SELECTED
</div>
</div>
<div v-if="profileName !== 'All Channels'" v-on:click='move' class='settingsButton'>
MOVE SELECTED TO
</div>
<div v-on:click='copy' class='settingsButton'>
COPY SELECTED TO
</div>
<div v-on:click='deleteChannel' style='color: #f44336' class='settingsButton'>
DELETE SELECTED
<br />
<div class="select center">
<select id="profileListSelect" class="select-text" v-model='selectedProfile' required>
<option v-for='profile in profileList' :value='profile.name'>{{profile.name}}</option>
</select>
<span class="select-highlight"></span>
<span class="select-bar"></span>
<label class="select-label">Profile Select</label>
</div>
<h4 v-if="profileName === 'All Channels'">NOTE: Deleting a channel from the "All Channels" profile will also delete the channel from all other profiles.</h4>
</div>
<br />
<div class="select center">
<select id="profileListSelect" class="select-text" v-model='selectedProfile' required>
<option v-for='profile in profileList' :value='profile.name'>{{profile.name}}</option>
</select>
<span class="select-highlight"></span>
<span class="select-bar"></span>
<label class="select-label">Profile Select</label>
</div>
<h4 v-if="profileName === 'All Channels'">NOTE: Deleting a channel from the "All Channels" profile will also delete the channel from all other profiles.</h4>
</div>
</div>
<div class='card'>
<h2 v-if='isNewProfile'>Add New Profile</h2>

View File

@ -1,4 +1,4 @@
<div v-if="seen">
<h2 style='margin-left: 15px;'>{{ title }}</h2>
<hr />
<h2 style='margin-left: 15px;'>{{ title }}</h2>
<hr />
</div>

View File

@ -19,13 +19,14 @@
body {
background-color: #424242;
font-family: 'Roboto', sans-serif;
margin:0;
margin: 0;
overflow: hidden;
}
#legacyPlayer {
width: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="../style/mediaelementplayer.css" />
<link rel="stylesheet" href="../js/plugins/quality/quality.min.css" />
@ -33,13 +34,14 @@ body {
<link rel="stylesheet" href="../js/plugins/speed/speed.css" />
<link rel="stylesheet" href="../js/plugins/context-menu/context-menu.css" />
<link rel="stylesheet" href="../js/plugins/title/title.css" />
<div id='miniPlayer'>
<div id='miniPlayer'>
<div v-if='playerSeen && !legacySeen' class='videoPlayer'>
<video id='player' onmousemove="hideMouseTimeout()" onmouseleave="removeMouseTimeout()" :poster="videoThumbnail">
<source v-if='validDash' data-quality='Auto' type="application/dash+xml" :src="videoDash" />
<source v-if='validLive' data-quality='Live' type="application/x-mpegURL" :src="videoLive" />
<span v-html="subtitleHtml"></span>
<track kind="metadata" srclang='' class="time-rail-thumbnails" :src="'https://invidio.us/api/v1/storyboards/' + videoId + '?height=90'"></track>
<track kind="metadata" srclang='' class="time-rail-thumbnails" :src="'https://invidio.us/api/v1/storyboards/' + videoId + '?height=90'">
</track>
</video>
</div>
<div v-else-if='!playerSeen && legacySeen'>
@ -49,8 +51,11 @@ body {
<div v-else>
<span v-html="embededHtml"></span>
</div>
</div>
<script>window.$ = window.jQuery = require('jquery');</script>
</div>
<script>
window.$ = window.jQuery = require('jquery');
</script>
<script src="../js/dash.all.min.js"></script>
<script src="../js/mediaelement-and-player.js"></script>
<script src="../js/plugins/quality/quality.js"></script>

View File

@ -1,15 +1,16 @@
<div v-if='seen'>
<div v-if='playerSeen && !legacySeen' class='videoPlayer'>
<video id='player' onloadstart='checkDashSettings()' onmousemove="hideMouseTimeout()" onmouseleave="removeMouseTimeout()" :poster="videoThumbnail" onended='playNext(5)' onvolumechange='updateVolume()' >
<video id='player' onloadstart='checkDashSettings()' onmousemove="hideMouseTimeout()" onmouseleave="removeMouseTimeout()" :poster="videoThumbnail" onended='playNext(5)' onvolumechange='updateVolume()'>
<source v-if='validDash' data-quality='Auto' type="application/dash+xml" :src="videoDash" />
<source v-if='validLive' data-quality='Live' type="application/x-mpegURL" :src="videoLive" />
<span v-html="subtitleHtml"></span>
<track kind="metadata" srclang='' class="time-rail-thumbnails" :src="storyBoardUrl"></track>
<track kind="metadata" srclang='' class="time-rail-thumbnails" :src="storyBoardUrl">
</track>
</video>
</div>
<div v-else-if='!playerSeen && legacySeen'>
<video id='legacyPlayer' class='videoPlayer' onloadstart='checkLegacySettings()' onmousemove="hideMouseTimeout()" onmouseleave="removeMouseTimeout()" :poster="videoThumbnail" onended='playNextVideo()' onvolumechange='updateVolume()' :src='videoUrl' controls="controls" v-html="subtitleHtml" >
<video id='legacyPlayer' class='videoPlayer' onloadstart='checkLegacySettings()' onmousemove="hideMouseTimeout()" onmouseleave="removeMouseTimeout()" :poster="videoThumbnail" onended='playNextVideo()' onvolumechange='updateVolume()' :src='videoUrl' controls="controls" v-html="subtitleHtml">
</video>
</div>
<div v-else>

View File

@ -21,46 +21,46 @@
<div class='playlistThumbnail'>
<img :src='thumbnail' />
</div>
<h2>{{title}}</h2>
<hr />
<div v-on:click='channel(channelId)' class='playlistChannel'>
<img :src='channelThumbnail' />
<h3>{{channelName}}</h3>
<h2>{{title}}</h2>
<hr />
<div v-on:click='channel(channelId)' class='playlistChannel'>
<img :src='channelThumbnail' />
<h3>{{channelName}}</h3>
</div>
<p>{{videoCount}} videos - {{viewCount}} views - Last updated on {{lastUpdated}}</p>
<hr />
<p v-html='description'></p>
</div>
<p>{{videoCount}} videos - {{viewCount}} views - Last updated on {{lastUpdated}}</p>
<hr />
<p v-html='description'></p>
</div>
<div class='playlistVideoView'>
<div v-for="video in videoList">
<div class='playlistVideoOptions'>
<i class="fas fa-ellipsis-v" onclick='showVideoOptions(this)'></i>
<ul>
<a v-on:click='openYouTube(video.id)' onclick='showVideoOptions(this.parentNode.previousSibling);'>
<div class='playlistVideoView'>
<div v-for="video in videoList">
<div class='playlistVideoOptions'>
<i class="fas fa-ellipsis-v" onclick='showVideoOptions(this)'></i>
<ul>
<a v-on:click='openYouTube(video.id)' onclick='showVideoOptions(this.parentNode.previousSibling);'>
<li>Open in YouTube</li>
</a>
<li v-on:click='copyYouTube(video.id)' onclick='showVideoOptions(this.parentNode.previousSibling);'>Copy YouTube Link</li>
<a v-on:click='openInvidious(video.id)' onclick='showVideoOptions(this.parentNode.previousSibling);'>
<li v-on:click='copyYouTube(video.id)' onclick='showVideoOptions(this.parentNode.previousSibling);'>Copy YouTube Link</li>
<a v-on:click='openInvidious(video.id)' onclick='showVideoOptions(this.parentNode.previousSibling);'>
<li>Open in Invidious</li>
</a>
<li v-on:click='copyInvidious(video.id)' onclick='showVideoOptions(this.parentNode.previousSibling);'>Copy Invidious Link</li>
</ul>
</div>
<div class='playlistVideo'>
<div class='playlistVideoThumbnail'>
<img v-on:click='play(video.id)' :src='video.thumbnail' />
<p v-on:click='play(video.id)' class='videoDuration'>{{video.duration}}</p>
<i class="fas fa-history playlistVideoSave" v-on:click='toggleSave(video.id)'></i>
<div v-if='video.watched' class='videoWatched'>
WATCHED
</div>
<li v-on:click='copyInvidious(video.id)' onclick='showVideoOptions(this.parentNode.previousSibling);'>Copy Invidious Link</li>
</ul>
</div>
<p v-on:click='play(video.id)' class='playlistVideoTitle'>{{video.title}}</p>
<p v-on:click='channel(video.channelId)' class='playlistChannelName'>{{video.channelName}}</p>
<p v-on:click='play(video.id)' class='live'>{{video.liveText}}</p>
<div class='playlistVideo'>
<div class='playlistVideoThumbnail'>
<img v-on:click='play(video.id)' :src='video.thumbnail' />
<p v-on:click='play(video.id)' class='videoDuration'>{{video.duration}}</p>
<i class="fas fa-history playlistVideoSave" v-on:click='toggleSave(video.id)'></i>
<div v-if='video.watched' class='videoWatched'>
WATCHED
</div>
</div>
<p v-on:click='play(video.id)' class='playlistVideoTitle'>{{video.title}}</p>
<p v-on:click='channel(video.channelId)' class='playlistChannelName'>{{video.channelName}}</p>
<p v-on:click='play(video.id)' class='live'>{{video.liveText}}</p>
</div>
<hr />
</div>
<hr />
</div>
</div>
</div>
</div>

View File

@ -1,3 +1,3 @@
<div v-if='seen'>
<span id='progressBar' :style='{ width: progressWidth + "%" }'></span>
<span id='progressBar' :style='{ width: progressWidth + "%" }'></span>
</div>

View File

@ -1 +0,0 @@

View File

@ -1,5 +1,5 @@
<div v-if='seen'>
<div v-if='suggestionList.length > 0' onfocus='searchSuggestionView.seen = true' class='searchSuggestions' >
<p v-for='suggestion in suggestionList' v-on:click='newSearchTerm(suggestion)'>{{suggestion}}</p>
</div>
<div v-if='suggestionList.length > 0' onfocus='searchSuggestionView.seen = true' class='searchSuggestions'>
<p v-for='suggestion in suggestionList' v-on:click='newSearchTerm(suggestion)'>{{suggestion}}</p>
</div>
</div>

View File

@ -6,9 +6,9 @@
<div class='videoOptions'>
<i class="fas fa-ellipsis-v" onclick='showVideoOptions(this)'></i>
<ul>
<div v-if='video.watched'>
<li v-on:click='history(video.id)' onclick='showVideoOptions(this.parentNode.parentNode.previousSibling);'>Remove From History</li>
</div>
<div v-if='video.watched'>
<li v-on:click='history(video.id)' onclick='showVideoOptions(this.parentNode.parentNode.previousSibling);'>Remove From History</li>
</div>
<a :href='video.youtubeUrl' onclick='showVideoOptions(this.parentNode.previousSibling);'>
<li>Open in YouTube</li>
</a>
@ -59,17 +59,17 @@
<div class='channelThumbnail'>
<img v-on:click='channel(video.channelId)' :src='video.thumbnail' />
</div>
<p v-on:click='channel(video.channelId)' class='videoTitle'>{{video.channelName}}</p>
<p v-on:click='channel(video.channelId)' class='channelName'>{{video.subscriberCount}} subscribers - {{video.videoCount}} videos</p>
<p v-on:click='channel(video.channelId)' class='videoDescription'>{{video.channelDescription}}</p>
<p v-on:click='channel(video.channelId)' class='videoTitle'>{{video.channelName}}</p>
<p v-on:click='channel(video.channelId)' class='channelName'>{{video.subscriberCount}} subscribers - {{video.videoCount}} videos</p>
<p v-on:click='channel(video.channelId)' class='videoDescription'>{{video.channelDescription}}</p>
</div>
<hr class='videoDivider' />
</div>
<hr class='videoDivider' />
</div>
</div>
<div class='getNextPage' v-if='isSearch'>
<div v-on:click='nextPage' id='getNextPage'>
<i class="fas fa-search"></i> Fetch more results…
<div class='getNextPage' v-if='isSearch'>
<div v-on:click='nextPage' id='getNextPage'>
<i class="fas fa-search"></i> Fetch more results…
</div>
</div>
</div>
</div>
</div>