mirror of https://github.com/FreeTubeApp/FreeTube
Implement Local Profiles
This commit is contained in:
parent
da2a4c9076
commit
25f9ec57d1
296
src/index.html
296
src/index.html
|
@ -2,165 +2,168 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
<link rel="stylesheet" href="style/lightTheme.css">
|
||||
<link rel="stylesheet" href="style/videoGrid.css">
|
||||
<link rel="stylesheet" href="style/player.css">
|
||||
<link rel="stylesheet" href="style/playerFix.css">
|
||||
<link rel="stylesheet" href="style/channel.css">
|
||||
<link rel="stylesheet" href="style/playlist.css">
|
||||
<link rel="stylesheet" href="style/loading.css">
|
||||
<link rel="stylesheet" href="style/select.css">
|
||||
<link rel="stylesheet" href="style/fa-solid.min.css">
|
||||
<link rel="stylesheet" href="style/fontawesome-all.min.css">
|
||||
<link rel="stylesheet" href="style/mediaelementplayer.css" />
|
||||
<link rel="stylesheet" href="style/radioButton.css" />
|
||||
<link rel="stylesheet" href="style/mdSlider.css" />
|
||||
<link rel="stylesheet" href="js/plugins/title/title.css" />
|
||||
<link rel="stylesheet" href="js/plugins/quality/quality.min.css" />
|
||||
<link rel="stylesheet" href="js/plugins/loop/loop.css" />
|
||||
<link rel="stylesheet" href="js/plugins/speed/speed.css" />
|
||||
<link rel="stylesheet" href="js/plugins/context-menu/context-menu.css" />
|
||||
<link rel="shortcut icon" href="icons/iconColor.ico" type="image/x-icon" />
|
||||
<title>FreeTube Player</title>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
<link rel="stylesheet" href="style/lightTheme.css">
|
||||
<link rel="stylesheet" href="style/videoGrid.css">
|
||||
<link rel="stylesheet" href="style/player.css">
|
||||
<link rel="stylesheet" href="style/playerFix.css">
|
||||
<link rel="stylesheet" href="style/channel.css">
|
||||
<link rel="stylesheet" href="style/playlist.css">
|
||||
<link rel="stylesheet" href="style/loading.css">
|
||||
<link rel="stylesheet" href="style/select.css">
|
||||
<link rel="stylesheet" href="style/fa-solid.min.css">
|
||||
<link rel="stylesheet" href="style/fontawesome-all.min.css">
|
||||
<link rel="stylesheet" href="style/mediaelementplayer.css" />
|
||||
<link rel="stylesheet" href="style/radioButton.css" />
|
||||
<link rel="stylesheet" href="style/mdSlider.css" />
|
||||
<link rel="stylesheet" href="js/plugins/title/title.css" />
|
||||
<link rel="stylesheet" href="js/plugins/quality/quality.min.css" />
|
||||
<link rel="stylesheet" href="js/plugins/loop/loop.css" />
|
||||
<link rel="stylesheet" href="js/plugins/speed/speed.css" />
|
||||
<link rel="stylesheet" href="js/plugins/context-menu/context-menu.css" />
|
||||
<link rel="shortcut icon" href="icons/iconColor.ico" type="image/x-icon" />
|
||||
<title>FreeTube Player</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div v-if='seen' id='loading'>
|
||||
<div class="spinner">
|
||||
<div class="double-bounce1"></div>
|
||||
<div class="double-bounce2"></div>
|
||||
<div v-if='seen' id='loading'>
|
||||
<div class="spinner">
|
||||
<div class="double-bounce1"></div>
|
||||
<div class="double-bounce2"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id='confirmFunction'>
|
||||
<span id='confirmMessage'>Would you like to perform the function?</span>
|
||||
<div class='confirmButton' id='confirmYes'>Yes</div>
|
||||
<div class='confirmButton' id='confirmNo'>No</div>
|
||||
</div>
|
||||
<div id='toast'>
|
||||
<span id='toastMessage'></span>
|
||||
<i onclick='hideToast()' class="closeToast fas fa-times"></i>
|
||||
</div>
|
||||
<div id="topNav" class="topNav">
|
||||
<i onclick='toggleSideNavigation()' class="fas fa-bars" id='menuButton'></i>
|
||||
<!--<i onclick='forceSubscriptions()' class="fas fa-sync" id='reloadButton' title='Force Subscription Reload'></i>-->
|
||||
<i v-on:click='back' v-if="canShowBackButton" class="fas fa-arrow-left" id="backButton"></i>
|
||||
<div class="searchBar">
|
||||
<input id='search' class="search" type="text" placeholder="Search / Go to URL">
|
||||
<span class='searchButton' onclick='parseSearchText()'><i class="fas fa-arrow-right" style='position: relative; right: 30px; cursor: pointer' title='Search'></i></span>
|
||||
<span class='filterButton' onclick='searchFilter.seen = !searchFilter.seen'><i class="fas fa-filter" style='margin-right: -10px; cursor: pointer' title='Filter'></i></span>
|
||||
<div id='confirmFunction'>
|
||||
<span id='confirmMessage'>Would you like to perform the function?</span>
|
||||
<div class='confirmButton' id='confirmYes'>Yes</div>
|
||||
<div class='confirmButton' id='confirmNo'>No</div>
|
||||
</div>
|
||||
<img src='icons/iconBlackSmall.png' id='menuIcon' />
|
||||
<img src='icons/textBlackSmall.png' id='menuText' />
|
||||
</div>
|
||||
<div id='sideNavDisabled'></div>
|
||||
<div id="sideNav">
|
||||
<div class="sideNavContainer">
|
||||
<ul>
|
||||
<li v-on:click='subscriptions'><i class="fas fa-rss"></i> Subscriptions <i onclick='event.stopPropagation(); forceSubscriptions()' class="fas fa-sync" id='reloadButton' title='Force Subscription Reload'></i></li>
|
||||
<li v-if='!distractionFreeMode' v-on:click='trending'><i class="fas fa-fire"></i> Trending</li>
|
||||
<li v-if='!distractionFreeMode' v-on:click='popular'><i class="fas fa-users"></i> Most Popular</li>
|
||||
<li v-on:click='saved'><i class="fas fa-star"></i> Favorites</li>
|
||||
<li v-on:click='history'><i class="fas fa-history"></i> History</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<ul>
|
||||
<li v-on:click='settings'><i class="fas fa-sliders-h"></i> Settings</li>
|
||||
<li v-on:click='about'><i class="fas fa-info-circle"></i> About</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<ul id='subscriptions'>
|
||||
</ul>
|
||||
<div id='toast'>
|
||||
<span id='toastMessage'></span>
|
||||
<i onclick='hideToast()' class="closeToast fas fa-times"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div id='searchFilter' class='center' v-show='seen'>
|
||||
<h2>Search Filters</h2>
|
||||
<br />
|
||||
<div style='position: relative; bottom: 80px;' class='pure-radiobutton filter'>
|
||||
<h3 class='filterTitle'>Sort By</h3>
|
||||
<input class='radio' id='searchSortBy1' type="radio" name="searchSortBy" value="relevance" checked='checked' />
|
||||
<label for='searchSortBy1'>Most Relevant</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchSortBy2' type="radio" name="searchSortBy" value="rating" />
|
||||
<label for='searchSortBy2'>Rating</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchSortBy3' type="radio" name="searchSortBy" value="upload_date" />
|
||||
<label for='searchSortBy3'>Upload Date</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchSortBy4' type="radio" name="searchSortBy" value="view_count" />
|
||||
<label for='searchSortBy4'>View Count</label>
|
||||
</div>
|
||||
<div class='pure-radiobutton filter'>
|
||||
<h3>Time</h3>
|
||||
<input class='radio' id='searchDate1' type="radio" name="searchDate" value="" checked='checked' />
|
||||
<label for='searchDate1'>Any Time</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate2' type="radio" name="searchDate" value="hour" />
|
||||
<label for='searchDate2'>Last Hour</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate3' type="radio" name="searchDate" value="today" />
|
||||
<label for='searchDate3'>Today</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate4' type="radio" name="searchDate" value="week" />
|
||||
<label for='searchDate4'>This Week</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate5' type="radio" name="searchDate" value="month" />
|
||||
<label for='searchDate5'>This Month</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate6' type="radio" name="searchDate" value="year" />
|
||||
<label for='searchDate6'>This Year</label>
|
||||
</div>
|
||||
<div style='position: relative; bottom: 80px;' class='pure-radiobutton filter'>
|
||||
<h3 class='filterTitle'>Type</h3>
|
||||
<input class='radio' id='searchType1' type="radio" name="searchType" value="all" checked='checked' />
|
||||
<label for='searchType1'>All Types</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchType2' type="radio" name="searchType" value="video" />
|
||||
<label for='searchType2'>Videos</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchType3' type="radio" name="searchType" value="channel" />
|
||||
<label for='searchType3'>Channels</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchType4' type="radio" name="searchType" value="playlist" />
|
||||
<label for='searchType4'>Playlists</label>
|
||||
</div>
|
||||
<div style='position: relative; bottom: 120px;' class='pure-radiobutton filter'>
|
||||
<h3 class='filterTitle'>Duration</h3>
|
||||
<input class='radio' id='searchDuration1' type="radio" name="searchDuration" value="" checked='checked' />
|
||||
<label for='searchDuration1'>All Durations</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDuration2' type="radio" name="searchDuration" value="short" />
|
||||
<label for='searchDuration2'>Short (< 4 minutes)</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDuration3' type="radio" name="searchDuration" value="long" />
|
||||
<label for='searchDuration3'>Long (> 20 minutes)</label>
|
||||
</div>
|
||||
<div id="topNav" class="topNav">
|
||||
<i onclick='toggleSideNavigation()' class="fas fa-bars" id='menuButton'></i>
|
||||
<i v-on:click='back' v-if="canShowBackButton" class="fas fa-arrow-left" id="backButton"></i>
|
||||
<img src='icons/iconBlackSmall.png' id='menuIcon' />
|
||||
<img src='icons/textBlackSmall.png' id='menuText' />
|
||||
<div class="searchBar">
|
||||
<input id='search' class="search" type="text" placeholder="Search / Go to URL">
|
||||
<span class='searchButton' onclick='parseSearchText()'><i class="fas fa-arrow-right" style='position: relative; right: 30px; cursor: pointer' title='Search'></i></span>
|
||||
<span class='filterButton' onclick='searchFilter.seen = !searchFilter.seen'><i class="fas fa-filter" style='margin-right: -10px; cursor: pointer' title='Filter'></i></span>
|
||||
</div>
|
||||
<div id='currentProfileView'></div>
|
||||
<div id='profileSelectView'></div>
|
||||
</div>
|
||||
<div id='noSubscriptions' v-if='seen'>
|
||||
<h2 class="message">
|
||||
<div id='sideNavDisabled'></div>
|
||||
<div id="sideNav">
|
||||
<div class="sideNavContainer">
|
||||
<ul>
|
||||
<li v-on:click='subscriptions'><i class="fas fa-rss"></i> Subscriptions <i onclick='event.stopPropagation(); forceSubscriptions()' class="fas fa-sync" id='reloadButton' title='Force Subscription Reload'></i></li>
|
||||
<li v-if='!distractionFreeMode' v-on:click='trending'><i class="fas fa-fire"></i> Trending</li>
|
||||
<li v-if='!distractionFreeMode' v-on:click='popular'><i class="fas fa-users"></i> Most Popular</li>
|
||||
<li v-on:click='saved'><i class="fas fa-star"></i> Favorites</li>
|
||||
<li v-on:click='history'><i class="fas fa-history"></i> History</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<ul>
|
||||
<li v-on:click='settings'><i class="fas fa-sliders-h"></i> Settings</li>
|
||||
<li v-on:click='about'><i class="fas fa-info-circle"></i> About</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<ul id='subscriptions'>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div id='searchFilter' class='center' v-show='seen'>
|
||||
<h2>Search Filters</h2>
|
||||
<br />
|
||||
<div style='position: relative; bottom: 80px;' class='pure-radiobutton filter'>
|
||||
<h3 class='filterTitle'>Sort By</h3>
|
||||
<input class='radio' id='searchSortBy1' type="radio" name="searchSortBy" value="relevance" checked='checked' />
|
||||
<label for='searchSortBy1'>Most Relevant</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchSortBy2' type="radio" name="searchSortBy" value="rating" />
|
||||
<label for='searchSortBy2'>Rating</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchSortBy3' type="radio" name="searchSortBy" value="upload_date" />
|
||||
<label for='searchSortBy3'>Upload Date</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchSortBy4' type="radio" name="searchSortBy" value="view_count" />
|
||||
<label for='searchSortBy4'>View Count</label>
|
||||
</div>
|
||||
<div class='pure-radiobutton filter'>
|
||||
<h3>Time</h3>
|
||||
<input class='radio' id='searchDate1' type="radio" name="searchDate" value="" checked='checked' />
|
||||
<label for='searchDate1'>Any Time</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate2' type="radio" name="searchDate" value="hour" />
|
||||
<label for='searchDate2'>Last Hour</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate3' type="radio" name="searchDate" value="today" />
|
||||
<label for='searchDate3'>Today</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate4' type="radio" name="searchDate" value="week" />
|
||||
<label for='searchDate4'>This Week</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate5' type="radio" name="searchDate" value="month" />
|
||||
<label for='searchDate5'>This Month</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDate6' type="radio" name="searchDate" value="year" />
|
||||
<label for='searchDate6'>This Year</label>
|
||||
</div>
|
||||
<div style='position: relative; bottom: 80px;' class='pure-radiobutton filter'>
|
||||
<h3 class='filterTitle'>Type</h3>
|
||||
<input class='radio' id='searchType1' type="radio" name="searchType" value="all" checked='checked' />
|
||||
<label for='searchType1'>All Types</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchType2' type="radio" name="searchType" value="video" />
|
||||
<label for='searchType2'>Videos</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchType3' type="radio" name="searchType" value="channel" />
|
||||
<label for='searchType3'>Channels</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchType4' type="radio" name="searchType" value="playlist" />
|
||||
<label for='searchType4'>Playlists</label>
|
||||
</div>
|
||||
<div style='position: relative; bottom: 120px;' class='pure-radiobutton filter'>
|
||||
<h3 class='filterTitle'>Duration</h3>
|
||||
<input class='radio' id='searchDuration1' type="radio" name="searchDuration" value="" checked='checked' />
|
||||
<label for='searchDuration1'>All Durations</label>
|
||||
<br /><br />
|
||||
<input class='radio' id='searchDuration2' type="radio" name="searchDuration" value="short" />
|
||||
<label for='searchDuration2'>Short (
|
||||
< 4 minutes)</label> <br /><br />
|
||||
<input class='radio' id='searchDuration3' type="radio" name="searchDuration" value="long" />
|
||||
<label for='searchDuration3'>Long (> 20 minutes)</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id='noSubscriptions' v-if='seen'>
|
||||
<h2 class="message">
|
||||
Your Subscription list is currently empty. Start adding subscriptions
|
||||
to see them here.
|
||||
<br /><br />
|
||||
<i class="far fa-frown" style="font-size: 200px"></i>
|
||||
</h2>
|
||||
</div>
|
||||
<div id='channelView'></div>
|
||||
<div id='mainHeaderView'></div>
|
||||
<div id='channelVideosView'></div>
|
||||
<div id='searchView'></div>
|
||||
<div id='subscriptionView'></div>
|
||||
<div id='popularView'></div>
|
||||
<div id='trendingView'></div>
|
||||
<div id='savedView'></div>
|
||||
<div id='historyView'></div>
|
||||
<div id='playlistView'></div>
|
||||
<div id='aboutView'></div>
|
||||
<div id='settingsView'></div>
|
||||
<div id='playerView'></div>
|
||||
<div id='subscriptionManagerView'></div>
|
||||
<div id='editProfileView'></div>
|
||||
</div>
|
||||
<div id='channelView'></div>
|
||||
<div id='mainHeaderView'></div>
|
||||
<div id='channelVideosView'></div>
|
||||
<div id='searchView'></div>
|
||||
<div id='subscriptionView'></div>
|
||||
<div id='popularView'></div>
|
||||
<div id='trendingView'></div>
|
||||
<div id='savedView'></div>
|
||||
<div id='historyView'></div>
|
||||
<div id='playlistView'></div>
|
||||
<div id='aboutView'></div>
|
||||
<div id='settingsView'></div>
|
||||
<div id='playerView'></div>
|
||||
</div>
|
||||
<div id='progressView'></div>
|
||||
<div id='progressView'></div>
|
||||
</body>
|
||||
<script src="js/vue.js"></script>
|
||||
<script src="js/general.js"></script>
|
||||
|
@ -192,4 +195,5 @@
|
|||
<script src="js/plugins/context-menu/context-menu-i18n.js"></script>
|
||||
<script src="js/plugins/timerailthumbnails/vtt.min.js"></script>
|
||||
<script src="js/plugins/timerailthumbnails/mep-feature-time-rail-thumbnails.js"></script>
|
||||
|
||||
</html>
|
||||
|
|
218
src/js/events.js
218
src/js/events.js
|
@ -31,28 +31,28 @@ let showComments = function (event, continuation = '') {
|
|||
comments.attr('loaded', 'true');
|
||||
|
||||
invidiousAPI('comments', $('#comments').attr('data-video-id'), {}, (data) => {
|
||||
ft.log(data);
|
||||
ft.log(data);
|
||||
|
||||
let comments = [];
|
||||
let comments = [];
|
||||
|
||||
data.comments.forEach((object) => {
|
||||
data.comments.forEach((object) => {
|
||||
|
||||
let snippet = {
|
||||
author: object.author,
|
||||
authorId: object.authorId,
|
||||
authorThumbnail: object.authorThumbnails[0].url,
|
||||
published: object.publishedText,
|
||||
authorComment: object.content,
|
||||
}
|
||||
let snippet = {
|
||||
author: object.author,
|
||||
authorId: object.authorId,
|
||||
authorThumbnail: object.authorThumbnails[0].url,
|
||||
published: object.publishedText,
|
||||
authorComment: object.content,
|
||||
}
|
||||
|
||||
comments.push(snippet);
|
||||
})
|
||||
const commentsTemplate = require('./templates/comments.html');
|
||||
const html = mustache.render(commentsTemplate, {
|
||||
comments: comments,
|
||||
});
|
||||
comments.push(snippet);
|
||||
})
|
||||
const commentsTemplate = require('./templates/comments.html');
|
||||
const html = mustache.render(commentsTemplate, {
|
||||
comments: comments,
|
||||
});
|
||||
|
||||
$('#comments').html(html);
|
||||
$('#comments').html(html);
|
||||
});
|
||||
|
||||
comments.show();
|
||||
|
@ -67,49 +67,47 @@ let showComments = function (event, continuation = '') {
|
|||
let playPauseVideo = function (event) {
|
||||
let el = event.currentTarget;
|
||||
if (el.paused && $('.videoPlayer').is(':hover')) {
|
||||
$('.videoPlayer')[0].style.cursor = 'none';
|
||||
$('.videoPlayer')[0].style.cursor = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle keyboard shortcut commands.
|
||||
*/
|
||||
* Handle keyboard shortcut commands.
|
||||
*/
|
||||
let videoShortcutHandler = function (event) {
|
||||
let videoPlayer;
|
||||
|
||||
if (event.which == 68 && event.altKey === true) {
|
||||
$('#search').focus();
|
||||
$('#search').focus();
|
||||
}
|
||||
|
||||
if (event.which == 82 && event.shiftKey === false && event.ctrlKey === true && !$('#jumpToInput').is(':focus') && !$('#search').is(':focus')) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
forceSubscriptions();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
forceSubscriptions();
|
||||
}
|
||||
|
||||
if ((typeof(playerView) !== 'undefined' && playerView.legacySeen) || (typeof(miniPlayerView) !== 'undefined' && miniPlayerView.legacySeen)) {
|
||||
videoPlayer = $('.videoPlayer').get(0);
|
||||
}
|
||||
else {
|
||||
videoPlayer = $('#player').get(0);
|
||||
if ((typeof (playerView) !== 'undefined' && playerView.legacySeen) || (typeof (miniPlayerView) !== 'undefined' && miniPlayerView.legacySeen)) {
|
||||
videoPlayer = $('.videoPlayer').get(0);
|
||||
} else {
|
||||
videoPlayer = $('#player').get(0);
|
||||
}
|
||||
|
||||
if (typeof(videoPlayer) !== 'undefined' && !$('#jumpToInput').is(':focus') && !$('#search').is(':focus')) {
|
||||
if (typeof (videoPlayer) !== 'undefined' && !$('#jumpToInput').is(':focus') && !$('#search').is(':focus')) {
|
||||
switch (event.which) {
|
||||
case 32:
|
||||
// Space Bar
|
||||
event.preventDefault();
|
||||
if ($('.videoPlayer').is(':focus')) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if (videoPlayer.paused) {
|
||||
videoPlayer.play();
|
||||
if($('.videoPlayer').is(':hover')) {
|
||||
$('.videoPlayer')[0].style.cursor = 'none';
|
||||
}
|
||||
}
|
||||
else {
|
||||
videoPlayer.pause();
|
||||
videoPlayer.play();
|
||||
if ($('.videoPlayer').is(':hover')) {
|
||||
$('.videoPlayer')[0].style.cursor = 'none';
|
||||
}
|
||||
} else {
|
||||
videoPlayer.pause();
|
||||
}
|
||||
break;
|
||||
case 74:
|
||||
|
@ -121,13 +119,12 @@ let videoShortcutHandler = function (event) {
|
|||
// K Key
|
||||
event.preventDefault();
|
||||
if (videoPlayer.paused) {
|
||||
videoPlayer.play();
|
||||
if($('.videoPlayer').is(':hover')) {
|
||||
$('.videoPlayer')[0].style.cursor = 'none';
|
||||
}
|
||||
}
|
||||
else {
|
||||
videoPlayer.pause();
|
||||
videoPlayer.play();
|
||||
if ($('.videoPlayer').is(':hover')) {
|
||||
$('.videoPlayer')[0].style.cursor = 'none';
|
||||
}
|
||||
} else {
|
||||
videoPlayer.pause();
|
||||
}
|
||||
break;
|
||||
case 76:
|
||||
|
@ -138,19 +135,19 @@ let videoShortcutHandler = function (event) {
|
|||
case 79:
|
||||
// O Key
|
||||
event.preventDefault();
|
||||
if (videoPlayer.playbackRate > 0.25){
|
||||
let rate = videoPlayer.playbackRate - 0.25;
|
||||
videoPlayer.playbackRate = rate;
|
||||
changeVideoSpeed(rate);
|
||||
if (videoPlayer.playbackRate > 0.25) {
|
||||
let rate = videoPlayer.playbackRate - 0.25;
|
||||
videoPlayer.playbackRate = rate;
|
||||
changeVideoSpeed(rate);
|
||||
}
|
||||
break;
|
||||
case 80:
|
||||
// P Key
|
||||
event.preventDefault();
|
||||
if (videoPlayer.playbackRate < 2){
|
||||
let rate = videoPlayer.playbackRate + 0.25;
|
||||
videoPlayer.playbackRate = rate;
|
||||
changeVideoSpeed(rate);
|
||||
if (videoPlayer.playbackRate < 2) {
|
||||
let rate = videoPlayer.playbackRate + 0.25;
|
||||
videoPlayer.playbackRate = rate;
|
||||
changeVideoSpeed(rate);
|
||||
}
|
||||
break;
|
||||
case 70:
|
||||
|
@ -172,22 +169,20 @@ let videoShortcutHandler = function (event) {
|
|||
case 67:
|
||||
// C Key
|
||||
if (playerView.legacySeen) {
|
||||
let subtitleMode = videoPlayer.textTracks[0].mode;
|
||||
if (subtitleMode === 'hidden') {
|
||||
videoPlayer.textTracks[0].mode = 'showing'
|
||||
} else {
|
||||
videoPlayer.textTracks[0].mode = 'hidden'
|
||||
}
|
||||
}
|
||||
else {
|
||||
let captionOptions = $('.mejs__captions-selector-input').get();
|
||||
let subtitleMode = videoPlayer.textTracks[0].mode;
|
||||
if (subtitleMode === 'hidden') {
|
||||
videoPlayer.textTracks[0].mode = 'showing'
|
||||
} else {
|
||||
videoPlayer.textTracks[0].mode = 'hidden'
|
||||
}
|
||||
} else {
|
||||
let captionOptions = $('.mejs__captions-selector-input').get();
|
||||
|
||||
if (!captionOptions[0].labels[0].className.includes('mejs__captions-selected')) {
|
||||
captionOptions[0].click();
|
||||
}
|
||||
else {
|
||||
captionOptions[1].click();
|
||||
}
|
||||
if (!captionOptions[0].labels[0].className.includes('mejs__captions-selected')) {
|
||||
captionOptions[0].click();
|
||||
} else {
|
||||
captionOptions[1].click();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 38:
|
||||
|
@ -265,31 +260,30 @@ let videoShortcutHandler = function (event) {
|
|||
};
|
||||
|
||||
let fullscreenVideo = function (event) {
|
||||
if (playerView.legacySeen) {
|
||||
if (document.webkitFullscreenElement !== null) {
|
||||
document.webkitExitFullscreen();
|
||||
if (playerView.legacySeen) {
|
||||
if (document.webkitFullscreenElement !== null) {
|
||||
document.webkitExitFullscreen();
|
||||
} else {
|
||||
$('.videoPlayer').get(0).webkitRequestFullscreen();
|
||||
}
|
||||
} else {
|
||||
$('.videoPlayer').get(0).webkitRequestFullscreen();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$('.mejs__fullscreen-button').click();
|
||||
$('.mejs__fullscreen-button').click();
|
||||
|
||||
if (document.webkitFullscreenElement !== null) {
|
||||
console.log('changing screen size...');
|
||||
const currentWindow = electron.remote.getCurrentWindow();
|
||||
let bounds = currentWindow.getBounds();
|
||||
let newBounds = {
|
||||
height: bounds.height,
|
||||
width: bounds.width + 1,
|
||||
x: bounds.x,
|
||||
y: bounds.y,
|
||||
}
|
||||
if (document.webkitFullscreenElement !== null) {
|
||||
console.log('changing screen size...');
|
||||
const currentWindow = electron.remote.getCurrentWindow();
|
||||
let bounds = currentWindow.getBounds();
|
||||
let newBounds = {
|
||||
height: bounds.height,
|
||||
width: bounds.width + 1,
|
||||
x: bounds.x,
|
||||
y: bounds.y,
|
||||
}
|
||||
|
||||
currentWindow.setBounds(newBounds);
|
||||
currentWindow.setBounds(bounds);
|
||||
currentWindow.setBounds(newBounds);
|
||||
currentWindow.setBounds(bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -310,24 +304,38 @@ $(document).on('click', '#confirmNo', hideConfirmFunction);
|
|||
|
||||
// Open links externally by default
|
||||
$(document).on('click', 'a[href^="http"]', (event) => {
|
||||
let el = event.currentTarget;
|
||||
if (!el.href.includes('freetube://')) {
|
||||
event.preventDefault();
|
||||
shell.openExternal(el.href);
|
||||
}
|
||||
else{
|
||||
search(el.href);
|
||||
}
|
||||
let el = event.currentTarget;
|
||||
if (!el.href.includes('freetube://')) {
|
||||
event.preventDefault();
|
||||
shell.openExternal(el.href);
|
||||
} else {
|
||||
search(el.href);
|
||||
}
|
||||
});
|
||||
|
||||
// Open links externally on middle click.
|
||||
$(document).on('auxclick', 'a[href^="http"]', (event) => {
|
||||
let el = event.currentTarget;
|
||||
if (!el.href.includes('freetube://')) {
|
||||
event.preventDefault();
|
||||
shell.openExternal(el.href);
|
||||
}
|
||||
else{
|
||||
search(el.href);
|
||||
}
|
||||
let el = event.currentTarget;
|
||||
if (!el.href.includes('freetube://')) {
|
||||
event.preventDefault();
|
||||
shell.openExternal(el.href);
|
||||
} else {
|
||||
search(el.href);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('mousewheel', function (event) {
|
||||
if (playerView.seen !== false && $('.mejs__volume-slider').is(':hover')) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
if (event.deltaY <= 0) {
|
||||
// Scroll up
|
||||
changeVolume(0.05);
|
||||
} else {
|
||||
// Scroll down
|
||||
changeVolume(-0.05);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
passive: false
|
||||
});
|
||||
|
|
|
@ -72,7 +72,7 @@ let init = function () {
|
|||
height: 800,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
nodeIntegration: true,
|
||||
},
|
||||
icon: path.join(__dirname, '..', 'icons', 'iconColor.png')
|
||||
});
|
||||
|
@ -85,11 +85,11 @@ let init = function () {
|
|||
let monitorList = screen.getAllDisplays();
|
||||
let width = 0;
|
||||
for (let i = 0; i < monitorList.length - 1; i++) {
|
||||
width = width + monitorList[i].size.width;
|
||||
width = width + monitorList[i].size.width;
|
||||
}
|
||||
|
||||
if (width <= doc.value.x) {
|
||||
win.setBounds(doc.value);
|
||||
win.setBounds(doc.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,22 +103,21 @@ let init = function () {
|
|||
_id: 'proxy'
|
||||
}, (err, doc) => {
|
||||
if (doc !== null) {
|
||||
win.webContents.session.setProxy({
|
||||
proxyRules: doc.value
|
||||
}, function () {
|
||||
win.loadURL(url.format({
|
||||
pathname: path.join(__dirname, '../index.html'),
|
||||
protocol: 'file:',
|
||||
slashes: true,
|
||||
}));
|
||||
});
|
||||
}
|
||||
else {
|
||||
win.loadURL(url.format({
|
||||
pathname: path.join(__dirname, '../index.html'),
|
||||
protocol: 'file:',
|
||||
slashes: true,
|
||||
}));
|
||||
win.webContents.session.setProxy({
|
||||
proxyRules: doc.value
|
||||
}, function () {
|
||||
win.loadURL(url.format({
|
||||
pathname: path.join(__dirname, '../index.html'),
|
||||
protocol: 'file:',
|
||||
slashes: true,
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
win.loadURL(url.format({
|
||||
pathname: path.join(__dirname, '../index.html'),
|
||||
protocol: 'file:',
|
||||
slashes: true,
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -267,8 +266,8 @@ let init = function () {
|
|||
*/
|
||||
let allWindowsClosed = function () {
|
||||
if (win !== null) {
|
||||
win.webContents.session.clearStorageData([], (data) => {});
|
||||
win.webContents.session.clearCache((data) => {});
|
||||
win.webContents.session.clearStorageData([], (data) => {});
|
||||
win.webContents.session.clearCache((data) => {});
|
||||
}
|
||||
app.quit();
|
||||
};
|
||||
|
@ -284,20 +283,20 @@ let active = function () {
|
|||
};
|
||||
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (win) {
|
||||
if (win.isMinimized()) win.restore()
|
||||
win.focus()
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (win) {
|
||||
if (win.isMinimized()) win.restore()
|
||||
win.focus()
|
||||
|
||||
win.webContents.send('ping', commandLine)
|
||||
}
|
||||
})
|
||||
win.webContents.send('ping', commandLine)
|
||||
}
|
||||
})
|
||||
|
||||
// Create myWindow, load the rest of the app, etc...
|
||||
app.on('ready', init);
|
||||
// Create myWindow, load the rest of the app, etc...
|
||||
app.on('ready', init);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,14 +45,14 @@ let dialog = electron.remote.dialog; // Used for opening file browser to export
|
|||
let toastTimeout; // Timeout for toast notifications.
|
||||
let mouseTimeout; // Timeout for hiding the mouse cursor on video playback
|
||||
|
||||
require.extensions['.html'] = function(module, filename) {
|
||||
require.extensions['.html'] = function (module, filename) {
|
||||
module.exports = fs.readFileSync(filename, 'utf8');
|
||||
};
|
||||
|
||||
// Grabs the default settings from the settings database file. Makes defaults if
|
||||
// none are found.
|
||||
|
||||
electron.ipcRenderer.on('ping', function(event, message) {
|
||||
electron.ipcRenderer.on('ping', function (event, message) {
|
||||
ft.log(message);
|
||||
let url = message[message.length - 1];
|
||||
if (url) {
|
||||
|
@ -63,7 +63,7 @@ electron.ipcRenderer.on('ping', function(event, message) {
|
|||
});
|
||||
|
||||
// Listens for proxy to be set in main process
|
||||
electron.ipcRenderer.on('proxyAvailable', function(event, message) {
|
||||
electron.ipcRenderer.on('proxyAvailable', function (event, message) {
|
||||
proxyAvailable = true;
|
||||
});
|
||||
|
||||
|
@ -88,39 +88,38 @@ $(document).ready(() => {
|
|||
_id: 'invidious'
|
||||
}]
|
||||
}, (err, docs) => {
|
||||
if (typeof(docs[0]) !== 'undefined') {
|
||||
invidiousInstance = docs[0].value;
|
||||
if (typeof (docs[0]) !== 'undefined') {
|
||||
invidiousInstance = docs[0].value;
|
||||
}
|
||||
|
||||
loadingView.seen = true;
|
||||
|
||||
if (typeof(docs[1]) !== 'undefined') {
|
||||
if (typeof (docs[1]) !== 'undefined') {
|
||||
switch (docs[1].value) {
|
||||
case 'subscriptions':
|
||||
sideNavBar.subscriptions();
|
||||
break;
|
||||
case 'trending':
|
||||
sideNavBar.trending();
|
||||
break;
|
||||
case 'popular':
|
||||
sideNavBar.popular();
|
||||
break;
|
||||
case 'favorites':
|
||||
sideNavBar.saved();
|
||||
break;
|
||||
case 'history':
|
||||
sideNavBar.history();
|
||||
break;
|
||||
case 'subscriptions':
|
||||
sideNavBar.subscriptions();
|
||||
break;
|
||||
case 'trending':
|
||||
sideNavBar.trending();
|
||||
break;
|
||||
case 'popular':
|
||||
sideNavBar.popular();
|
||||
break;
|
||||
case 'favorites':
|
||||
sideNavBar.saved();
|
||||
break;
|
||||
case 'history':
|
||||
sideNavBar.history();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sideNavBar.subscriptions();
|
||||
} else {
|
||||
sideNavBar.subscriptions();
|
||||
}
|
||||
});
|
||||
|
||||
$.get('https://write.as/freetube/feed/', function(data) {
|
||||
$.get('https://write.as/freetube/feed/', function (data) {
|
||||
aboutView.rssFeed = [];
|
||||
$(data).find("item").each(function() {
|
||||
$(data).find("item").each(function () {
|
||||
let el = $(this);
|
||||
let rssData = {
|
||||
title: el.find("title").text(),
|
||||
|
@ -147,31 +146,31 @@ function toggleSideNavigation() {
|
|||
sideNav.style.display = 'inline';
|
||||
mainContainer.style.marginLeft = '250px';
|
||||
if (confirmSettings !== null) {
|
||||
confirmSettings.style.marginLeft = '250px';
|
||||
confirmSettings.style.marginLeft = '250px';
|
||||
}
|
||||
} else {
|
||||
sideNav.style.display = 'none';
|
||||
mainContainer.style.marginLeft = '0px';
|
||||
if (confirmSettings !== null) {
|
||||
confirmSettings.style.marginLeft = '0px';
|
||||
confirmSettings.style.marginLeft = '0px';
|
||||
}
|
||||
}
|
||||
|
||||
if (playerView.playerSeen) {
|
||||
// This is a really dumb way to fix the issue of the video player
|
||||
// not resizing properly when the side bar is toggled.
|
||||
// This is a really dumb way to fix the issue of the video player
|
||||
// not resizing properly when the side bar is toggled.
|
||||
|
||||
const currentWindow = electron.remote.getCurrentWindow();
|
||||
let bounds = currentWindow.getBounds();
|
||||
let newBounds = {
|
||||
height: bounds.height,
|
||||
width: bounds.width + 1,
|
||||
x: bounds.x,
|
||||
y: bounds.y,
|
||||
}
|
||||
const currentWindow = electron.remote.getCurrentWindow();
|
||||
let bounds = currentWindow.getBounds();
|
||||
let newBounds = {
|
||||
height: bounds.height,
|
||||
width: bounds.width + 1,
|
||||
x: bounds.x,
|
||||
y: bounds.y,
|
||||
}
|
||||
|
||||
currentWindow.setBounds(newBounds);
|
||||
currentWindow.setBounds(bounds);
|
||||
currentWindow.setBounds(newBounds);
|
||||
currentWindow.setBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,20 +219,25 @@ function hideToast() {
|
|||
* @return {Void}
|
||||
*/
|
||||
function confirmFunction(message, performFunction, parameters = '') {
|
||||
let confirmYes = document.getElementById('confirmYes');
|
||||
let confirmContainer = document.getElementById('confirmFunction');
|
||||
let confirmMessage = document.getElementById('confirmMessage');
|
||||
|
||||
confirmYes.removeAttribute("onclick");
|
||||
|
||||
confirmMessage.innerHTML = message;
|
||||
confirmContainer.style.visibility = 'visible';
|
||||
|
||||
$(document).on('click', '#confirmYes', (event) => {
|
||||
confirmYes.onclick = function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (parameters != '') {
|
||||
performFunction(parameters);
|
||||
} else {
|
||||
performFunction();
|
||||
}
|
||||
hideConfirmFunction();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,7 +259,7 @@ function hideConfirmFunction() {
|
|||
function hideMouseTimeout() {
|
||||
$('.videoPlayer')[0].style.cursor = 'default';
|
||||
clearTimeout(mouseTimeout);
|
||||
mouseTimeout = window.setTimeout(function() {
|
||||
mouseTimeout = window.setTimeout(function () {
|
||||
$('.videoPlayer')[0].style.cursor = 'none';
|
||||
}, 2650);
|
||||
}
|
||||
|
@ -287,7 +291,7 @@ function proxyRequest(callback) {
|
|||
let counter = 0;
|
||||
|
||||
// Wait for proxy to become available
|
||||
proxyCheckingInterval = setInterval(function() {
|
||||
proxyCheckingInterval = setInterval(function () {
|
||||
if (proxyAvailable) {
|
||||
clearInterval(proxyCheckingInterval)
|
||||
|
||||
|
|
|
@ -41,6 +41,24 @@ let invidiousInstance = 'https://invidio.us';
|
|||
let checkedSettings = false; // Used to prevent data leak when using self-hosted Invidious Instance
|
||||
let debugMode = false;
|
||||
let defaultPage = 'subscriptions';
|
||||
const colorPalette = {
|
||||
red: '#d50000',
|
||||
pink: '#C51162',
|
||||
purple: '#AA00FF',
|
||||
deepPurple: '#6200EA',
|
||||
indigo: '#304FFE',
|
||||
blue: '#2962FF',
|
||||
lightBlue: '#0091EA',
|
||||
cyan: '#00B8D4',
|
||||
teal: '#00BFA5',
|
||||
green: '#00C853',
|
||||
lightGreen: '#64DD17',
|
||||
lime: '#AEEA00',
|
||||
yellow: '#FFD600',
|
||||
amber: '#FFAB00',
|
||||
orange: '#FF6D00',
|
||||
deepOrange: '#DD2C00',
|
||||
};
|
||||
|
||||
/**
|
||||
* Display the settings screen to the user.
|
||||
|
@ -56,10 +74,10 @@ function updateSettingsView() {
|
|||
settingsDb.find({}, (err, docs) => {
|
||||
docs.forEach((setting) => {
|
||||
switch (setting['_id']) {
|
||||
case 'theme':
|
||||
if (currentTheme == '') {
|
||||
currentTheme = setting['value'];
|
||||
}
|
||||
case 'theme':
|
||||
if (currentTheme == '') {
|
||||
currentTheme = setting['value'];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -137,6 +155,9 @@ function checkDefaultSettings() {
|
|||
|
||||
let newSetting;
|
||||
|
||||
let colorPaletteKeys = Object.keys(colorPalette);
|
||||
let randomColor = colorPalette[colorPaletteKeys[colorPaletteKeys.length * Math.random() << 0]];
|
||||
|
||||
let settingDefaults = {
|
||||
'theme': 'light',
|
||||
'useTor': false,
|
||||
|
@ -159,6 +180,11 @@ function checkDefaultSettings() {
|
|||
'distractionFreeMode': false,
|
||||
'hideWatchedSubs': false,
|
||||
'videoView': 'grid',
|
||||
'profileList': [{
|
||||
name: 'Default',
|
||||
color: randomColor
|
||||
}, ],
|
||||
'defaultProfile': 'Default',
|
||||
};
|
||||
|
||||
ft.log(settingDefaults);
|
||||
|
@ -180,95 +206,130 @@ function checkDefaultSettings() {
|
|||
}
|
||||
|
||||
if (key == 'videoView') {
|
||||
enableGridView();
|
||||
enableGridView();
|
||||
}
|
||||
|
||||
if (key == 'profileList') {
|
||||
profileSelectView.profileList = settingDefaults.profileList;
|
||||
profileSelectView.setActiveProfile(0);
|
||||
|
||||
subDb.find({}, (err, docs) => {
|
||||
if (!jQuery.isEmptyObject(docs)) {
|
||||
docs.forEach((doc) => {
|
||||
subDb.update({
|
||||
channelId: doc.channelId
|
||||
}, {
|
||||
$set: {
|
||||
profile: [{
|
||||
value: 'Default'
|
||||
}]
|
||||
}
|
||||
}, {}, (err, newDoc) => {
|
||||
profileSelectView.setActiveProfile(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
switch (docs[0]['_id']) {
|
||||
case 'theme':
|
||||
setTheme(docs[0]['value']);
|
||||
break;
|
||||
case 'useTor':
|
||||
useTor = docs[0]['value'];
|
||||
break;
|
||||
case 'history':
|
||||
rememberHistory = docs[0]['value'];
|
||||
break;
|
||||
case 'autoplay':
|
||||
autoplay = docs[0]['value'];
|
||||
break;
|
||||
case 'autoplayPlaylists':
|
||||
settingsView.autoplayPlaylists = docs[0]['value'];
|
||||
break;
|
||||
case 'playNextVideo':
|
||||
settingsView.playNextVideo = docs[0]['value'];
|
||||
break;
|
||||
case 'subtitles':
|
||||
enableSubtitles = docs[0]['value'];
|
||||
break;
|
||||
case 'updates':
|
||||
checkForUpdates = docs[0]['value'];
|
||||
case 'theme':
|
||||
setTheme(docs[0]['value']);
|
||||
break;
|
||||
case 'useTor':
|
||||
useTor = docs[0]['value'];
|
||||
break;
|
||||
case 'history':
|
||||
rememberHistory = docs[0]['value'];
|
||||
break;
|
||||
case 'autoplay':
|
||||
autoplay = docs[0]['value'];
|
||||
break;
|
||||
case 'autoplayPlaylists':
|
||||
settingsView.autoplayPlaylists = docs[0]['value'];
|
||||
break;
|
||||
case 'playNextVideo':
|
||||
settingsView.playNextVideo = docs[0]['value'];
|
||||
break;
|
||||
case 'subtitles':
|
||||
enableSubtitles = docs[0]['value'];
|
||||
break;
|
||||
case 'updates':
|
||||
checkForUpdates = docs[0]['value'];
|
||||
|
||||
if (checkForUpdates) {
|
||||
checkForNewUpdate();
|
||||
}
|
||||
break;
|
||||
case 'player':
|
||||
defaultPlayer = docs[0]['value'];
|
||||
break;
|
||||
case 'quality':
|
||||
defaultQuality = docs[0]['value'];
|
||||
break;
|
||||
case 'volume':
|
||||
defaultVolume = docs[0]['value'];
|
||||
currentVolume = docs[0]['value'];
|
||||
break;
|
||||
case 'rate':
|
||||
defaultPlaybackRate = docs[0]['value'];
|
||||
break;
|
||||
case 'proxy':
|
||||
defaultProxy = docs[0]['value'];
|
||||
if (checkForUpdates) {
|
||||
checkForNewUpdate();
|
||||
}
|
||||
break;
|
||||
case 'player':
|
||||
defaultPlayer = docs[0]['value'];
|
||||
break;
|
||||
case 'quality':
|
||||
defaultQuality = docs[0]['value'];
|
||||
break;
|
||||
case 'volume':
|
||||
defaultVolume = docs[0]['value'];
|
||||
currentVolume = docs[0]['value'];
|
||||
break;
|
||||
case 'rate':
|
||||
defaultPlaybackRate = docs[0]['value'];
|
||||
break;
|
||||
case 'proxy':
|
||||
defaultProxy = docs[0]['value'];
|
||||
|
||||
if (useTor && defaultProxy) {
|
||||
electron.ipcRenderer.send("setProxy", defaultProxy);
|
||||
}
|
||||
break;
|
||||
case 'invidious':
|
||||
invidiousInstance = docs[0]['value'].replace(/\/$/, '');
|
||||
settingsView.invidiousInstance = invidiousInstance;
|
||||
break;
|
||||
case 'region':
|
||||
defaultRegion = docs[0]['value'];
|
||||
settingsView.region = docs[0]['value'];
|
||||
break;
|
||||
case 'localScrape':
|
||||
getVideosLocally = docs[0]['value'];
|
||||
settingsView.localScrape = docs[0]['value'];
|
||||
break;
|
||||
case 'debugMode':
|
||||
debugMode = docs[0]['value'];
|
||||
settingsView.debugMode = docs[0]['value'];
|
||||
break;
|
||||
case 'startScreen':
|
||||
defaultPage = docs[0]['value'];
|
||||
break;
|
||||
case 'distractionFreeMode':
|
||||
settingsView.setDistractionFreeMode(docs[0]['value']);
|
||||
break;
|
||||
case 'hideWatchedSubs':
|
||||
hideWatchedSubs = docs[0]['value'];
|
||||
settingsView.hideWatchedSubs = docs[0]['value'];
|
||||
break;
|
||||
case 'videoView':
|
||||
settingsView.videoView = docs[0]['value'];
|
||||
if (settingsView.videoView == 'grid') {
|
||||
enableGridView();
|
||||
}
|
||||
else {
|
||||
enableListView();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (useTor && defaultProxy) {
|
||||
electron.ipcRenderer.send("setProxy", defaultProxy);
|
||||
}
|
||||
break;
|
||||
case 'invidious':
|
||||
invidiousInstance = docs[0]['value'].replace(/\/$/, '');
|
||||
settingsView.invidiousInstance = invidiousInstance;
|
||||
break;
|
||||
case 'region':
|
||||
defaultRegion = docs[0]['value'];
|
||||
settingsView.region = docs[0]['value'];
|
||||
break;
|
||||
case 'localScrape':
|
||||
getVideosLocally = docs[0]['value'];
|
||||
settingsView.localScrape = docs[0]['value'];
|
||||
break;
|
||||
case 'debugMode':
|
||||
debugMode = docs[0]['value'];
|
||||
settingsView.debugMode = docs[0]['value'];
|
||||
break;
|
||||
case 'startScreen':
|
||||
defaultPage = docs[0]['value'];
|
||||
break;
|
||||
case 'distractionFreeMode':
|
||||
settingsView.setDistractionFreeMode(docs[0]['value']);
|
||||
break;
|
||||
case 'hideWatchedSubs':
|
||||
hideWatchedSubs = docs[0]['value'];
|
||||
settingsView.hideWatchedSubs = docs[0]['value'];
|
||||
break;
|
||||
case 'videoView':
|
||||
settingsView.videoView = docs[0]['value'];
|
||||
if (settingsView.videoView == 'grid') {
|
||||
enableGridView();
|
||||
} else {
|
||||
enableListView();
|
||||
}
|
||||
break;
|
||||
case 'profileList':
|
||||
profileSelectView.profileList = docs[0]['value'];
|
||||
break;
|
||||
case 'defaultProfile':
|
||||
let profileIndex = profileSelectView.profileList.findIndex(x => x.name === docs[0]['value']);
|
||||
settingsView.defaultProfile = docs[0]['value'];
|
||||
|
||||
if (profileIndex === -1) {
|
||||
profileSelectView.setActiveProfile(0);
|
||||
} else {
|
||||
profileSelectView.setActiveProfile(profileIndex);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -334,7 +395,7 @@ function updateSettings() {
|
|||
_id: 'theme'
|
||||
}, {
|
||||
value: theme
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
});
|
||||
|
@ -344,7 +405,7 @@ function updateSettings() {
|
|||
_id: 'useTor'
|
||||
}, {
|
||||
value: torSwitch
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
useTor = torSwitch;
|
||||
|
@ -355,7 +416,7 @@ function updateSettings() {
|
|||
_id: 'proxy'
|
||||
}, {
|
||||
value: proxyAddress
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
defaultProxy = proxyAddress;
|
||||
|
@ -366,7 +427,7 @@ function updateSettings() {
|
|||
_id: 'invidious'
|
||||
}, {
|
||||
value: invidious
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
settingsView.invidiousInstance = invidious;
|
||||
|
@ -378,7 +439,7 @@ function updateSettings() {
|
|||
_id: 'history'
|
||||
}, {
|
||||
value: historySwitch
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
rememberHistory = historySwitch;
|
||||
|
@ -389,7 +450,7 @@ function updateSettings() {
|
|||
_id: 'autoplay'
|
||||
}, {
|
||||
value: autoplaySwitch
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
autoplay = autoplaySwitch;
|
||||
|
@ -400,7 +461,7 @@ function updateSettings() {
|
|||
_id: 'autoplayPlaylists'
|
||||
}, {
|
||||
value: autoplayPlaylistsSwitch
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
settingsView.autoplayPlaylists = autoplayPlaylistsSwitch;
|
||||
|
@ -411,7 +472,7 @@ function updateSettings() {
|
|||
_id: 'playNextVideo'
|
||||
}, {
|
||||
value: playNextVideoSwitch
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
settingsView.playNextVideo = playNextVideoSwitch;
|
||||
|
@ -422,7 +483,7 @@ function updateSettings() {
|
|||
_id: 'localScrape'
|
||||
}, {
|
||||
value: localSwitch
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
getVideosLocally = localSwitch;
|
||||
|
@ -433,7 +494,7 @@ function updateSettings() {
|
|||
_id: 'subtitles'
|
||||
}, {
|
||||
value: subtitlesSwitch
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
enableSubtitles = subtitlesSwitch;
|
||||
|
@ -444,7 +505,7 @@ function updateSettings() {
|
|||
_id: 'updates'
|
||||
}, {
|
||||
value: updatesSwitch
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
checkForUpdates = updatesSwitch;
|
||||
|
@ -455,7 +516,7 @@ function updateSettings() {
|
|||
_id: 'player'
|
||||
}, {
|
||||
value: playerSelect
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
defaultPlayer = playerSelect;
|
||||
|
@ -466,7 +527,7 @@ function updateSettings() {
|
|||
_id: 'quality'
|
||||
}, {
|
||||
value: qualitySelect
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
defaultQuality = qualitySelect;
|
||||
|
@ -477,7 +538,7 @@ function updateSettings() {
|
|||
_id: 'volume'
|
||||
}, {
|
||||
value: volumeSelect
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
defaultVolume = volumeSelect;
|
||||
|
@ -489,7 +550,7 @@ function updateSettings() {
|
|||
_id: 'rate'
|
||||
}, {
|
||||
value: rateSelect
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
defaultPlaybackRate = rateSelect;
|
||||
|
@ -500,7 +561,7 @@ function updateSettings() {
|
|||
_id: 'region'
|
||||
}, {
|
||||
value: regionSelect
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
settingsView.region = regionSelect;
|
||||
|
@ -511,7 +572,7 @@ function updateSettings() {
|
|||
_id: 'debugMode'
|
||||
}, {
|
||||
value: debugMode
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
settingsView.debugMode = debugMode;
|
||||
|
@ -522,7 +583,7 @@ function updateSettings() {
|
|||
_id: 'startScreen'
|
||||
}, {
|
||||
value: pageSelect
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
});
|
||||
|
@ -532,7 +593,7 @@ function updateSettings() {
|
|||
_id: 'distractionFreeMode'
|
||||
}, {
|
||||
value: distractionFreeMode
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
});
|
||||
|
@ -542,7 +603,7 @@ function updateSettings() {
|
|||
_id: 'hideWatchedSubs'
|
||||
}, {
|
||||
value: hideSubs
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
hideWatchedSubs = hideSubs;
|
||||
|
@ -554,14 +615,13 @@ function updateSettings() {
|
|||
_id: 'videoView'
|
||||
}, {
|
||||
value: videoViewType
|
||||
}, {}, function(err, numReplaced) {
|
||||
}, {}, function (err, numReplaced) {
|
||||
ft.log(err);
|
||||
ft.log(numReplaced);
|
||||
if (settingsView.videoView == 'grid') {
|
||||
enableGridView();
|
||||
}
|
||||
else {
|
||||
enableListView();
|
||||
enableGridView();
|
||||
} else {
|
||||
enableListView();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -614,24 +674,24 @@ function setTheme(option) {
|
|||
|
||||
// Grab the css file to be used.
|
||||
switch (option) {
|
||||
case 'light':
|
||||
cssFile = './style/lightTheme.css';
|
||||
document.getElementById('menuText').src = 'icons/textBlackSmall.png';
|
||||
document.getElementById('menuIcon').src = 'icons/iconBlackSmall.png';
|
||||
document.getElementById('menuButton').style.color = 'black';
|
||||
document.getElementById('reloadButton').style.color = 'black';
|
||||
break;
|
||||
case 'dark':
|
||||
cssFile = './style/darkTheme.css';
|
||||
document.getElementById('menuText').src = 'icons/textColorSmall.png';
|
||||
document.getElementById('menuIcon').src = 'icons/iconColorSmall.png';
|
||||
document.getElementById('menuButton').style.color = 'white';
|
||||
document.getElementById('reloadButton').style.color = 'white';
|
||||
break;
|
||||
default:
|
||||
// Default to the light theme
|
||||
cssFile = './style/lightTheme.css';
|
||||
break;
|
||||
case 'light':
|
||||
cssFile = './style/lightTheme.css';
|
||||
document.getElementById('menuText').src = 'icons/textBlackSmall.png';
|
||||
document.getElementById('menuIcon').src = 'icons/iconBlackSmall.png';
|
||||
document.getElementById('menuButton').style.color = 'black';
|
||||
document.getElementById('reloadButton').style.color = 'black';
|
||||
break;
|
||||
case 'dark':
|
||||
cssFile = './style/darkTheme.css';
|
||||
document.getElementById('menuText').src = 'icons/textColorSmall.png';
|
||||
document.getElementById('menuIcon').src = 'icons/iconColorSmall.png';
|
||||
document.getElementById('menuButton').style.color = 'white';
|
||||
document.getElementById('reloadButton').style.color = 'white';
|
||||
break;
|
||||
default:
|
||||
// Default to the light theme
|
||||
cssFile = './style/lightTheme.css';
|
||||
break;
|
||||
}
|
||||
newTheme.setAttribute("href", cssFile);
|
||||
|
||||
|
@ -640,31 +700,31 @@ function setTheme(option) {
|
|||
}
|
||||
|
||||
function enableGridView() {
|
||||
let cssFile;
|
||||
const currentView = document.getElementsByTagName("link").item(2);
|
||||
let cssFile;
|
||||
const currentView = document.getElementsByTagName("link").item(2);
|
||||
|
||||
// Create a link element
|
||||
const newView = document.createElement("link");
|
||||
newView.setAttribute("rel", "stylesheet");
|
||||
newView.setAttribute("type", "text/css");
|
||||
newView.setAttribute("href", './style/videoGrid.css');
|
||||
// Create a link element
|
||||
const newView = document.createElement("link");
|
||||
newView.setAttribute("rel", "stylesheet");
|
||||
newView.setAttribute("type", "text/css");
|
||||
newView.setAttribute("href", './style/videoGrid.css');
|
||||
|
||||
// Replace the current theme with the new theme
|
||||
document.getElementsByTagName("head").item(0).replaceChild(newView, currentView);
|
||||
// Replace the current theme with the new theme
|
||||
document.getElementsByTagName("head").item(0).replaceChild(newView, currentView);
|
||||
}
|
||||
|
||||
function enableListView() {
|
||||
let cssFile;
|
||||
const currentView = document.getElementsByTagName("link").item(2);
|
||||
let cssFile;
|
||||
const currentView = document.getElementsByTagName("link").item(2);
|
||||
|
||||
// Create a link element
|
||||
const newView = document.createElement("link");
|
||||
newView.setAttribute("rel", "stylesheet");
|
||||
newView.setAttribute("type", "text/css");
|
||||
newView.setAttribute("href", './style/videoList.css');
|
||||
// Create a link element
|
||||
const newView = document.createElement("link");
|
||||
newView.setAttribute("rel", "stylesheet");
|
||||
newView.setAttribute("type", "text/css");
|
||||
newView.setAttribute("href", './style/videoList.css');
|
||||
|
||||
// Replace the current theme with the new theme
|
||||
document.getElementsByTagName("head").item(0).replaceChild(newView, currentView);
|
||||
// Replace the current theme with the new theme
|
||||
document.getElementsByTagName("head").item(0).replaceChild(newView, currentView);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -725,8 +785,8 @@ function importSubscriptions() {
|
|||
name: 'Database File',
|
||||
extensions: ['*']
|
||||
}, ]
|
||||
}, function(fileLocation) {
|
||||
if (typeof(fileLocation) === 'undefined') {
|
||||
}, function (fileLocation) {
|
||||
if (typeof (fileLocation) === 'undefined') {
|
||||
ft.log('Import Aborted');
|
||||
return;
|
||||
}
|
||||
|
@ -735,14 +795,14 @@ function importSubscriptions() {
|
|||
let fileType = (i < 0) ? '' : fileLocation[0].substr(i);
|
||||
ft.log(fileType);
|
||||
|
||||
fs.readFile(fileLocation[0], function(readErr, data) {
|
||||
fs.readFile(fileLocation[0], function (readErr, data) {
|
||||
if (readErr) {
|
||||
showToast('Unable to read file. File may be corrupt or have invalid permissions.');
|
||||
throw readErr;
|
||||
}
|
||||
|
||||
if (data.includes("<opml")) {
|
||||
getOpml(data, function(error, json) {
|
||||
getOpml(data, function (error, json) {
|
||||
if (!error) {
|
||||
clearFile('subscriptions', false);
|
||||
importOpmlSubs(json['children'][0]['children']);
|
||||
|
@ -757,15 +817,64 @@ function importSubscriptions() {
|
|||
return;
|
||||
}
|
||||
|
||||
clearFile('subscriptions', false);
|
||||
subDb.remove({}, {
|
||||
multi: true
|
||||
}, function (err, numRemoved) {});
|
||||
let textDecode = new TextDecoder("utf-8").decode(data);
|
||||
textDecode = textDecode.split("\n");
|
||||
textDecode.pop();
|
||||
console.log(textDecode);
|
||||
|
||||
fs.writeFile(appDatabaseFile, data, function(writeErr) {
|
||||
if (writeErr) {
|
||||
showToast('Unable to create file. Please check your permissions and try again.');
|
||||
throw writeErr;
|
||||
textDecode.forEach((data) => {
|
||||
let parsedData = JSON.parse(data);
|
||||
|
||||
let newSubscription = {
|
||||
channelId: parsedData.channelId,
|
||||
channelName: parsedData.channelName,
|
||||
channelThumbnail: parsedData.channelThumbnail,
|
||||
}
|
||||
|
||||
if (typeof (parsedData.profile) !== 'undefined') {
|
||||
let profileList = [];
|
||||
parsedData.profile.forEach((profile) => {
|
||||
if (profileList.indexOf(profile.value) !== -1) {
|
||||
console.log('found duplicate');
|
||||
return;
|
||||
}
|
||||
|
||||
profileList.push(profile.value);
|
||||
|
||||
// Sometimes adding the same channel to the database too fast
|
||||
// will duplicate the channel in the wrong profile. The wait
|
||||
// time to add to the database is randomized to prevent this.
|
||||
let randomNumber = Math.floor((Math.random() * 10000) + 1);
|
||||
window.setTimeout(() => {
|
||||
let existingProfileIndex = profileSelectView.profileList.findIndex(x => x.name === profile);
|
||||
if (existingProfileIndex === -1) {
|
||||
// User doesn't have this profile, let's create it.
|
||||
|
||||
let colorPaletteKeys = Object.keys(colorPalette);
|
||||
let randomColor = colorPalette[colorPaletteKeys[colorPaletteKeys.length * Math.random() << 0]];
|
||||
editProfileView.isNewProfile = true;
|
||||
editProfileView.newProfileColor = randomColor;
|
||||
editProfileView.newProfileName = profile.value;
|
||||
editProfileView.updateProfile(false);
|
||||
}
|
||||
addSubscription(newSubscription, true, profile.value);
|
||||
displaySubs();
|
||||
}, randomNumber);
|
||||
});
|
||||
} else {
|
||||
let randomNumber = Math.floor((Math.random() * 1000) + 1);
|
||||
window.setTimeout(() => {
|
||||
addSubscription(newSubscription)
|
||||
}, randomNumber);
|
||||
}
|
||||
showToast('Susbcriptions have been successfully imported. Please restart FreeTube for the changes to take effect.');
|
||||
});
|
||||
|
||||
window.setTimeout(() => {
|
||||
displaySubs()
|
||||
}, 8000);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -829,42 +938,42 @@ function exportSubscriptions() {
|
|||
}
|
||||
|
||||
const dateYear = date.getFullYear();
|
||||
const dateString = 'freetube-subscriptions-' + dateYear + '-' + dateMonth + '-' + dateDay;
|
||||
const dateString = 'freetube-subscriptions-' + dateYear + '-' + dateMonth + '-' + dateDay + '.db';
|
||||
|
||||
switch (document.querySelector('#exportSelect').value) {
|
||||
|
||||
case "NewPipe":
|
||||
exportNewpipeSubscriptions(dateYear, dateMonth, dateDay);
|
||||
break;
|
||||
case "OPML":
|
||||
exportOpmlSubscriptions(dateYear, dateMonth, dateDay);
|
||||
break;
|
||||
default:
|
||||
// Open user file browser. User gives location of file to be created.
|
||||
dialog.showSaveDialog({
|
||||
defaultPath: dateString,
|
||||
filters: [{
|
||||
name: 'Database File',
|
||||
extensions: ['db']
|
||||
}, ]
|
||||
}, function(fileLocation) {
|
||||
ft.log(fileLocation);
|
||||
if (typeof(fileLocation) === 'undefined') {
|
||||
ft.log('Export Aborted');
|
||||
return;
|
||||
case "NewPipe":
|
||||
exportNewpipeSubscriptions(dateYear, dateMonth, dateDay);
|
||||
break;
|
||||
case "OPML":
|
||||
exportOpmlSubscriptions(dateYear, dateMonth, dateDay);
|
||||
break;
|
||||
default:
|
||||
// Open user file browser. User gives location of file to be created.
|
||||
dialog.showSaveDialog({
|
||||
defaultPath: dateString,
|
||||
filters: [{
|
||||
name: 'Database File',
|
||||
extensions: ['db']
|
||||
}, ]
|
||||
}, function (fileLocation) {
|
||||
ft.log(fileLocation);
|
||||
if (typeof (fileLocation) === 'undefined') {
|
||||
ft.log('Export Aborted');
|
||||
return;
|
||||
}
|
||||
fs.readFile(appDatabaseFile, function (readErr, data) {
|
||||
if (readErr) {
|
||||
throw readErr;
|
||||
}
|
||||
fs.readFile(appDatabaseFile, function(readErr, data) {
|
||||
if (readErr) {
|
||||
throw readErr;
|
||||
fs.writeFile(fileLocation, data, function (writeErr) {
|
||||
if (writeErr) {
|
||||
throw writeErr;
|
||||
}
|
||||
fs.writeFile(fileLocation, data, function(writeErr) {
|
||||
if (writeErr) {
|
||||
throw writeErr;
|
||||
}
|
||||
showToast('Susbcriptions have been successfully exported');
|
||||
});
|
||||
})
|
||||
});
|
||||
showToast('Susbcriptions have been successfully exported');
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -882,9 +991,9 @@ function exportNewpipeSubscriptions(dateYear, dateMonth, dateDay) {
|
|||
name: 'JSON',
|
||||
extensions: ['json']
|
||||
}, ]
|
||||
}, function(fileLocation) {
|
||||
}, function (fileLocation) {
|
||||
ft.log(fileLocation);
|
||||
if (typeof(fileLocation) === 'undefined') {
|
||||
if (typeof (fileLocation) === 'undefined') {
|
||||
ft.log('Export Aborted');
|
||||
return;
|
||||
}
|
||||
|
@ -905,7 +1014,7 @@ function exportNewpipeSubscriptions(dateYear, dateMonth, dateDay) {
|
|||
newpipe.subscriptions.push(subs);
|
||||
}
|
||||
|
||||
fs.writeFile(fileLocation, JSON.stringify(newpipe), function(writeErr) {
|
||||
fs.writeFile(fileLocation, JSON.stringify(newpipe), function (writeErr) {
|
||||
if (writeErr) {
|
||||
throw writeErr;
|
||||
} else {
|
||||
|
@ -931,9 +1040,9 @@ function exportOpmlSubscriptions(dateYear, dateMonth, dateDay) {
|
|||
name: 'OPML',
|
||||
extensions: ['opml']
|
||||
}, ]
|
||||
}, function(fileLocation) {
|
||||
}, function (fileLocation) {
|
||||
ft.log(fileLocation);
|
||||
if (typeof(fileLocation) === 'undefined') {
|
||||
if (typeof (fileLocation) === 'undefined') {
|
||||
ft.log('Export Aborted');
|
||||
return;
|
||||
}
|
||||
|
@ -952,7 +1061,7 @@ function exportOpmlSubscriptions(dateYear, dateMonth, dateDay) {
|
|||
opml += subs;
|
||||
}
|
||||
|
||||
fs.writeFile(fileLocation, opml, function(writeErr) {
|
||||
fs.writeFile(fileLocation, opml, function (writeErr) {
|
||||
if (writeErr) {
|
||||
throw writeErr;
|
||||
}
|
||||
|
@ -974,22 +1083,22 @@ function clearFile(type, showMessage = true) {
|
|||
let dataBaseFile;
|
||||
|
||||
switch (type) {
|
||||
case 'subscriptions':
|
||||
dataBaseFile = localDataStorage + '/subscriptions.db';
|
||||
break;
|
||||
case 'history':
|
||||
dataBaseFile = localDataStorage + '/videohistory.db';
|
||||
break;
|
||||
case 'saved':
|
||||
dataBaseFile = localDataStorage + '/savedvideos.db';
|
||||
break;
|
||||
default:
|
||||
showToast('Unknown file: ' + type)
|
||||
return
|
||||
case 'subscriptions':
|
||||
dataBaseFile = localDataStorage + '/subscriptions.db';
|
||||
break;
|
||||
case 'history':
|
||||
dataBaseFile = localDataStorage + '/videohistory.db';
|
||||
break;
|
||||
case 'saved':
|
||||
dataBaseFile = localDataStorage + '/savedvideos.db';
|
||||
break;
|
||||
default:
|
||||
showToast('Unknown file: ' + type)
|
||||
return
|
||||
}
|
||||
|
||||
// Replace data with an empty string.
|
||||
fs.writeFile(dataBaseFile, '', function(err) {
|
||||
fs.writeFile(dataBaseFile, '', function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
@ -1001,11 +1110,11 @@ function clearFile(type, showMessage = true) {
|
|||
}
|
||||
|
||||
function showSettingsConfirm() {
|
||||
$('#confirmSettings').get(0).style.opacity = 0.9;
|
||||
$('#confirmSettings').get(0).style.opacity = 0.9;
|
||||
}
|
||||
|
||||
function hideSettingsConfirm() {
|
||||
$('#confirmSettings').get(0).style.opacity = 0;
|
||||
$('#confirmSettings').get(0).style.opacity = 0;
|
||||
}
|
||||
|
||||
checkDefaultSettings();
|
||||
|
|
|
@ -25,6 +25,7 @@ let subscriptionTimer;
|
|||
let forceTimer;
|
||||
let checkSubscriptions = true;
|
||||
let forceSubs = true;
|
||||
let displaySubsLock = false;
|
||||
|
||||
/**
|
||||
* Add a channel to the user's subscription database.
|
||||
|
@ -33,15 +34,46 @@ let forceSubs = true;
|
|||
*
|
||||
* @return {Void}
|
||||
*/
|
||||
function addSubscription(data, useToast = true) {
|
||||
function addSubscription(data, useToast = true, profile = '') {
|
||||
ft.log('Channel Data: ', data);
|
||||
|
||||
// Refresh the list of subscriptions on the side navigation bar.
|
||||
subDb.insert(data, (err, newDoc) => {
|
||||
if (useToast) {
|
||||
showToast('Added ' + data.channelName + ' to subscriptions.');
|
||||
let newSubscription = data;
|
||||
newSubscription.profile = [{
|
||||
value: profile
|
||||
}];
|
||||
|
||||
if (profile === '') {
|
||||
newSubscription.profile = [{
|
||||
value: profileSelectView.activeProfile.name
|
||||
}];
|
||||
}
|
||||
|
||||
subDb.find({
|
||||
channelId: data.channelId
|
||||
}, (err, docs) => {
|
||||
if (jQuery.isEmptyObject(docs)) {
|
||||
subDb.insert(newSubscription, (err, newDoc) => {
|
||||
if (useToast) {
|
||||
showToast('Added ' + newSubscription.channelName + ' to subscriptions.');
|
||||
}
|
||||
// Refresh the list of subscriptions on the side navigation bar.
|
||||
displaySubs();
|
||||
});
|
||||
} else {
|
||||
subDb.update({
|
||||
channelId: data.channelId,
|
||||
}, {
|
||||
$push: {
|
||||
profile: {
|
||||
value: newSubscription.profile[0].value
|
||||
}
|
||||
}
|
||||
}, (err, numAdded) => {
|
||||
// Refresh the list of subscriptions on the side navigation bar.
|
||||
displaySubs();
|
||||
showToast('Added ' + data.channelName + ' to subscriptions.');
|
||||
});
|
||||
}
|
||||
displaySubs();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -53,12 +85,32 @@ function addSubscription(data, useToast = true) {
|
|||
* @return {Void}
|
||||
*/
|
||||
function removeSubscription(channelId) {
|
||||
subDb.remove({
|
||||
subDb.find({
|
||||
channelId: channelId
|
||||
}, {}, (err, numRemoved) => {
|
||||
// Refresh the list of subscriptions on the side navigation bar.
|
||||
displaySubs();
|
||||
showToast('Removed channel from subscriptions.');
|
||||
}, (err, docs) => {
|
||||
if (docs[0].profile.length > 1) {
|
||||
subDb.update({
|
||||
channelId: channelId,
|
||||
}, {
|
||||
$pull: {
|
||||
profile: {
|
||||
value: profileSelectView.activeProfile.name
|
||||
}
|
||||
}
|
||||
}, (err, numAdded) => {
|
||||
// Refresh the list of subscriptions on the side navigation bar.
|
||||
displaySubs();
|
||||
showToast('Removed channel from subscriptions.');
|
||||
});
|
||||
} else {
|
||||
subDb.remove({
|
||||
channelId: channelId
|
||||
}, {}, (err, numRemoved) => {
|
||||
// Refresh the list of subscriptions on the side navigation bar.
|
||||
displaySubs();
|
||||
showToast('Removed channel from subscriptions.');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -95,15 +147,17 @@ function loadSubscriptions() {
|
|||
|
||||
invidiousAPI('channels/latest', channelId, {}, (data) => {
|
||||
data.forEach((video, index) => {
|
||||
data[index].author = results[i]['channelName'];
|
||||
historyDb.findOne({ videoId: video.videoId }, function (err, doc) {
|
||||
if(doc === null) {
|
||||
data[index].watched = false
|
||||
}
|
||||
else {
|
||||
data[index].watched = true;
|
||||
}
|
||||
});
|
||||
data[index].author = results[i]['channelName'];
|
||||
data[index].profile = results[i]['profile'];
|
||||
historyDb.findOne({
|
||||
videoId: video.videoId
|
||||
}, function (err, doc) {
|
||||
if (doc === null) {
|
||||
data[index].watched = false
|
||||
} else {
|
||||
data[index].watched = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
videoList = videoList.concat(data);
|
||||
counter = counter + 1;
|
||||
|
@ -139,11 +193,15 @@ function addSubsToView(videoList) {
|
|||
});
|
||||
|
||||
if (hideWatchedSubs) {
|
||||
videoList = videoList.filter(a => {
|
||||
return !a.watched;
|
||||
});
|
||||
videoList = videoList.filter(a => {
|
||||
return !a.watched;
|
||||
});
|
||||
}
|
||||
|
||||
videoList = videoList.filter(a => {
|
||||
return a.profile.map(x => x.value).indexOf(profileSelectView.activeProfile.name) !== -1
|
||||
});
|
||||
|
||||
videoList.sort((a, b) => {
|
||||
return b.published - a.published;
|
||||
});
|
||||
|
@ -209,12 +267,24 @@ function returnSubscriptions() {
|
|||
* @return {Void}
|
||||
*/
|
||||
function displaySubs() {
|
||||
if (displaySubsLock) {
|
||||
return;
|
||||
}
|
||||
|
||||
displaySubsLock = true;
|
||||
|
||||
const subList = document.getElementById('subscriptions');
|
||||
|
||||
subList.innerHTML = '';
|
||||
|
||||
// Sort alphabetically
|
||||
subDb.find({}).sort({
|
||||
subDb.find({
|
||||
profile: {
|
||||
$elemMatch: {
|
||||
value: profileSelectView.activeProfile.name
|
||||
}
|
||||
}
|
||||
}).sort({
|
||||
channelName: 1
|
||||
}).exec((err, subs) => {
|
||||
subs.forEach((channel) => {
|
||||
|
@ -230,6 +300,8 @@ function displaySubs() {
|
|||
const subscriptionsHtml = $('#subscriptions').html();
|
||||
$('#subscriptions').html(subscriptionsHtml + rendered);
|
||||
});
|
||||
|
||||
displaySubsLock = false;
|
||||
});
|
||||
|
||||
// Add onclick function
|
||||
|
@ -268,10 +340,20 @@ function toggleSubscription(data) {
|
|||
*
|
||||
* @return {promise} - A boolean value if the channel is currently subscribed or not.
|
||||
*/
|
||||
function isSubscribed(channelId) {
|
||||
function isSubscribed(channelId, profile = profileSelectView.activeProfile.name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
subDb.find({
|
||||
channelId: channelId
|
||||
$and: [{
|
||||
channelId: channelId
|
||||
},
|
||||
{
|
||||
profile: {
|
||||
$elemMatch: {
|
||||
value: profile
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
}, (err, docs) => {
|
||||
if (jQuery.isEmptyObject(docs)) {
|
||||
resolve(false);
|
||||
|
|
2085
src/js/templates.js
2085
src/js/templates.js
File diff suppressed because it is too large
Load Diff
|
@ -211,6 +211,22 @@ input[type=text] {
|
|||
color: white;
|
||||
}
|
||||
|
||||
.profile:hover {
|
||||
background-color: #616161;
|
||||
}
|
||||
|
||||
.profileEditSelected {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
.profileSelectSettings {
|
||||
background-color: #9E9E9E;
|
||||
}
|
||||
|
||||
.profileEditPadding:hover {
|
||||
background-color: #616161;
|
||||
}
|
||||
|
||||
#main {
|
||||
color: #EEEEEE;
|
||||
}
|
||||
|
@ -291,3 +307,12 @@ input[type=text] {
|
|||
#miniPL {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
#profileSelect {
|
||||
background-color: #424242;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#profileSelectHeader span:hover {
|
||||
background-color: #616161;
|
||||
}
|
||||
|
|
|
@ -180,6 +180,22 @@ body {
|
|||
color: black;
|
||||
}
|
||||
|
||||
.profile:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.profileEditSelected {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
.profileSelectSettings {
|
||||
background-color: #9E9E9E;
|
||||
}
|
||||
|
||||
.profileEditPadding:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
#subscriptions img {
|
||||
border: 0px solid #000000;
|
||||
}
|
||||
|
@ -229,3 +245,11 @@ body {
|
|||
#miniPL {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#profileSelect {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#profileSelectHeader span:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
|
|
@ -43,20 +43,20 @@ a {
|
|||
}
|
||||
|
||||
.link {
|
||||
color: #2196F3;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-decoration-line: 'underline';
|
||||
color: #2196F3;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-decoration-line: 'underline';
|
||||
}
|
||||
|
||||
#progressBar{
|
||||
height: 3px;
|
||||
background-color: #f44336;
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
#progressBar {
|
||||
height: 3px;
|
||||
background-color: #f44336;
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.center {
|
||||
|
@ -86,7 +86,7 @@ a {
|
|||
font-size: 20px;
|
||||
margin-left: 20px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
#reloadButton {
|
||||
|
@ -101,30 +101,230 @@ a {
|
|||
font-size: 20px;
|
||||
margin-left: 20px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
#menuIcon {
|
||||
width: 25px;
|
||||
position: relative;
|
||||
top: 15px;
|
||||
right: 120px;
|
||||
float: right;
|
||||
left: 20px;
|
||||
bottom: 5px;
|
||||
}
|
||||
|
||||
#menuText {
|
||||
width: 100px;
|
||||
position: relative;
|
||||
top: 5px;
|
||||
left: 10px;
|
||||
top: 7px;
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
#currentProfile {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
cursor: pointer;
|
||||
border-radius: 200px 200px 200px 200px;
|
||||
-webkit-border-radius: 200px 200px 200px 200px;
|
||||
}
|
||||
|
||||
#currentInitial {
|
||||
font-size: 22px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
left: 13px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
#profileSelect {
|
||||
width: 275px;
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: 50px;
|
||||
-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);
|
||||
}
|
||||
|
||||
#profileSelectHeader {
|
||||
height: 55px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
line-height: 55px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#profileSelectHeader span {
|
||||
float: right;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 10px;
|
||||
margin-top: 5px;
|
||||
cursor: pointer;
|
||||
border-radius: 200px 200px 200px 200px;
|
||||
-webkit-border-radius: 200px 200px 200px 200px;
|
||||
-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;
|
||||
}
|
||||
|
||||
#profileSelectHeader span:hover {
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
#profileSelectHeader i {
|
||||
font-size: 15px;
|
||||
position: relative;
|
||||
left: 11px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
#profileSelectList {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
.profile {
|
||||
width: 265px;
|
||||
height: 30px;
|
||||
padding-top: 10px;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 10px;
|
||||
cursor: pointer;
|
||||
-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;
|
||||
}
|
||||
|
||||
.profile:hover {
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
.profileBackground {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
float: left;
|
||||
border-radius: 200px 200px 200px 200px;
|
||||
-webkit-border-radius: 200px 200px 200px 200px;
|
||||
}
|
||||
|
||||
.profileEditSelected {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
float: left;
|
||||
position: absolute;
|
||||
margin-left: -50px;
|
||||
opacity: 0.8;
|
||||
border-radius: 200px 200px 200px 200px;
|
||||
-webkit-border-radius: 200px 200px 200px 200px;
|
||||
}
|
||||
|
||||
.profileEditSelected i {
|
||||
font-size: 22px;
|
||||
position: relative;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
.profileInitial {
|
||||
font-size: 15px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
left: 10px;
|
||||
bottom: 16px;
|
||||
}
|
||||
|
||||
.profileName {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
bottom: 30px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.profileSelectSettings {
|
||||
margin: 0 auto;
|
||||
line-height: 55px;
|
||||
}
|
||||
|
||||
.profileSelectSettings i {
|
||||
position: relative;
|
||||
left: 15px;
|
||||
bottom: 2px;
|
||||
}
|
||||
|
||||
.colorPicker {
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 200px 200px 200px 200px;
|
||||
-webkit-border-radius: 200px 200px 200px 200px;
|
||||
}
|
||||
|
||||
.colorPicker span {
|
||||
position: relative;
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
.colorPickerPadding {
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.profileEdit {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-bottom: 5px;
|
||||
border-radius: 200px 200px 200px 200px;
|
||||
-webkit-border-radius: 200px 200px 200px 200px;
|
||||
}
|
||||
|
||||
.profileEditInitial {
|
||||
font-size: 25px;
|
||||
position: relative;
|
||||
top: 11px;
|
||||
}
|
||||
|
||||
.profileEditName {
|
||||
font-size: 13px;
|
||||
height: 60px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.profileEditPadding {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
height: 115px;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
-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;
|
||||
}
|
||||
|
||||
.profileEditPadding:hover {
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
.searchBar {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
right: -75px;
|
||||
top: 0;
|
||||
width: 800px;
|
||||
width: 750px;
|
||||
}
|
||||
|
||||
.searchBar input {
|
||||
|
@ -133,10 +333,10 @@ a {
|
|||
}
|
||||
|
||||
#searchFilter {
|
||||
width: 90%;
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
-webkit-box-shadow: 4px -2px 51px -6px rgba(0, 0, 0, 0.75);
|
||||
width: 90%;
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
-webkit-box-shadow: 4px -2px 51px -6px rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
|
||||
.searchButton {
|
||||
|
@ -145,18 +345,18 @@ a {
|
|||
}
|
||||
|
||||
.filterButton {
|
||||
text-decoration: none;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filter {
|
||||
width: 180px;
|
||||
height: 295px;
|
||||
padding: 10px;
|
||||
border-right: 1px solid #f44336;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
width: 180px;
|
||||
height: 295px;
|
||||
padding: 10px;
|
||||
border-right: 1px solid #f44336;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#sideNav {
|
||||
|
@ -241,14 +441,14 @@ a {
|
|||
}
|
||||
|
||||
#loading {
|
||||
width: 75%;
|
||||
height: 20%;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 5;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 75%;
|
||||
height: 20%;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 5;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.settingsInput {
|
||||
|
@ -257,27 +457,27 @@ a {
|
|||
}
|
||||
|
||||
.settingsSlider {
|
||||
padding: 30px;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
#confirmSettings {
|
||||
position: fixed;
|
||||
margin-left: 250px;
|
||||
margin-right: auto;
|
||||
left: 4%;
|
||||
right: 4%;
|
||||
bottom: 20px;
|
||||
height: 50px;
|
||||
background-color: #212121;
|
||||
color: #f5f5f5;
|
||||
padding: 10px;
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
-webkit-box-shadow: 4px -2px 51px -6px rgba(0, 0, 0, 0.75);
|
||||
-webkit-transition: opacity 0.4s ease-in-out;
|
||||
-moz-transition: opacity 0.4s ease-in-out;
|
||||
-ms-transition: opacity 0.4s ease-in-out;
|
||||
-o-transition: opacity 0.4s ease-in-out;
|
||||
position: fixed;
|
||||
margin-left: 250px;
|
||||
margin-right: auto;
|
||||
left: 4%;
|
||||
right: 4%;
|
||||
bottom: 20px;
|
||||
height: 50px;
|
||||
background-color: #212121;
|
||||
color: #f5f5f5;
|
||||
padding: 10px;
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
-webkit-box-shadow: 4px -2px 51px -6px rgba(0, 0, 0, 0.75);
|
||||
-webkit-transition: opacity 0.4s ease-in-out;
|
||||
-moz-transition: opacity 0.4s ease-in-out;
|
||||
-ms-transition: opacity 0.4s ease-in-out;
|
||||
-o-transition: opacity 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
.input-text-settings input {
|
||||
|
@ -315,14 +515,14 @@ a {
|
|||
}
|
||||
|
||||
.card {
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
margin-bottom: 30px;
|
||||
-webkit-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75);
|
||||
-moz-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75);
|
||||
box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75);
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
margin-bottom: 30px;
|
||||
-webkit-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75);
|
||||
-moz-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75);
|
||||
box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
|
||||
.help {
|
||||
|
@ -413,15 +613,15 @@ a {
|
|||
}
|
||||
|
||||
.blogFeed a {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 900px) {
|
||||
.searchBar {
|
||||
width: 500px;
|
||||
right: 80px;
|
||||
}
|
||||
.searchBar {
|
||||
width: 500px;
|
||||
right: -15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Thanks to Guus Lieben for the Material Design Switch */
|
||||
|
|
|
@ -28,14 +28,15 @@ iframe {
|
|||
.videoPlayer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
#player {
|
||||
min-width: 100%;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
#legacyPlayer {
|
||||
max-height: 80vh;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
.statistics {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<div>
|
||||
<div id='currentProfile' :style='{ backgroundColor: activeProfile.color }' onclick='profileSelectView.seen = !profileSelectView.seen'>
|
||||
<span id='currentInitial' :style='{ color: activeProfileInitialColor }'>{{activeProfileInitial}}</span>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,75 @@
|
|||
<div v-if='seen'>
|
||||
<div v-if='!isNewProfile' class='card'>
|
||||
<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>
|
||||
<br /><br /><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>
|
||||
<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-on:click='move' class='settingsButton'>
|
||||
MOVE SELECTED
|
||||
</div>
|
||||
<div v-on:click='copy' class='settingsButton'>
|
||||
COPY SELECTED
|
||||
</div>
|
||||
<div v-on:click='deleteChannel' style='color: #f44336' class='settingsButton'>
|
||||
DELETE SELECTED
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='card'>
|
||||
<h2 v-if='isNewProfile'>Add New Profile</h2>
|
||||
<h2 v-if='!isNewProfile'>Edit Profile Attributes</h2>
|
||||
<div class="input-text-settings">
|
||||
<input type="text" placeholder='Profile Name' name="set-name" v-model='newProfileName' />
|
||||
</div>
|
||||
<h3>Color Picker</h3>
|
||||
<div class='colorPickerPadding' v-for='(value, key) in colorPalette'>
|
||||
<div class='colorPicker' v-on:click='changeProfileColor(value)' :style='{ backgroundColor: value }' style='cursor: pointer;'></div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="input-text-settings">
|
||||
<input type="text" placeholder='HEX Color' name="set-name" v-model='newProfileColor' />
|
||||
</div>
|
||||
<br />
|
||||
<h3>New Profile Color</h3>
|
||||
<div class='colorPickerPadding'>
|
||||
<div class='colorPicker' :style='{ backgroundColor: newProfileColor }'></div>
|
||||
</div>
|
||||
<div class='center'>
|
||||
<div v-if='isNewProfile' v-on:click='updateProfile' class='settingsButton'>
|
||||
ADD PROFILE
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-on:click='updateProfile' class='settingsButton'>
|
||||
UPDATE PROFILE
|
||||
</div>
|
||||
<div v-on:click='defaultProfile' class='settingsButton'>
|
||||
MAKE DEFAULT PROFILE
|
||||
</div>
|
||||
<div v-on:click='deleteProfile' style='color: #f44336' class='settingsButton'>
|
||||
DELETE PROFILE
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,11 @@
|
|||
<div v-if='seen' id='profileSelect'>
|
||||
<h3 id='profileSelectHeader'>Profile Select<span v-on:click='showSubscriptionManager'><i class="fas fa-sliders-h"></i></span></h3>
|
||||
<div id='profileSelectList'>
|
||||
<div class='profile' v-on:click='setActiveProfile(index)' v-for='(profile, index) in profileList'>
|
||||
<div class='profileBackground' :style='{ backgroundColor: profile.color }'>
|
||||
<span class='profileInitial' :style='{ color: profileTextColor[index] }'>{{profileInitials[index]}}</span>
|
||||
</div>
|
||||
<p class='profileName'>{{profile.name}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -349,6 +349,9 @@
|
|||
<label class="select-label">Subscriptions Export Format</label>
|
||||
</div>
|
||||
<div class='center'>
|
||||
<div onclick='hideViews(); subscriptionManagerView.seen = true;' class='settingsButton'>
|
||||
MANAGE SUBSCRIPTIONS
|
||||
</div>
|
||||
<div onclick='importSubscriptions()' class='settingsButton'>
|
||||
IMPORT SUBSCRIPTIONS
|
||||
</div>
|
||||
|
@ -397,13 +400,13 @@
|
|||
<br />
|
||||
<br />
|
||||
<div class='center'>
|
||||
<div onclick='confirmFunction("Are you sure you want to delete your history?", clearFile, "history")' class='settingsButton'>
|
||||
<div onclick='confirmFunction("Are you sure you want to delete your history?", clearFile, "history")' style='color: #f44336' class='settingsButton'>
|
||||
CLEAR HISTORY
|
||||
</div>
|
||||
<div onclick='confirmFunction("Are you sure you want to remove all saved videos?", clearFile, "saved")' class='settingsButton'>
|
||||
<div onclick='confirmFunction("Are you sure you want to remove all saved videos?", clearFile, "saved")' style='color: #f44336' class='settingsButton'>
|
||||
CLEAR FAVORITED VIDEOS
|
||||
</div>
|
||||
<div onclick='confirmFunction("Are you sure you want to remove all subscriptions?", clearFile, "subscriptions")' class='settingsButton'>
|
||||
<div onclick='confirmFunction("Are you sure you want to remove all subscriptions?", clearFile, "subscriptions")' style='color: #f44336' class='settingsButton'>
|
||||
CLEAR SUBSCRIPTIONS
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<div v-if='seen'>
|
||||
<div class='card'>
|
||||
<h2>Subscription / Profile Manager</h2>
|
||||
<br />
|
||||
<div class='profileEditPadding' v-for='(profile, index) in profileList' v-on:click='editProfile(false, index)'>
|
||||
<div class='profileEdit' :style='{ backgroundColor: profile.color }' style='cursor: pointer;'>
|
||||
<span class='profileEditInitial' :style='{ color: profileTextColor[index] }'>{{profileInitials[index]}}</span>
|
||||
</div>
|
||||
<div class='profileEditName'><span>{{profile.name}}</span></div>
|
||||
</div>
|
||||
<div class='profileEditPadding' v-on:click='editProfile(true, -1)'>
|
||||
<div class='profileEdit' style='background-color: #9E9E9E; cursor: pointer;'>
|
||||
<i class='profileEditInitial fas fa-plus' style='color: #000000; top: 14px;'></i>
|
||||
</div>
|
||||
<div class='profileEditName'><span>Add New Profile</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue