From a6a0bbf39834003b9ee26392e626828c05209010 Mon Sep 17 00:00:00 2001 From: bbielsa Date: Mon, 25 Oct 2021 19:50:17 -0400 Subject: [PATCH 1/8] Add remember_position field to the Preferences and VideoPreferences structs, and add a checkbox in the preferences page to toggle it --- src/invidious/config.cr | 1 + src/invidious/routes/preferences.cr | 5 +++++ src/invidious/user/preferences.cr | 1 + src/invidious/videos.cr | 6 ++++++ src/invidious/views/preferences.ecr | 5 +++++ 5 files changed, 18 insertions(+) diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 578e31fd..bdd670f1 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -42,6 +42,7 @@ struct ConfigPreferences property volume : Int32 = 100 property vr_mode : Bool = true property show_nick : Bool = true + property remember_position : Bool = false def to_tuple {% begin %} diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index edf9e1e7..3bf7e5da 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -70,6 +70,10 @@ module Invidious::Routes::PreferencesRoute vr_mode ||= "off" vr_mode = vr_mode == "on" + remember_position = env.params.body["remember_position"]?.try &.as(String) + remember_position ||= "off" + remember_position = remember_position == "on" + show_nick = env.params.body["show_nick"]?.try &.as(String) show_nick ||= "off" show_nick = show_nick == "on" @@ -165,6 +169,7 @@ module Invidious::Routes::PreferencesRoute extend_desc: extend_desc, vr_mode: vr_mode, show_nick: show_nick, + remember_position: remember_position, }.to_json).to_json if user = env.get? "user" diff --git a/src/invidious/user/preferences.cr b/src/invidious/user/preferences.cr index c15876f5..f2d089b4 100644 --- a/src/invidious/user/preferences.cr +++ b/src/invidious/user/preferences.cr @@ -53,6 +53,7 @@ struct Preferences property video_loop : Bool = CONFIG.default_user_preferences.video_loop property extend_desc : Bool = CONFIG.default_user_preferences.extend_desc property volume : Int32 = CONFIG.default_user_preferences.volume + property remember_position : Bool = CONFIG.default_user_preferences.remember_position module BoolToString def self.to_json(value : String, json : JSON::Builder) diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index 621ff386..bffd564d 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -246,6 +246,7 @@ struct VideoPreferences property video_start : Float64 | Int32 property volume : Int32 property vr_mode : Bool + property remember_position : Bool end struct Video @@ -1090,6 +1091,7 @@ def process_video_params(query, preferences) extend_desc = query["extend_desc"]?.try { |q| (q == "true" || q == "1").to_unsafe } volume = query["volume"]?.try &.to_i? vr_mode = query["vr_mode"]?.try { |q| (q == "true" || q == "1").to_unsafe } + remember_position = query["remember_position"]?.try { |q| (q == "true" || q == "1").to_unsafe } if preferences # region ||= preferences.region @@ -1110,6 +1112,7 @@ def process_video_params(query, preferences) extend_desc ||= preferences.extend_desc.to_unsafe volume ||= preferences.volume vr_mode ||= preferences.vr_mode.to_unsafe + remember_position ||= preferences.remember_position.to_unsafe end annotations ||= CONFIG.default_user_preferences.annotations.to_unsafe @@ -1129,6 +1132,7 @@ def process_video_params(query, preferences) extend_desc ||= CONFIG.default_user_preferences.extend_desc.to_unsafe volume ||= CONFIG.default_user_preferences.volume vr_mode ||= CONFIG.default_user_preferences.vr_mode.to_unsafe + remember_position ||= CONFIG.default_user_preferences.remember_position.to_unsafe annotations = annotations == 1 autoplay = autoplay == 1 @@ -1140,6 +1144,7 @@ def process_video_params(query, preferences) video_loop = video_loop == 1 extend_desc = extend_desc == 1 vr_mode = vr_mode == 1 + remember_position = remember_position == 1 if CONFIG.disabled?("dash") && quality == "dash" quality = "high" @@ -1190,6 +1195,7 @@ def process_video_params(query, preferences) video_start: video_start, volume: volume, vr_mode: vr_mode, + remember_position: remember_position, }) return params diff --git a/src/invidious/views/preferences.ecr b/src/invidious/views/preferences.ecr index 6bd9e348..603c337b 100644 --- a/src/invidious/views/preferences.ecr +++ b/src/invidious/views/preferences.ecr @@ -116,6 +116,11 @@ checked<% end %>> +
+ + checked<% end %>> +
+ <%= translate(locale, "preferences_category_visual") %>
From 2a45b4eba031cc59551150a7e674e5b5943ab490 Mon Sep 17 00:00:00 2001 From: bbielsa Date: Mon, 25 Oct 2021 20:59:36 -0400 Subject: [PATCH 2/8] Save and load the position for the video using a local storage object, the object is a dictionary, where the key is the video ID, and the value is the time at which the user last left off watching the video. If the user deselected the 'remember video position' checkbox in the preferences this dictionary is cleared --- assets/js/player.js | 72 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/assets/js/player.js b/assets/js/player.js index a461c53d..4c12f1fe 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -38,6 +38,8 @@ embed_url.searchParams.delete('v'); short_url = location.origin + '/' + video_data.id + embed_url.search; embed_url = location.origin + '/embed/' + video_data.id + embed_url.search; +var remember_position_key = "remember_position"; + var shareOptions = { socials: ['fbFeed', 'tw', 'reddit', 'email'], @@ -199,6 +201,27 @@ if (video_data.premiere_timestamp && Math.round(new Date() / 1000) < video_data. player.getChild('bigPlayButton').hide(); } +if (video_data.params.remember_position) { + const remeberedTime = get_video_time(); + let lastUpdated = 0; + + set_seconds_after_start(remeberedTime); + + player.on("timeupdate", e => { + const raw = player.currentTime(); + const time = Math.floor(raw); + + if(lastUpdated !== time) { + save_video_time(time); + lastUpdated = time; + } + }); +} +else { + console.log("Removing data for remebered positions"); + remove_all_video_times(); +} + if (video_data.params.autoplay) { var bpb = player.getChild('bigPlayButton'); bpb.hide(); @@ -330,6 +353,55 @@ function skip_seconds(delta) { player.currentTime(newTime); } +function set_seconds_after_start(delta) { + const start = video_data.params.video_start; + player.currentTime(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; + + set_all_video_times(all_video_times); +} + +function get_video_time() { + try { + const videoId = video_data.id; + const all_video_times = get_all_video_times(); + const timestamp = all_video_times[videoId]; + + return timestamp; + } + catch { + return 0; + } +} + +function set_all_video_times(times) { + const json = JSON.stringify(times); + + localStorage.setItem(remember_position_key, json); +} + +function get_all_video_times() { + try { + const raw = localStorage.getItem(remember_position_key); + const times = JSON.parse(raw); + + return times || {}; + } + catch { + return {}; + } +} + +function remove_all_video_times() { + localStorage.removeItem(remember_position_key); +} + function set_time_percent(percent) { const duration = player.duration(); const newTime = duration * (percent / 100); From 1261323c66e4c4886e4620e4e1eaaa7de3b2403e Mon Sep 17 00:00:00 2001 From: bbielsa Date: Tue, 26 Oct 2021 17:30:59 -0400 Subject: [PATCH 3/8] Remove console.log debugging --- assets/js/player.js | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/js/player.js b/assets/js/player.js index 4c12f1fe..ed9c62ee 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -218,7 +218,6 @@ if (video_data.params.remember_position) { }); } else { - console.log("Removing data for remebered positions"); remove_all_video_times(); } From b6792cf02e79b2376ffae13fae6dc225095469bf Mon Sep 17 00:00:00 2001 From: bbielsa Date: Tue, 26 Oct 2021 18:43:28 -0400 Subject: [PATCH 4/8] Added default value for get_video_time() which was causing a bug in safari --- assets/js/player.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/assets/js/player.js b/assets/js/player.js index ed9c62ee..2a0c6fd7 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -207,7 +207,7 @@ if (video_data.params.remember_position) { set_seconds_after_start(remeberedTime); - player.on("timeupdate", e => { + const updateTime = () => { const raw = player.currentTime(); const time = Math.floor(raw); @@ -215,7 +215,9 @@ if (video_data.params.remember_position) { save_video_time(time); lastUpdated = time; } - }); + }; + + player.on("timeupdate", updateTime); } else { remove_all_video_times(); @@ -372,7 +374,7 @@ function get_video_time() { const all_video_times = get_all_video_times(); const timestamp = all_video_times[videoId]; - return timestamp; + return timestamp || 0; } catch { return 0; From 5abe7fe12377096c5b63bc787ccdbb11b8cf78a9 Mon Sep 17 00:00:00 2001 From: bbielsa Date: Tue, 26 Oct 2021 19:25:29 -0400 Subject: [PATCH 5/8] Rename 'remember_position' to 'save_player_pos' for clarity --- assets/js/player.js | 10 +++++----- src/invidious/config.cr | 2 +- src/invidious/routes/preferences.cr | 8 ++++---- src/invidious/user/preferences.cr | 2 +- src/invidious/videos.cr | 12 ++++++------ src/invidious/views/preferences.ecr | 4 ++-- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/assets/js/player.js b/assets/js/player.js index 2a0c6fd7..b4973482 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -38,7 +38,7 @@ embed_url.searchParams.delete('v'); short_url = location.origin + '/' + video_data.id + embed_url.search; embed_url = location.origin + '/embed/' + video_data.id + embed_url.search; -var remember_position_key = "remember_position"; +var save_player_pos_key = "save_player_pos"; var shareOptions = { socials: ['fbFeed', 'tw', 'reddit', 'email'], @@ -201,7 +201,7 @@ if (video_data.premiere_timestamp && Math.round(new Date() / 1000) < video_data. player.getChild('bigPlayButton').hide(); } -if (video_data.params.remember_position) { +if (video_data.params.save_player_pos) { const remeberedTime = get_video_time(); let lastUpdated = 0; @@ -384,12 +384,12 @@ function get_video_time() { function set_all_video_times(times) { const json = JSON.stringify(times); - localStorage.setItem(remember_position_key, json); + localStorage.setItem(save_player_pos_key, json); } function get_all_video_times() { try { - const raw = localStorage.getItem(remember_position_key); + const raw = localStorage.getItem(save_player_pos_key); const times = JSON.parse(raw); return times || {}; @@ -400,7 +400,7 @@ function get_all_video_times() { } function remove_all_video_times() { - localStorage.removeItem(remember_position_key); + localStorage.removeItem(save_player_pos_key); } function set_time_percent(percent) { diff --git a/src/invidious/config.cr b/src/invidious/config.cr index bdd670f1..c4a8bf83 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -42,7 +42,7 @@ struct ConfigPreferences property volume : Int32 = 100 property vr_mode : Bool = true property show_nick : Bool = true - property remember_position : Bool = false + property save_player_pos : Bool = false def to_tuple {% begin %} diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 3bf7e5da..a07584c8 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -70,9 +70,9 @@ module Invidious::Routes::PreferencesRoute vr_mode ||= "off" vr_mode = vr_mode == "on" - remember_position = env.params.body["remember_position"]?.try &.as(String) - remember_position ||= "off" - remember_position = remember_position == "on" + save_player_pos = env.params.body["save_player_pos"]?.try &.as(String) + save_player_pos ||= "off" + save_player_pos = save_player_pos == "on" show_nick = env.params.body["show_nick"]?.try &.as(String) show_nick ||= "off" @@ -169,7 +169,7 @@ module Invidious::Routes::PreferencesRoute extend_desc: extend_desc, vr_mode: vr_mode, show_nick: show_nick, - remember_position: remember_position, + save_player_pos: save_player_pos, }.to_json).to_json if user = env.get? "user" diff --git a/src/invidious/user/preferences.cr b/src/invidious/user/preferences.cr index f2d089b4..bf7ea401 100644 --- a/src/invidious/user/preferences.cr +++ b/src/invidious/user/preferences.cr @@ -53,7 +53,7 @@ struct Preferences property video_loop : Bool = CONFIG.default_user_preferences.video_loop property extend_desc : Bool = CONFIG.default_user_preferences.extend_desc property volume : Int32 = CONFIG.default_user_preferences.volume - property remember_position : Bool = CONFIG.default_user_preferences.remember_position + property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos module BoolToString def self.to_json(value : String, json : JSON::Builder) diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index bffd564d..9b4b54e8 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -246,7 +246,7 @@ struct VideoPreferences property video_start : Float64 | Int32 property volume : Int32 property vr_mode : Bool - property remember_position : Bool + property save_player_pos : Bool end struct Video @@ -1091,7 +1091,7 @@ def process_video_params(query, preferences) extend_desc = query["extend_desc"]?.try { |q| (q == "true" || q == "1").to_unsafe } volume = query["volume"]?.try &.to_i? vr_mode = query["vr_mode"]?.try { |q| (q == "true" || q == "1").to_unsafe } - remember_position = query["remember_position"]?.try { |q| (q == "true" || q == "1").to_unsafe } + save_player_pos = query["save_player_pos"]?.try { |q| (q == "true" || q == "1").to_unsafe } if preferences # region ||= preferences.region @@ -1112,7 +1112,7 @@ def process_video_params(query, preferences) extend_desc ||= preferences.extend_desc.to_unsafe volume ||= preferences.volume vr_mode ||= preferences.vr_mode.to_unsafe - remember_position ||= preferences.remember_position.to_unsafe + save_player_pos ||= preferences.save_player_pos.to_unsafe end annotations ||= CONFIG.default_user_preferences.annotations.to_unsafe @@ -1132,7 +1132,7 @@ def process_video_params(query, preferences) extend_desc ||= CONFIG.default_user_preferences.extend_desc.to_unsafe volume ||= CONFIG.default_user_preferences.volume vr_mode ||= CONFIG.default_user_preferences.vr_mode.to_unsafe - remember_position ||= CONFIG.default_user_preferences.remember_position.to_unsafe + save_player_pos ||= CONFIG.default_user_preferences.save_player_pos.to_unsafe annotations = annotations == 1 autoplay = autoplay == 1 @@ -1144,7 +1144,7 @@ def process_video_params(query, preferences) video_loop = video_loop == 1 extend_desc = extend_desc == 1 vr_mode = vr_mode == 1 - remember_position = remember_position == 1 + save_player_pos = save_player_pos == 1 if CONFIG.disabled?("dash") && quality == "dash" quality = "high" @@ -1195,7 +1195,7 @@ def process_video_params(query, preferences) video_start: video_start, volume: volume, vr_mode: vr_mode, - remember_position: remember_position, + save_player_pos: save_player_pos, }) return params diff --git a/src/invidious/views/preferences.ecr b/src/invidious/views/preferences.ecr index 603c337b..b1ec68ad 100644 --- a/src/invidious/views/preferences.ecr +++ b/src/invidious/views/preferences.ecr @@ -117,8 +117,8 @@
- - checked<% end %>> + + checked<% end %>>
<%= translate(locale, "preferences_category_visual") %> From f31bd5ffb9faf770810360476c63e4e5bed6ed67 Mon Sep 17 00:00:00 2001 From: bbielsa Date: Tue, 26 Oct 2021 19:31:50 -0400 Subject: [PATCH 6/8] Use localization for save player position label in the preferences page --- locales/en-US.json | 3 ++- src/invidious/views/preferences.ecr | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/locales/en-US.json b/locales/en-US.json index 8bdf719b..94aac89e 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -461,5 +461,6 @@ "download_subtitles": "Subtitles - `x` (.vtt)", "user_created_playlists": "`x` created playlists", "user_saved_playlists": "`x` saved playlists", - "Video unavailable": "Video unavailable" + "Video unavailable": "Video unavailable", + "preferences_save_player_pos_label": "Save the current video time: " } diff --git a/src/invidious/views/preferences.ecr b/src/invidious/views/preferences.ecr index b1ec68ad..96904259 100644 --- a/src/invidious/views/preferences.ecr +++ b/src/invidious/views/preferences.ecr @@ -117,7 +117,7 @@
- + checked<% end %>>
From b90bceb2dc0e4bd29b9ace6a0b9d413f8eb673da Mon Sep 17 00:00:00 2001 From: bbielsa Date: Wed, 3 Nov 2021 00:06:29 -0400 Subject: [PATCH 7/8] Fix formatting of preferences.cr and videos.cr --- src/invidious/routes/preferences.cr | 2 +- src/invidious/videos.cr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index a07584c8..15c00700 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -169,7 +169,7 @@ module Invidious::Routes::PreferencesRoute extend_desc: extend_desc, vr_mode: vr_mode, show_nick: show_nick, - save_player_pos: save_player_pos, + save_player_pos: save_player_pos, }.to_json).to_json if user = env.get? "user" diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index 9b4b54e8..d4ef0900 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -1195,7 +1195,7 @@ def process_video_params(query, preferences) video_start: video_start, volume: volume, vr_mode: vr_mode, - save_player_pos: save_player_pos, + save_player_pos: save_player_pos, }) return params From ed6476b5ea1534d18198296f1c897e13467c7c48 Mon Sep 17 00:00:00 2001 From: bbielsa Date: Wed, 17 Nov 2021 20:25:47 -0500 Subject: [PATCH 8/8] Allow the t parameter to override the stored video playback position --- assets/js/player.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/assets/js/player.js b/assets/js/player.js index b4973482..0cc4bab9 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -202,10 +202,14 @@ if (video_data.premiere_timestamp && Math.round(new Date() / 1000) < video_data. } if (video_data.params.save_player_pos) { + const url = new URL(location); + const hasTimeParam = url.searchParams.has("t"); const remeberedTime = get_video_time(); let lastUpdated = 0; - set_seconds_after_start(remeberedTime); + if(!hasTimeParam) { + set_seconds_after_start(remeberedTime); + } const updateTime = () => { const raw = player.currentTime();