handled invalid values in storage

partial rewrite notifications.js
innerText to textContent
fixed bug with clamping
pull/3084/head
meow 3 years ago
parent 319bbd2f81
commit b72b917af2

@ -39,6 +39,7 @@ if (!window.hasOwnProperty('HTMLDetailsElement') && !window.hasOwnProperty('mock
} }
// Monstrous global variable for handy code // Monstrous global variable for handy code
// Includes: clamp, xhr, storage.{get,set,remove}
window.helpers = window.helpers || { window.helpers = window.helpers || {
/** /**
* https://en.wikipedia.org/wiki/Clamping_(graphics) * https://en.wikipedia.org/wiki/Clamping_(graphics)
@ -164,19 +165,20 @@ window.helpers = window.helpers || {
}, options.retry_timeout); }, options.retry_timeout);
}; };
// Pack retry() call into error handlers
callbacks._onError = callbacks.onError; callbacks._onError = callbacks.onError;
callbacks.onError = function (xhr) { callbacks.onError = function (xhr) {
if (callbacks._onError) if (callbacks._onError)
callbacks._onError(); callbacks._onError(xhr);
retry(); retry();
}; };
callbacks._onTimeout = callbacks.onTimeout; callbacks._onTimeout = callbacks.onTimeout;
callbacks.onTimeout = function (xhr) { callbacks.onTimeout = function (xhr) {
if (callbacks._onTimeout) if (callbacks._onTimeout)
callbacks._onTimeout(); callbacks._onTimeout(xhr);
retry(); retry();
}; };
helpers._xhrRetry(method, url, options, callbacks); helpers._xhrRetry(method, url, options, callbacks);
}, },
@ -198,13 +200,22 @@ window.helpers = window.helpers || {
if (localStorageIsUsable) { if (localStorageIsUsable) {
return { return {
get: function (key) { if (localStorage[key]) return JSON.parse(decodeURIComponent(localStorage[key])); }, get: function (key) {
if (!localStorage[key]) return;
try {
return JSON.parse(decodeURIComponent(localStorage[key]));
} catch(e) {
// Erase non parsable value
helpers.storage.remove(key);
}
},
set: function (key, value) { localStorage[key] = encodeURIComponent(JSON.stringify(value)); }, set: function (key, value) { localStorage[key] = encodeURIComponent(JSON.stringify(value)); },
remove: function (key) { localStorage.removeItem(key); } remove: function (key) { localStorage.removeItem(key); }
}; };
} }
console.info('Storage: localStorage is disabled or unaccessible trying cookies'); // TODO: fire 'storage' event for cookies
console.info('Storage: localStorage is disabled or unaccessible. Cookies used as fallback');
return { return {
get: function (key) { get: function (key) {
const cookiePrefix = key + '='; const cookiePrefix = key + '=';
@ -213,7 +224,12 @@ window.helpers = window.helpers || {
if (matchedCookie) { if (matchedCookie) {
const cookieBody = matchedCookie.replace(cookiePrefix, ''); const cookieBody = matchedCookie.replace(cookiePrefix, '');
if (cookieBody.length === 0) return; if (cookieBody.length === 0) return;
try {
return JSON.parse(decodeURIComponent(cookieBody)); return JSON.parse(decodeURIComponent(cookieBody));
} catch(e) {
// Erase non parsable value
helpers.storage.remove(key);
}
} }
}, },
set: function (key, value) { set: function (key, value) {

@ -62,7 +62,7 @@ function get_youtube_replies(target, load_more) {
a.onclick = hide_youtube_replies; a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', community_data.hide_replies_text); a.setAttribute('data-sub-text', community_data.hide_replies_text);
a.setAttribute('data-inner-text', community_data.show_replies_text); a.setAttribute('data-inner-text', community_data.show_replies_text);
a.innerText = community_data.hide_replies_text; a.textContent = community_data.hide_replies_text;
var div = document.createElement('div'); var div = document.createElement('div');
div.innerHTML = response.contentHtml; div.innerHTML = response.contentHtml;

@ -78,7 +78,7 @@
document.querySelectorAll('[data-onrange="update_volume_value"]').forEach(function (el) { document.querySelectorAll('[data-onrange="update_volume_value"]').forEach(function (el) {
function update_volume_value() { function update_volume_value() {
document.getElementById('volume-value').innerText = el.value; document.getElementById('volume-value').textContent = el.value;
} }
el.oninput = update_volume_value; el.oninput = update_volume_value;
el.onchange = update_volume_value; el.onchange = update_volume_value;
@ -89,7 +89,7 @@
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode; var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
row.style.display = 'none'; row.style.display = 'none';
var count = document.getElementById('count'); var count = document.getElementById('count');
count.innerText = parseInt(count.innerText) - 1; count.textContent--;
var url = '/token_ajax?action_revoke_token=1&redirect=false' + var url = '/token_ajax?action_revoke_token=1&redirect=false' +
'&referer=' + encodeURIComponent(location.href) + '&referer=' + encodeURIComponent(location.href) +
@ -99,7 +99,7 @@
helpers.xhr('POST', url, {payload: payload}, { helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) { onNon200: function (xhr) {
count.innerText = parseInt(count.innerText) + 1; count.textContent++;
row.style.display = ''; row.style.display = '';
} }
}); });
@ -109,7 +109,7 @@
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode; var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
row.style.display = 'none'; row.style.display = 'none';
var count = document.getElementById('count'); var count = document.getElementById('count');
count.innerText = parseInt(count.innerText) - 1; count.textContent--;
var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' + var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
'&referer=' + encodeURIComponent(location.href) + '&referer=' + encodeURIComponent(location.href) +
@ -119,7 +119,7 @@
helpers.xhr('POST', url, {payload: payload}, { helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) { onNon200: function (xhr) {
count.innerText = parseInt(count.innerText) + 1; count.textContent++;
row.style.display = ''; row.style.display = '';
} }
}); });

@ -1,8 +1,13 @@
'use strict'; 'use strict';
var notification_data = JSON.parse(document.getElementById('notification_data').textContent); var notification_data = JSON.parse(document.getElementById('notification_data').textContent);
/** Boolean meaning 'some tab have stream' */
const STORAGE_KEY_STREAM = 'stream';
/** Number of notifications. May be increased or reset */
const STORAGE_KEY_NOTIF_COUNT = 'notification_count';
var notifications, delivered; var notifications, delivered;
var notifications_substitution = { close: function () { } }; var notifications_mock = { close: function () { } };
function get_subscriptions() { function get_subscriptions() {
helpers.xhr('GET', '/api/v1/auth/subscriptions?fields=authorId', { helpers.xhr('GET', '/api/v1/auth/subscriptions?fields=authorId', {
@ -32,92 +37,96 @@ function create_notification_stream(subscriptions) {
var notification = JSON.parse(event.data); var notification = JSON.parse(event.data);
console.info('Got notification:', notification); console.info('Got notification:', notification);
if (start_time < notification.published && !delivered.includes(notification.videoId)) { // Ignore not actual and delivered notifications
if (Notification.permission === 'granted') { if (start_time > notification.published || delivered.includes(notification.videoId)) return;
var system_notification =
new Notification((notification.liveNow ? notification_data.live_now_text : notification_data.upload_text).replace('`x`', notification.author), { delivered.push(notification.videoId);
let notification_count = helpers.storage.get(STORAGE_KEY_NOTIF_COUNT) || 0;
notification_count++;
helpers.storage.set(STORAGE_KEY_NOTIF_COUNT, notification_count);
update_ticker_count();
// TODO: ask permission to show notifications via Notification.requestPermission
// https://developer.mozilla.org/en-US/docs/Web/API/notification
if (window.Notification && Notification.permission === 'granted') {
var notification_text = notification.liveNow ? notification_data.live_now_text : notification_data.upload_text;
notification_text = notification_text.replace('`x`', notification.author);
var system_notification = new Notification(notification_text, {
body: notification.title, body: notification.title,
icon: '/ggpht' + new URL(notification.authorThumbnails[2].url).pathname, icon: '/ggpht' + new URL(notification.authorThumbnails[2].url).pathname,
img: '/ggpht' + new URL(notification.authorThumbnails[4].url).pathname, img: '/ggpht' + new URL(notification.authorThumbnails[4].url).pathname
tag: notification.videoId
}); });
system_notification.onclick = function (event) { system_notification.onclick = function (e) {
open('/watch?v=' + event.currentTarget.tag, '_blank'); open('/watch?v=' + notification.videoId, '_blank');
}; };
} }
};
delivered.push(notification.videoId); notifications.addEventListener('error', function (e) {
helpers.storage.set('notification_count', (helpers.storage.get('notification_count') || 0) + 1); console.warn('Something went wrong with notifications, trying to reconnect...');
notifications = notifications_mock;
setTimeout(get_subscriptions, 1000);
});
notifications.stream();
}
function update_ticker_count() {
var notification_ticker = document.getElementById('notification_ticker'); var notification_ticker = document.getElementById('notification_ticker');
if (parseInt(helpers.storage.get('notification_count')) > 0) { const notification_count = helpers.storage.get(STORAGE_KEY_STREAM);
if (notification_count > 0) {
notification_ticker.innerHTML = notification_ticker.innerHTML =
'<span id="notification_count">' + helpers.storage.get('notification_count') + '</span> <i class="icon ion-ios-notifications"></i>'; '<span id="notification_count">' + notification_count + '</span> <i class="icon ion-ios-notifications"></i>';
} else { } else {
notification_ticker.innerHTML = notification_ticker.innerHTML =
'<i class="icon ion-ios-notifications-outline"></i>'; '<i class="icon ion-ios-notifications-outline"></i>';
} }
} }
};
notifications.addEventListener('error', handle_notification_error);
notifications.stream();
}
function handle_notification_error(event) {
console.warn('Something went wrong with notifications, trying to reconnect...');
notifications = notifications_substitution;
setTimeout(get_subscriptions, 1000);
}
addEventListener('load', function (e) {
var notification_count = document.getElementById('notification_count');
if (notification_count) {
helpers.storage.set('notification_count', parseInt(notification_count.innerText));
} else {
helpers.storage.set('notification_count', 0);
}
if (helpers.storage.get('stream')) { function start_stream_if_needed() {
helpers.storage.remove('stream'); // random wait for other tabs set 'stream' flag
} else {
setTimeout(function () { setTimeout(function () {
if (!helpers.storage.get('stream')) { if (!helpers.storage.get(STORAGE_KEY_STREAM)) {
notifications = notifications_substitution; // if no one set 'stream', set it by yourself and start stream
helpers.storage.set('stream', true); helpers.storage.set(STORAGE_KEY_STREAM, true);
notifications = notifications_mock;
get_subscriptions(); get_subscriptions();
} }
}, Math.random() * 1000 + 50); }, Math.random() * 1000 + 50); // [0.050 .. 1.050) second
} }
addEventListener('storage', function (e) { addEventListener('storage', function (e) {
if (e.key === 'stream' && !e.newValue) { if (e.key === STORAGE_KEY_NOTIF_COUNT)
if (notifications) { update_ticker_count();
helpers.storage.set('stream', true);
} else {
setTimeout(function () {
if (!helpers.storage.get('stream')) {
notifications = notifications_substitution;
helpers.storage.set('stream', true);
get_subscriptions();
}
}, Math.random() * 1000 + 50);
}
} else if (e.key === 'notification_count') {
var notification_ticker = document.getElementById('notification_ticker');
if (parseInt(e.newValue) > 0) { // if 'stream' key was removed
notification_ticker.innerHTML = if (e.key === STORAGE_KEY_STREAM && !helpers.storage.get(STORAGE_KEY_STREAM)) {
'<span id="notification_count">' + e.newValue + '</span> <i class="icon ion-ios-notifications"></i>'; if (notifications) {
// restore it if we have active stream
helpers.storage.set(STORAGE_KEY_STREAM, true);
} else { } else {
notification_ticker.innerHTML = start_stream_if_needed();
'<i class="icon ion-ios-notifications-outline"></i>';
} }
} }
}); });
addEventListener('load', function () {
var notification_count_el = document.getElementById('notification_count');
var notification_count = notification_count_el ? parseInt(notification_count_el.textContent) : 0;
helpers.storage.set(STORAGE_KEY_NOTIF_COUNT, notification_count);
if (helpers.storage.get(STORAGE_KEY_STREAM))
helpers.storage.remove(STORAGE_KEY_STREAM);
start_stream_if_needed();
}); });
addEventListener('unload', function (e) { addEventListener('unload', function () {
if (notifications) helpers.storage.remove('stream'); // let chance to other tabs to be a streamer via firing 'storage' event
if (notifications) helpers.storage.remove(STORAGE_KEY_STREAM);
}); });

@ -43,9 +43,10 @@ var save_player_pos_key = 'save_player_pos';
videojs.Vhs.xhr.beforeRequest = function(options) { videojs.Vhs.xhr.beforeRequest = function(options) {
// set local if requested not videoplayback // set local if requested not videoplayback
if (!options.uri.includes('videoplayback')) if (!options.uri.includes('videoplayback')) {
if (!options.uri.includes('local=true')) if (!options.uri.includes('local=true'))
options.uri += '?local=true'; options.uri += '?local=true';
}
return options; return options;
}; };
@ -346,7 +347,7 @@ if (!video_data.params.listen && video_data.params.quality === 'dash') {
targetQualityLevel = 0; targetQualityLevel = 0;
break; break;
default: default:
const targetHeight = parseInt(video_data.params.quality_dash, 10); const targetHeight = parseInt(video_data.params.quality_dash);
for (let i = 0; i < qualityLevels.length; i++) { for (let i = 0; i < qualityLevels.length; i++) {
if (qualityLevels[i].height <= targetHeight) if (qualityLevels[i].height <= targetHeight)
targetQualityLevel = i; targetQualityLevel = i;
@ -411,8 +412,8 @@ if (!video_data.params.listen && video_data.params.annotations) {
function change_volume(delta) { function change_volume(delta) {
const curVolume = player.volume(); const curVolume = player.volume();
const newVolume = curVolume + delta; let newVolume = curVolume + delta;
helpers.clamp(newVolume, 0, 1); newVolume = helpers.clamp(newVolume, 0, 1);
player.volume(newVolume); player.volume(newVolume);
} }
@ -423,8 +424,8 @@ function toggle_muted() {
function skip_seconds(delta) { function skip_seconds(delta) {
const duration = player.duration(); const duration = player.duration();
const curTime = player.currentTime(); const curTime = player.currentTime();
const newTime = curTime + delta; let newTime = curTime + delta;
helpers.clamp(newTime, 0, duration); newTime = helpers.clamp(newTime, 0, duration);
player.currentTime(newTime); player.currentTime(newTime);
} }
@ -434,20 +435,13 @@ function set_seconds_after_start(delta) {
} }
function save_video_time(seconds) { function save_video_time(seconds) {
const videoId = video_data.id;
const all_video_times = get_all_video_times(); const all_video_times = get_all_video_times();
all_video_times[video_data.id] = seconds;
all_video_times[videoId] = seconds;
helpers.storage.set(save_player_pos_key, all_video_times); helpers.storage.set(save_player_pos_key, all_video_times);
} }
function get_video_time() { function get_video_time() {
const videoId = video_data.id; return get_all_video_times()[video_data.id] || 0;
const all_video_times = get_all_video_times();
const timestamp = all_video_times[videoId];
return timestamp || 0;
} }
function get_all_video_times() { function get_all_video_times() {
@ -534,8 +528,8 @@ function toggle_fullscreen() {
function increase_playback_rate(steps) { function increase_playback_rate(steps) {
const maxIndex = options.playbackRates.length - 1; const maxIndex = options.playbackRates.length - 1;
const curIndex = options.playbackRates.indexOf(player.playbackRate()); const curIndex = options.playbackRates.indexOf(player.playbackRate());
const newIndex = curIndex + steps; let newIndex = curIndex + steps;
helpers.clamp(newIndex, 0, maxIndex); newIndex = helpers.clamp(newIndex, 0, maxIndex);
player.playbackRate(options.playbackRates[newIndex]); player.playbackRate(options.playbackRates[newIndex]);
} }

@ -12,7 +12,7 @@ function add_playlist_video(target) {
helpers.xhr('POST', url, {payload: payload}, { helpers.xhr('POST', url, {payload: payload}, {
on200: function (response) { on200: function (response) {
option.innerText = '✓' + option.innerText; option.textContent = '✓' + option.textContent;
} }
}); });
} }

@ -294,7 +294,7 @@ function get_youtube_replies(target, load_more, load_replies) {
a.onclick = hide_youtube_replies; a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', video_data.hide_replies_text); a.setAttribute('data-sub-text', video_data.hide_replies_text);
a.setAttribute('data-inner-text', video_data.show_replies_text); a.setAttribute('data-inner-text', video_data.show_replies_text);
a.innerText = video_data.hide_replies_text; a.textContent = video_data.hide_replies_text;
var div = document.createElement('div'); var div = document.createElement('div');
div.innerHTML = response.contentHtml; div.innerHTML = response.contentHtml;

@ -20,14 +20,14 @@ function mark_unwatched(target) {
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode; var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
tile.style.display = 'none'; tile.style.display = 'none';
var count = document.getElementById('count'); var count = document.getElementById('count');
count.innerText = parseInt(count.innerText) - 1; count.textContent--;
var url = '/watch_ajax?action_mark_unwatched=1&redirect=false' + var url = '/watch_ajax?action_mark_unwatched=1&redirect=false' +
'&id=' + target.getAttribute('data-id'); '&id=' + target.getAttribute('data-id');
helpers.xhr('POST', url, {payload: payload}, { helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) { onNon200: function (xhr) {
count.innerText = parseInt(count.innerText) + 1; count.textContent++;
tile.style.display = ''; tile.style.display = '';
} }
}); });

Loading…
Cancel
Save