diff options
| -rw-r--r-- | assets/js/watch.js | 54 | ||||
| -rw-r--r-- | src/invidious.cr | 298 | ||||
| -rw-r--r-- | src/invidious/views/components/feed_menu.ecr | 19 | ||||
| -rw-r--r-- | src/invidious/views/index.ecr | 24 | ||||
| -rw-r--r-- | src/invidious/views/popular.ecr | 24 | ||||
| -rw-r--r-- | src/invidious/views/preferences.ecr | 52 | ||||
| -rw-r--r-- | src/invidious/views/subscriptions.ecr | 2 | ||||
| -rw-r--r-- | src/invidious/views/template.ecr | 18 | ||||
| -rw-r--r-- | src/invidious/views/top.ecr | 24 | ||||
| -rw-r--r-- | src/invidious/views/trending.ecr | 24 | ||||
| -rw-r--r-- | src/invidious/views/watch.ecr | 22 |
11 files changed, 259 insertions, 302 deletions
diff --git a/assets/js/watch.js b/assets/js/watch.js index 37ca4e43..7a68c30c 100644 --- a/assets/js/watch.js +++ b/assets/js/watch.js @@ -50,57 +50,3 @@ function hide_youtube_replies(target, inner_text, sub_text) { target.innerHTML = sub_text; target.setAttribute("onclick", "show_youtube_replies(this, \'" + inner_text + "\', \'" + sub_text + "\')"); } - -function download_video(target) { - var title = target.getAttribute("data-title"); - var children = document.getElementById("download_widget").children; - var progress = document.getElementById("download-progress"); - var url = ""; - - document.getElementById("progress-container").style.display = ""; - - for (i = 0; i < children.length; i++) { - if (children[i].selected) { - url = children[i].getAttribute("data-url"); - } - } - - var xhr = new XMLHttpRequest(); - xhr.open("GET", url); - xhr.responseType = "arraybuffer"; - - xhr.onprogress = function(event) { - if (event.lengthComputable) { - progress.style.width = "" + (event.loaded / event.total)*100 + "%"; - } - }; - - xhr.onload = function(event) { - if (event.currentTarget.status != 200) { - console.log("Downloading " + title + " failed.") - document.getElementById("progress-container").style.display = "none"; - progress.style.width = "0%"; - - return; - } - - var data = new Blob([xhr.response], {'type' : 'video/mp4'}); - var videoFile = window.URL.createObjectURL(data); - - var link = document.createElement('a'); - link.href = videoFile; - link.setAttribute('download', title); - document.body.appendChild(link); - - window.requestAnimationFrame(function() { - var event = new MouseEvent('click'); - link.dispatchEvent(event); - document.body.removeChild(link); - }); - - document.getElementById("progress-container").style.display = "none"; - progress.style.width = "0%"; - }; - - xhr.send(null); -}
\ No newline at end of file diff --git a/src/invidious.cr b/src/invidious.cr index 971f0fbd..9f0f6a3f 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -175,6 +175,7 @@ before_all do |env| locale = user.preferences.locale env.set "user", user + env.set "preferences", user.preferences env.set "sid", sid end else @@ -187,12 +188,20 @@ before_all do |env| locale = user.preferences.locale env.set "user", user + env.set "preferences", user.preferences env.set "sid", sid rescue ex end end end + if env.request.cookies.has_key? "PREFS" + preferences = Preferences.from_json(env.request.cookies["PREFS"].value) + + locale = preferences.locale + env.set "preferences", preferences + end + locale = env.params.query["hl"]? || locale locale ||= "en-US" env.set "locale", locale @@ -268,11 +277,12 @@ get "/watch" do |env| nojs ||= "0" nojs = nojs == "1" - user = env.get? "user" - if user - user = user.as(User) + if env.get? "preferences" + preferences = env.get("preferences").as(Preferences) + end - preferences = user.preferences + if env.get? "user" + user = env.get("user").as(User) subscriptions = user.subscriptions watched = user.watched end @@ -866,17 +876,31 @@ post "/login" do |env| host = URI.parse(env.request.headers["Host"]).host + if Kemal.config.ssl || CONFIG.https_only + secure = true + else + secure = false + end + login.cookies.each do |cookie| if Kemal.config.ssl || CONFIG.https_only - cookie.secure = true + cookie.secure = secure else - cookie.secure = false + cookie.secure = secure end cookie.extension = cookie.extension.not_nil!.gsub(".youtube.com", host) cookie.extension = cookie.extension.not_nil!.gsub("Secure; ", "") end + if env.request.cookies["PREFS"]? + preferences = env.get("preferences").as(Preferences) + PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences, user.email) + + login.cookies["PREFS"] = HTTP::Cookie.new(name: "PREFS", value: "", expires: Time.new(1990, 1, 1), + secure: secure, http_only: true) + end + login.cookies.add_response_headers(env.response.headers) env.redirect referer @@ -985,6 +1009,12 @@ post "/login" do |env| error_message = translate(locale, "Invalid username or password") next templated "error" end + + # Since this user has already registered, we don't want to overwrite their preferences + if env.request.cookies["PREFS"]? + env.response.cookies["PREFS"] = HTTP::Cookie.new(name: "PREFS", value: "", expires: Time.new(1990, 1, 1), + secure: secure, http_only: true) + end elsif action == "register" if password.empty? error_message = translate(locale, "Password cannot be empty") @@ -1032,6 +1062,14 @@ post "/login" do |env| env.response.cookies["SID"] = HTTP::Cookie.new(name: "SID", value: sid, expires: Time.now + 2.years, secure: secure, http_only: true) end + + if env.request.cookies["PREFS"]? + preferences = env.get("preferences").as(Preferences) + PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences, user.email) + + env.response.cookies["PREFS"] = HTTP::Cookie.new(name: "PREFS", value: "", expires: Time.new(1990, 1, 1), + secure: secure, http_only: true) + end end env.redirect referer @@ -1073,121 +1111,121 @@ end get "/preferences" do |env| locale = LOCALES[env.get("locale").as(String)]? - - user = env.get? "user" referer = get_referer(env) - if user - user = user.as(User) + if preferences = env.get? "preferences" + preferences = preferences.as(Preferences) + templated "preferences" else - env.redirect referer + preferences = DEFAULT_USER_PREFERENCES + + templated "preferences" end end post "/preferences" do |env| locale = LOCALES[env.get("locale").as(String)]? - - user = env.get? "user" referer = get_referer(env) - if user + video_loop = env.params.body["video_loop"]?.try &.as(String) + video_loop ||= "off" + video_loop = video_loop == "on" + + autoplay = env.params.body["autoplay"]?.try &.as(String) + autoplay ||= "off" + autoplay = autoplay == "on" + + continue = env.params.body["continue"]?.try &.as(String) + continue ||= "off" + continue = continue == "on" + + listen = env.params.body["listen"]?.try &.as(String) + listen ||= "off" + listen = listen == "on" + + speed = env.params.body["speed"]?.try &.as(String).to_f? + speed ||= DEFAULT_USER_PREFERENCES.speed + + quality = env.params.body["quality"]?.try &.as(String) + quality ||= DEFAULT_USER_PREFERENCES.quality + + volume = env.params.body["volume"]?.try &.as(String).to_i? + volume ||= DEFAULT_USER_PREFERENCES.volume + + comments_0 = env.params.body["comments_0"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.comments[0] + comments_1 = env.params.body["comments_1"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.comments[1] + comments = [comments_0, comments_1] + + captions_0 = env.params.body["captions_0"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[0] + captions_1 = env.params.body["captions_1"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[1] + captions_2 = env.params.body["captions_2"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[2] + captions = [captions_0, captions_1, captions_2] + + related_videos = env.params.body["related_videos"]?.try &.as(String) + related_videos ||= "off" + related_videos = related_videos == "on" + + redirect_feed = env.params.body["redirect_feed"]?.try &.as(String) + redirect_feed ||= "off" + redirect_feed = redirect_feed == "on" + + locale = env.params.body["locale"]?.try &.as(String) + locale ||= DEFAULT_USER_PREFERENCES.locale + + dark_mode = env.params.body["dark_mode"]?.try &.as(String) + dark_mode ||= "off" + dark_mode = dark_mode == "on" + + thin_mode = env.params.body["thin_mode"]?.try &.as(String) + thin_mode ||= "off" + thin_mode = thin_mode == "on" + + max_results = env.params.body["max_results"]?.try &.as(String).to_i? + max_results ||= DEFAULT_USER_PREFERENCES.max_results + + sort = env.params.body["sort"]?.try &.as(String) + sort ||= DEFAULT_USER_PREFERENCES.sort + + latest_only = env.params.body["latest_only"]?.try &.as(String) + latest_only ||= "off" + latest_only = latest_only == "on" + + unseen_only = env.params.body["unseen_only"]?.try &.as(String) + unseen_only ||= "off" + unseen_only = unseen_only == "on" + + notifications_only = env.params.body["notifications_only"]?.try &.as(String) + notifications_only ||= "off" + notifications_only = notifications_only == "on" + + preferences = { + "video_loop" => video_loop, + "autoplay" => autoplay, + "continue" => continue, + "listen" => listen, + "speed" => speed, + "quality" => quality, + "volume" => volume, + "comments" => comments, + "captions" => captions, + "related_videos" => related_videos, + "redirect_feed" => redirect_feed, + "locale" => locale, + "dark_mode" => dark_mode, + "thin_mode" => thin_mode, + "max_results" => max_results, + "sort" => sort, + "latest_only" => latest_only, + "unseen_only" => unseen_only, + "notifications_only" => notifications_only, + }.to_json + + if user = env.get? "user" user = user.as(User) - - video_loop = env.params.body["video_loop"]?.try &.as(String) - video_loop ||= "off" - video_loop = video_loop == "on" - - autoplay = env.params.body["autoplay"]?.try &.as(String) - autoplay ||= "off" - autoplay = autoplay == "on" - - continue = env.params.body["continue"]?.try &.as(String) - continue ||= "off" - continue = continue == "on" - - listen = env.params.body["listen"]?.try &.as(String) - listen ||= "off" - listen = listen == "on" - - speed = env.params.body["speed"]?.try &.as(String).to_f? - speed ||= DEFAULT_USER_PREFERENCES.speed - - quality = env.params.body["quality"]?.try &.as(String) - quality ||= DEFAULT_USER_PREFERENCES.quality - - volume = env.params.body["volume"]?.try &.as(String).to_i? - volume ||= DEFAULT_USER_PREFERENCES.volume - - comments_0 = env.params.body["comments_0"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.comments[0] - comments_1 = env.params.body["comments_1"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.comments[1] - comments = [comments_0, comments_1] - - captions_0 = env.params.body["captions_0"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[0] - captions_1 = env.params.body["captions_1"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[1] - captions_2 = env.params.body["captions_2"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[2] - captions = [captions_0, captions_1, captions_2] - - related_videos = env.params.body["related_videos"]?.try &.as(String) - related_videos ||= "off" - related_videos = related_videos == "on" - - redirect_feed = env.params.body["redirect_feed"]?.try &.as(String) - redirect_feed ||= "off" - redirect_feed = redirect_feed == "on" - - locale = env.params.body["locale"]?.try &.as(String) - locale ||= DEFAULT_USER_PREFERENCES.locale - - dark_mode = env.params.body["dark_mode"]?.try &.as(String) - dark_mode ||= "off" - dark_mode = dark_mode == "on" - - thin_mode = env.params.body["thin_mode"]?.try &.as(String) - thin_mode ||= "off" - thin_mode = thin_mode == "on" - - max_results = env.params.body["max_results"]?.try &.as(String).to_i? - max_results ||= DEFAULT_USER_PREFERENCES.max_results - - sort = env.params.body["sort"]?.try &.as(String) - sort ||= DEFAULT_USER_PREFERENCES.sort - - latest_only = env.params.body["latest_only"]?.try &.as(String) - latest_only ||= "off" - latest_only = latest_only == "on" - - unseen_only = env.params.body["unseen_only"]?.try &.as(String) - unseen_only ||= "off" - unseen_only = unseen_only == "on" - - notifications_only = env.params.body["notifications_only"]?.try &.as(String) - notifications_only ||= "off" - notifications_only = notifications_only == "on" - - preferences = { - "video_loop" => video_loop, - "autoplay" => autoplay, - "continue" => continue, - "listen" => listen, - "speed" => speed, - "quality" => quality, - "volume" => volume, - "comments" => comments, - "captions" => captions, - "related_videos" => related_videos, - "redirect_feed" => redirect_feed, - "locale" => locale, - "dark_mode" => dark_mode, - "thin_mode" => thin_mode, - "max_results" => max_results, - "sort" => sort, - "latest_only" => latest_only, - "unseen_only" => unseen_only, - "notifications_only" => notifications_only, - }.to_json - PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences, user.email) + else + env.response.cookies["PREFS"] = preferences end env.redirect referer @@ -1195,21 +1233,24 @@ end get "/toggle_theme" do |env| locale = LOCALES[env.get("locale").as(String)]? - - user = env.get? "user" referer = get_referer(env) - if user + if user = env.get? "user" user = user.as(User) preferences = user.preferences - - if preferences.dark_mode - preferences.dark_mode = false - else - preferences.dark_mode = true - end + preferences.dark_mode = !preferences.dark_mode PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences.to_json, user.email) + elsif preferences = env.get? "preferences" + preferences = preferences.as(Preferences) + preferences.dark_mode = !preferences.dark_mode + + env.response.cookies["PREFS"] = preferences.to_json + else + preferences = DEFAULT_USER_PREFERENCES + preferences.dark_mode = true + + env.response.cookies["PREFS"] = preferences.to_json end env.redirect referer @@ -3863,12 +3904,20 @@ end # YouTube /videoplayback links expire after 6 hours, # so we have a mechanism here to redirect to the latest version get "/latest_version" do |env| - id = env.params.query["id"]? - itag = env.params.query["itag"]? + if env.params.query["download_widget"]? + download_widget = JSON.parse(env.params.query["download_widget"]) + id = download_widget["id"].as_s + itag = download_widget["itag"].as_s + title = download_widget["title"].as_s + local = "true" + end + + id ||= env.params.query["id"]? + itag ||= env.params.query["itag"]? region = env.params.query["region"]? - local = env.params.query["local"]? + local ||= env.params.query["local"]? local ||= "false" local = local == "true" @@ -3893,6 +3942,10 @@ get "/latest_version" do |env| url = URI.parse(url).full_path.not_nil! end + if title + url += "&title=#{title}" + end + env.redirect url end @@ -3997,6 +4050,10 @@ get "/videoplayback" do |env| client.get(url, headers) do |response| env.response.status_code = response.status_code + if title = env.params.query["title"]? + env.response.headers["Content-Disposition"] = "attachment; filename=#{title}" + end + response.headers.each do |key, value| env.response.headers[key] = value end @@ -4210,6 +4267,7 @@ add_handler FilteredCompressHandler.new add_handler DenyFrame.new add_handler APIHandler.new add_context_storage_type(User) +add_context_storage_type(Preferences) Kemal.config.logger = logger Kemal.run diff --git a/src/invidious/views/components/feed_menu.ecr b/src/invidious/views/components/feed_menu.ecr new file mode 100644 index 00000000..5188689a --- /dev/null +++ b/src/invidious/views/components/feed_menu.ecr @@ -0,0 +1,19 @@ +<div class="h-box pure-g"> + <div class="pure-u-1-4"></div> + <div class="pure-u-1 pure-u-md-1-2"> + <div class="pure-g"> + <% feeds = ["Popular", "Top", "Trending"] %> + <% if env.get? "user" %> + <% feeds << "Subscriptions" %> + <% end %> + <% feeds.each do |feed| %> + <div class="pure-u-1-<%= feeds.size %>"> + <a href="/feed/<%= feed.downcase %>" style="text-align:center;" class="pure-menu-heading"> + <%= translate(locale, feed) %> + </a> + </div> + <% end %> + </div> + </div> + <div class="pure-u-1-4"></div> +</div>
\ No newline at end of file diff --git a/src/invidious/views/index.ecr b/src/invidious/views/index.ecr index a12455b0..6cc978e5 100644 --- a/src/invidious/views/index.ecr +++ b/src/invidious/views/index.ecr @@ -3,29 +3,7 @@ <title>Invidious</title> <% end %> -<div class="h-box pure-g"> - <div class="pure-u-1-4"></div> - <div class="pure-u-1 pure-u-md-1-2"> - <div class="pure-g"> - <div class="pure-u-1-3"> - <a href="/feed/popular" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Popular") %> - </a> - </div> - <div class="pure-u-1-3"> - <a href="/feed/top" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Top") %> - </a> - </div> - <div class="pure-u-1-3"> - <a href="/feed/trending" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Trending") %> - </a> - </div> - </div> - </div> - <div class="pure-u-1-4"></div> -</div> +<%= rendered "components/feed_menu" %> <div class="pure-g"> <% top_videos.each_slice(4) do |slice| %> diff --git a/src/invidious/views/popular.ecr b/src/invidious/views/popular.ecr index 8d67241f..f235aad8 100644 --- a/src/invidious/views/popular.ecr +++ b/src/invidious/views/popular.ecr @@ -3,29 +3,7 @@ <title><%= translate(locale, "Popular") %> - Invidious</title> <% end %> -<div class="h-box pure-g"> - <div class="pure-u-1-4"></div> - <div class="pure-u-1 pure-u-md-1-2"> - <div class="pure-g"> - <div class="pure-u-1-3"> - <a href="/feed/popular" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Popular") %> - </a> - </div> - <div class="pure-u-1-3"> - <a href="/feed/top" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Top") %> - </a> - </div> - <div class="pure-u-1-3"> - <a href="/feed/trending" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Trending") %> - </a> - </div> - </div> - </div> - <div class="pure-u-1-4"></div> -</div> +<%= rendered "components/feed_menu" %> <div class="pure-g"> <% popular_videos.each_slice(4) do |slice| %> diff --git a/src/invidious/views/preferences.ecr b/src/invidious/views/preferences.ecr index cd752900..7435c91e 100644 --- a/src/invidious/views/preferences.ecr +++ b/src/invidious/views/preferences.ecr @@ -15,29 +15,29 @@ function update_value(element) { <div class="pure-control-group"> <label for="video_loop"><%= translate(locale, "Always loop: ") %></label> - <input name="video_loop" id="video_loop" type="checkbox" <% if user.preferences.video_loop %>checked<% end %>> + <input name="video_loop" id="video_loop" type="checkbox" <% if preferences.video_loop %>checked<% end %>> </div> <div class="pure-control-group"> <label for="autoplay"><%= translate(locale, "Autoplay: ") %></label> - <input name="autoplay" id="autoplay" type="checkbox" <% if user.preferences.autoplay %>checked<% end %>> + <input name="autoplay" id="autoplay" type="checkbox" <% if preferences.autoplay %>checked<% end %>> </div> <div class="pure-control-group"> <label for="continue"><%= translate(locale, "Autoplay next video: ") %></label> - <input name="continue" id="continue" type="checkbox" <% if user.preferences.continue %>checked<% end %>> + <input name="continue" id="continue" type="checkbox" <% if preferences.continue %>checked<% end %>> </div> <div class="pure-control-group"> <label for="listen"><%= translate(locale, "Listen by default: ") %></label> - <input name="listen" id="listen" type="checkbox" <% if user.preferences.listen %>checked<% end %>> + <input name="listen" id="listen" type="checkbox" <% if preferences.listen %>checked<% end %>> </div> <div class="pure-control-group"> <label for="speed"><%= translate(locale, "Default speed: ") %></label> <select name="speed" id="speed"> <% {2.0, 1.5, 1.0, 0.5}.each do |option| %> - <option <% if user.preferences.speed == option %> selected <% end %>><%= option %></option> + <option <% if preferences.speed == option %> selected <% end %>><%= option %></option> <% end %> </select> </div> @@ -46,22 +46,22 @@ function update_value(element) { <label for="quality"><%= translate(locale, "Preferred video quality: ") %></label> <select name="quality" id="quality"> <% {"dash", "hd720", "medium", "small"}.each do |option| %> - <option value="<%= option %>" <% if user.preferences.quality == option %> selected <% end %>><%= translate(locale, option) %></option> + <option value="<%= option %>" <% if preferences.quality == option %> selected <% end %>><%= translate(locale, option) %></option> <% end %> </select> </div> <div class="pure-control-group"> <label for="volume"><%= translate(locale, "Player volume: ") %></label> - <input name="volume" id="volume" oninput="update_value(this);" type="range" min="0" max="100" step="5" value="<%= user.preferences.volume %>"> - <span class="pure-form-message-inline" id="volume-value"><%= user.preferences.volume %></span> + <input name="volume" id="volume" oninput="update_value(this);" type="range" min="0" max="100" step="5" value="<%= preferences.volume %>"> + <span class="pure-form-message-inline" id="volume-value"><%= preferences.volume %></span> </div> <div class="pure-control-group"> <label for="comments_0"><%= translate(locale, "Default comments: ") %></label> <select name="comments_0" id="comments_0"> <% {"", "youtube", "reddit"}.each do |option| %> - <option value="<%= option %>" <% if user.preferences.comments[0] == option %> selected <% end %>><%= translate(locale, option) %></option> + <option value="<%= option %>" <% if preferences.comments[0] == option %> selected <% end %>><%= translate(locale, option) %></option> <% end %> </select> </div> @@ -70,7 +70,7 @@ function update_value(element) { <label for="comments_1"><%= translate(locale, "Fallback comments: ") %></label> <select name="comments_1" id="comments_1"> <% {"", "youtube", "reddit"}.each do |option| %> - <option value="<%= option %>" <% if user.preferences.comments[1] == option %> selected <% end %>><%= translate(locale, option) %></option> + <option value="<%= option %>" <% if preferences.comments[1] == option %> selected <% end %>><%= translate(locale, option) %></option> <% end %> </select> </div> @@ -79,7 +79,7 @@ function update_value(element) { <label for="captions_0"><%= translate(locale, "Default captions: ") %></label> <select class="pure-u-1-5" name="captions_0" id="captions_0"> <% CAPTION_LANGUAGES.each do |option| %> - <option value="<%= option %>" <% if user.preferences.captions[0] == option %> selected <% end %>><%= translate(locale, option) %></option> + <option value="<%= option %>" <% if preferences.captions[0] == option %> selected <% end %>><%= translate(locale, option) %></option> <% end %> </select> </div> @@ -88,20 +88,20 @@ function update_value(element) { <label for="captions_fallback"><%= translate(locale, "Fallback captions: ") %></label> <select class="pure-u-1-5" name="captions_1" id="captions_1"> <% CAPTION_LANGUAGES.each do |option| %> - <option value="<%= option %>" <% if user.preferences.captions[1] == option %> selected <% end %>><%= translate(locale, option) %></option> + <option value="<%= option %>" <% if preferences.captions[1] == option %> selected <% end %>><%= translate(locale, option) %></option> <% end %> </select> <select class="pure-u-1-5" name="captions_2" id="captions_2"> <% CAPTION_LANGUAGES.each do |option| %> - <option value="<%= option %>" <% if user.preferences.captions[2] == option %> selected <% end %>><%= translate(locale, option) %></option> + <option value="<%= option %>" <% if preferences.captions[2] == option %> selected <% end %>><%= translate(locale, option) %></option> <% end %> </select> </div> <div class="pure-control-group"> <label for="related_videos"><%= translate(locale, "Show related videos? ") %></label> - <input name="related_videos" id="related_videos" type="checkbox" <% if user.preferences.related_videos %>checked<% end %>> + <input name="related_videos" id="related_videos" type="checkbox" <% if preferences.related_videos %>checked<% end %>> </div> <legend><%= translate(locale, "Visual preferences") %></legend> @@ -110,61 +110,64 @@ function update_value(element) { <label for="locale"><%= translate(locale, "Language: ") %></label> <select name="locale" id="locale"> <% LOCALES.each_key do |option| %> - <option value="<%= option %>" <% if user.preferences.locale == option %> selected <% end %>><%= option %></option> + <option value="<%= option %>" <% if preferences.locale == option %> selected <% end %>><%= option %></option> <% end %> </select> </div> <div class="pure-control-group"> <label for="dark_mode"><%= translate(locale, "Dark mode: ") %></label> - <input name="dark_mode" id="dark_mode" type="checkbox" <% if user.preferences.dark_mode %>checked<% end %>> + <input name="dark_mode" id="dark_mode" type="checkbox" <% if preferences.dark_mode %>checked<% end %>> </div> <div class="pure-control-group"> <label for="thin_mode"><%= translate(locale, "Thin mode: ") %></label> - <input name="thin_mode" id="thin_mode" type="checkbox" <% if user.preferences.thin_mode %>checked<% end %>> + <input name="thin_mode" id="thin_mode" type="checkbox" <% if preferences.thin_mode %>checked<% end %>> </div> + <% if env.get? "user" %> <legend><%= translate(locale, "Subscription preferences") %></legend> <div class="pure-control-group"> <label for="redirect_feed"><%= translate(locale, "Redirect homepage to feed: ") %></label> - <input name="redirect_feed" id="redirect_feed" type="checkbox" <% if user.preferences.redirect_feed %>checked<% end %>> + <input name="redirect_feed" id="redirect_feed" type="checkbox" <% if preferences.redirect_feed %>checked<% end %>> </div> <div class="pure-control-group"> <label for="max_results"><%= translate(locale, "Number of videos shown in feed: ") %></label> - <input name="max_results" id="max_results" type="number" value="<%= user.preferences.max_results %>"> + <input name="max_results" id="max_results" type="number" value="<%= preferences.max_results %>"> </div> <div class="pure-control-group"> <label for="sort"><%= translate(locale, "Sort videos by: ") %></label> <select name="sort" id="sort"> <% {"published", "published - reverse", "alphabetically", "alphabetically - reverse", "channel name", "channel name - reverse"}.each do |option| %> - <option value="<%= option %>" <% if user.preferences.sort == option %> selected <% end %>><%= translate(locale, option) %></option> + <option value="<%= option %>" <% if preferences.sort == option %> selected <% end %>><%= translate(locale, option) %></option> <% end %> </select> </div> <div class="pure-control-group"> - <% if user.preferences.unseen_only %> + <% if preferences.unseen_only %> <label for="latest_only"><%= translate(locale, "Only show latest unwatched video from channel: ") %></label> <% else %> <label for="latest_only"><%= translate(locale, "Only show latest video from channel: ") %></label> <% end %> - <input name="latest_only" id="latest_only" type="checkbox" <% if user.preferences.latest_only %>checked<% end %>> + <input name="latest_only" id="latest_only" type="checkbox" <% if preferences.latest_only %>checked<% end %>> </div> <div class="pure-control-group"> <label for="unseen_only"><%= translate(locale, "Only show unwatched: ") %></label> - <input name="unseen_only" id="unseen_only" type="checkbox" <% if user.preferences.unseen_only %>checked<% end %>> + <input name="unseen_only" id="unseen_only" type="checkbox" <% if preferences.unseen_only %>checked<% end %>> </div> <div class="pure-control-group"> <label for="notifications_only"><%= translate(locale, "Only show notifications (if there are any): ") %></label> - <input name="notifications_only" id="notifications_only" type="checkbox" <% if user.preferences.notifications_only %>checked<% end %>> + <input name="notifications_only" id="notifications_only" type="checkbox" <% if preferences.notifications_only %>checked<% end %>> </div> + <% end %> + <% if env.get? "user" %> <legend><%= translate(locale, "Data preferences") %></legend> <div class="pure-control-group"> @@ -186,6 +189,7 @@ function update_value(element) { <div class="pure-control-group"> <a href="/delete_account?referer=<%= URI.escape(referer) %>"><%= translate(locale, "Delete account") %></a> </div> + <% end %> <div class="pure-controls"> <button type="submit" class="pure-button pure-button-primary"><%= translate(locale, "Save preferences") %></button> diff --git a/src/invidious/views/subscriptions.ecr b/src/invidious/views/subscriptions.ecr index 6679cdf9..109da18f 100644 --- a/src/invidious/views/subscriptions.ecr +++ b/src/invidious/views/subscriptions.ecr @@ -2,6 +2,8 @@ <title><%= translate(locale, "Subscriptions") %> - Invidious</title> <% end %> +<%= rendered "components/feed_menu" %> + <div class="pure-g h-box"> <div class="pure-u-1-3"> <h3> diff --git a/src/invidious/views/template.ecr b/src/invidious/views/template.ecr index 8f2d9c9b..a7d96d72 100644 --- a/src/invidious/views/template.ecr +++ b/src/invidious/views/template.ecr @@ -18,7 +18,7 @@ <link rel="stylesheet" href="/css/grids-responsive-min.css"> <link rel="stylesheet" href="/css/ionicons.min.css"> <link rel="stylesheet" href="/css/default.css"> - <% if env.get?("user") && env.get("user").as(User).preferences.dark_mode %> + <% if env.get?("preferences").try &.as(Preferences).dark_mode %> <link rel="stylesheet" href="/css/darktheme.css"> <% else %> <link rel="stylesheet" href="/css/lighttheme.css"> @@ -75,9 +75,25 @@ </a> </div> <% else %> + <div class="pure-u-1-3"> + <a href="/toggle_theme?referer=<%= env.get?("current_page") %>" class="pure-menu-heading"> + <% if env.get?("preferences").try &.as(Preferences).dark_mode %> + <i class="icon ion-ios-sunny"></i> + <% else %> + <i class="icon ion-ios-moon"></i> + <% end %> + </a> + </div> + <div class="pure-u-1-3"> + <a href="/preferences?referer=<%= env.get?("current_page") %>" class="pure-menu-heading"> + <i class="icon ion-ios-cog"></i> + </a> + </div> + <div class="pure-u-1-3"> <a href="/login?referer=<%= env.get?("current_page") %>" class="pure-menu-heading"> <%= translate(locale, "Login") %> </a> + </div> <% end %> </div> </div> diff --git a/src/invidious/views/top.ecr b/src/invidious/views/top.ecr index ea5679c4..acf122a6 100644 --- a/src/invidious/views/top.ecr +++ b/src/invidious/views/top.ecr @@ -3,29 +3,7 @@ <title><%= translate(locale, "Top") %> - Invidious</title> <% end %> -<div class="h-box pure-g"> - <div class="pure-u-1-4"></div> - <div class="pure-u-1 pure-u-md-1-2"> - <div class="pure-g"> - <div class="pure-u-1-3"> - <a href="/feed/popular" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Popular") %> - </a> - </div> - <div class="pure-u-1-3"> - <a href="/feed/top" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Top") %> - </a> - </div> - <div class="pure-u-1-3"> - <a href="/feed/trending" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Trending") %> - </a> - </div> - </div> - </div> - <div class="pure-u-1-4"></div> -</div> +<%= rendered "components/feed_menu" %> <div class="pure-g"> <% top_videos.each_slice(4) do |slice| %> diff --git a/src/invidious/views/trending.ecr b/src/invidious/views/trending.ecr index a3db4de3..617a9a58 100644 --- a/src/invidious/views/trending.ecr +++ b/src/invidious/views/trending.ecr @@ -3,29 +3,7 @@ <title><%= translate(locale, "Trending") %> - Invidious</title> <% end %> -<div class="h-box pure-g"> - <div class="pure-u-1-4"></div> - <div class="pure-u-1 pure-u-md-1-2"> - <div class="pure-g"> - <div class="pure-u-1-3"> - <a href="/feed/popular" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Popular") %> - </a> - </div> - <div class="pure-u-1-3"> - <a href="/feed/top" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Top") %> - </a> - </div> - <div class="pure-u-1-3"> - <a href="/feed/trending" style="text-align:center;" class="pure-menu-heading"> - <%= translate(locale, "Trending") %> - </a> - </div> - </div> - </div> - <div class="pure-u-1-4"></div> -</div> +<%= rendered "components/feed_menu" %> <div class="pure-g h-box"> <div class="pure-u-2-3"> diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 9432eb4e..3949245d 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -54,29 +54,29 @@ <div class="h-box"> <p><a href="https://www.youtube.com/watch?v=<%= video.id %>"><%= translate(locale, "Watch video on Youtube") %></a></p> - <form class="pure-form pure-form-stacked"> + <form class="pure-form pure-form-stacked" action="/latest_version" method="get" rel="noopener" target="_blank"> <div class="pure-control-group"> <label for="download_widget"><%= translate(locale, "Download as: ") %></label> <select style="width:100%" name="download_widget" id="download_widget"> <% video_streams.each do |option| %> - <option data-url="/latest_version?id=<%= video.id %>&itag=<%= option["itag"] %>&local=true"><%= option["quality_label"] %> - <%= option["type"].split(";")[0] %> @ <%= option["fps"] %>fps - video only</option> + <option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= video.title.dump_unquoted %>-<%= video.id %>.mp4"}'> + <%= option["quality_label"] %> - <%= option["type"].split(";")[0] %> @ <%= option["fps"] %>fps - video only + </option> <% end %> <% audio_streams.each do |option| %> - <option data-url="/latest_version?id=<%= video.id %>&itag=<%= option["itag"] %>&local=true"><%= option["type"].split(";")[0] %> @ <%= option["bitrate"] %>k - audio only</option> + <option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= video.title.dump_unquoted %>-<%= video.id %>.mp4"}'> + <%= option["type"].split(";")[0] %> @ <%= option["bitrate"] %>k - audio only + </option> <% end %> <% fmt_stream.each do |option| %> - <option data-url="/latest_version?id=<%= video.id %>&itag=<%= option["itag"] %>&local=true"><%= itag_to_metadata?(option["itag"]).try &.["height"]? || "~240" %>p - <%= option["type"].split(";")[0] %></option> + <option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= video.title.dump_unquoted %>-<%= video.id %>.mp4"}'> + <%= itag_to_metadata?(option["itag"]).try &.["height"]? || "~240" %>p - <%= option["type"].split(";")[0] %> + </option> <% end %> </select> </div> - <div id="progress-container" style="width:100%; display:none"> - <div id="download-progress"> - </div> - </div> - - <button type="button" data-title="<%= video.title.dump_unquoted %>-<%= video.id %>.mp4" onclick="download_video(this)" - class="pure-button pure-button-primary"> + <button type="submit" class="pure-button pure-button-primary"> <b><%= translate(locale, "Download") %></b> </button> </form> |
