handled invalid values in storage

partial rewrite notifications.js
innerText to textContent
fixed bug with clamping
This commit is contained in:
meow 2022-05-21 13:35:41 +03:00
parent 319bbd2f81
commit b72b917af2
8 changed files with 128 additions and 109 deletions

View File

@ -39,6 +39,7 @@ if (!window.hasOwnProperty('HTMLDetailsElement') && !window.hasOwnProperty('mock
}
// Monstrous global variable for handy code
// Includes: clamp, xhr, storage.{get,set,remove}
window.helpers = window.helpers || {
/**
* https://en.wikipedia.org/wiki/Clamping_(graphics)
@ -164,19 +165,20 @@ window.helpers = window.helpers || {
}, options.retry_timeout);
};
// Pack retry() call into error handlers
callbacks._onError = callbacks.onError;
callbacks.onError = function (xhr) {
if (callbacks._onError)
callbacks._onError();
callbacks._onError(xhr);
retry();
};
callbacks._onTimeout = callbacks.onTimeout;
callbacks.onTimeout = function (xhr) {
if (callbacks._onTimeout)
callbacks._onTimeout();
callbacks._onTimeout(xhr);
retry();
};
helpers._xhrRetry(method, url, options, callbacks);
},
@ -198,13 +200,22 @@ window.helpers = window.helpers || {
if (localStorageIsUsable) {
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)); },
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 {
get: function (key) {
const cookiePrefix = key + '=';
@ -213,7 +224,12 @@ window.helpers = window.helpers || {
if (matchedCookie) {
const cookieBody = matchedCookie.replace(cookiePrefix, '');
if (cookieBody.length === 0) return;
return JSON.parse(decodeURIComponent(cookieBody));
try {
return JSON.parse(decodeURIComponent(cookieBody));
} catch(e) {
// Erase non parsable value
helpers.storage.remove(key);
}
}
},
set: function (key, value) {

View File

@ -62,7 +62,7 @@ function get_youtube_replies(target, load_more) {
a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', community_data.hide_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');
div.innerHTML = response.contentHtml;

View File

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

View File

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

View File

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

View File

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

View File

@ -294,7 +294,7 @@ function get_youtube_replies(target, load_more, load_replies) {
a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', video_data.hide_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');
div.innerHTML = response.contentHtml;

View File

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