mirror of
https://git.nadeko.net/Fijxu/invidious.git
synced 2025-12-19 11:28:51 +00:00
Refactor CSRF tokens (using format in #473)
This commit is contained in:
@@ -19,7 +19,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="token" value="<%= token %>">
|
||||
<input type="hidden" name="challenge" value="<%= challenge %>">
|
||||
<input type="hidden" name="token" value="<%= URI.escape(token) %>">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -85,17 +85,19 @@
|
||||
<div class="thumbnail">
|
||||
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
||||
<% if env.get? "show_watched" %>
|
||||
<p class="watched">
|
||||
<a onclick="mark_watched(this)"
|
||||
data-id="<%= item.id %>"
|
||||
onmouseenter='this["href"]="javascript:void(0)"'
|
||||
href="/mark_watched?id=<%= item.id %>">
|
||||
<i onmouseenter='this.setAttribute("class", "icon ion-ios-eye-off")'
|
||||
onmouseleave='this.setAttribute("class", "icon ion-ios-eye")'
|
||||
class="icon ion-ios-eye">
|
||||
</i>
|
||||
</a>
|
||||
</p>
|
||||
<form onsubmit="return false;" action="/watch_ajax?action_mark_watched=1&id=<%= item.id %>&referer=<%= env.get("current_page") %>" method="post">
|
||||
<input type="hidden" name="token" value="<%= URI.escape(env.get?("token").try &.as(String) || "") %>">
|
||||
<p class="watched">
|
||||
<a onclick="mark_watched(this)" data-id="<%= item.id %>" href="#">
|
||||
<button type="submit" style="all:unset">
|
||||
<i onmouseenter='this.setAttribute("class", "icon ion-ios-eye-off")'
|
||||
onmouseleave='this.setAttribute("class", "icon ion-ios-eye")'
|
||||
class="icon ion-ios-eye">
|
||||
</i>
|
||||
</button>
|
||||
</a>
|
||||
</p>
|
||||
</form>
|
||||
<% end %>
|
||||
<% if item.responds_to?(:live_now) && item.live_now %>
|
||||
<p class="length"><i class="icon ion-ios-play-circle"></i> <%= translate(locale, "LIVE") %></p>
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
<% if user %>
|
||||
<% if subscriptions.includes? ucid %>
|
||||
<p>
|
||||
<a id="subscribe" onclick="unsubscribe()" class="pure-button pure-button-primary"
|
||||
href="/subscription_ajax?action_remove_subscriptions=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>">
|
||||
<b><%= translate(locale, "Unsubscribe") %> | <%= sub_count_text %></b>
|
||||
</a>
|
||||
<form onsubmit="return false;" action="/subscription_ajax?action_remove_subscriptions=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>" method="post">
|
||||
<input type="hidden" name="token" value="<%= URI.escape(env.get?("token").try &.as(String) || "") %>">
|
||||
<a id="subscribe" onclick="unsubscribe()" class="pure-button pure-button-primary" href="#">
|
||||
<b><input style="all:unset" type="submit" value="<%= translate(locale, "Unsubscribe") %> | <%= sub_count_text %>"></b>
|
||||
</a>
|
||||
</form>
|
||||
</p>
|
||||
<% else %>
|
||||
<p>
|
||||
<a id="subscribe" onclick="subscribe()" class="pure-button pure-button-primary"
|
||||
href="/subscription_ajax?action_create_subscription_to_channel=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>">
|
||||
<b><%= translate(locale, "Subscribe") %> | <%= sub_count_text %></b>
|
||||
<form onsubmit="return false;" action="/subscription_ajax?action_create_subscription_to_channel=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>" method="post">
|
||||
<input type="hidden" name="token" value="<%= URI.escape(env.get?("token").try &.as(String) || "") %>">
|
||||
<a id="subscribe" onclick="subscribe()" class="pure-button pure-button-primary" href="#">
|
||||
<b><input style="all:unset" type="submit" value="<%= translate(locale, "Subscribe") %> | <%= sub_count_text %>"></b>
|
||||
</a>
|
||||
</form>
|
||||
</p>
|
||||
<% end %>
|
||||
<% else %>
|
||||
|
||||
@@ -15,8 +15,9 @@ function subscribe(timeouts = 0) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = "json";
|
||||
xhr.timeout = 20000;
|
||||
xhr.open("GET", url, true);
|
||||
xhr.send();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.send("token=<%= URI.escape(env.get?("token").try &.as(String) || "") %>");
|
||||
|
||||
var fallback = subscribe_button.innerHTML;
|
||||
subscribe_button.onclick = unsubscribe;
|
||||
@@ -50,8 +51,9 @@ function unsubscribe(timeouts = 0) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = "json";
|
||||
xhr.timeout = 20000;
|
||||
xhr.open("GET", url, true);
|
||||
xhr.send();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.send("token=<%= URI.escape(env.get?("token").try &.as(String) || "") %>");
|
||||
|
||||
var fallback = subscribe_button.innerHTML;
|
||||
subscribe_button.onclick = subscribe;
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="token" value="<%= token %>">
|
||||
<input type="hidden" name="challenge" value="<%= challenge %>">
|
||||
<input type="hidden" name="token" value="<%= URI.escape(token) %>">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -28,14 +28,16 @@
|
||||
<% else %>
|
||||
<div class="thumbnail">
|
||||
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg"/>
|
||||
<p class="watched">
|
||||
<a onclick="mark_unwatched(this)"
|
||||
data-id="<%= item %>"
|
||||
onmouseenter='this["href"]="javascript:void(0)"'
|
||||
href="/mark_unwatched?id=<%= item %>">
|
||||
<i class="icon ion-md-trash"></i>
|
||||
</a>
|
||||
</p>
|
||||
<form onsubmit="return false;" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post">
|
||||
<input type="hidden" name="token" value="<%= URI.escape(env.get?("token").try &.as(String) || "") %>">
|
||||
<p class="watched">
|
||||
<a onclick="mark_unwatched(this)" data-id="<%= item %>" href="#">
|
||||
<button type="submit" style="all:unset">
|
||||
<i class="icon ion-md-trash"></i>
|
||||
</button>
|
||||
</a>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<p></p>
|
||||
<% end %>
|
||||
@@ -48,17 +50,18 @@
|
||||
|
||||
<script>
|
||||
function mark_unwatched(target) {
|
||||
var tile = target.parentNode.parentNode.parentNode.parentNode;
|
||||
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||
tile.style.display = "none";
|
||||
var count = document.getElementById("count")
|
||||
count.innerText = count.innerText - 1;
|
||||
|
||||
var url = "/mark_unwatched?redirect=false&id=" + target.getAttribute("data-id");
|
||||
var url = "/watch_ajax?action_mark_unwatched=1&redirect=false&id=" + target.getAttribute("data-id");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = "json";
|
||||
xhr.timeout = 20000;
|
||||
xhr.open("GET", url, true);
|
||||
xhr.send();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.send("token=<%= URI.escape(env.get?("token").try &.as(String) || "") %>");
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
|
||||
@@ -42,8 +42,7 @@
|
||||
<% captcha = captcha.not_nil! %>
|
||||
<img style="width:100%" src='<%= captcha[:question] %>'/>
|
||||
<% captcha[:tokens].each_with_index do |token, i| %>
|
||||
<input type="hidden" name="challenge[<%= i %>]" value="<%= token[0] %>">
|
||||
<input type="hidden" name="token[<%= i %>]" value="<%= token[1] %>">
|
||||
<input type="hidden" name="token[<%= i %>]" value="<%= URI.escape(token) %>">
|
||||
<% end %>
|
||||
<input type="hidden" name="captcha_type" value="image">
|
||||
<label for="answer"><%= translate(locale, "Time (h:mm:ss):") %></label>
|
||||
@@ -51,8 +50,7 @@
|
||||
<% when "text" %>
|
||||
<% captcha = captcha.not_nil! %>
|
||||
<% captcha[:tokens].each_with_index do |token, i| %>
|
||||
<input type="hidden" name="challenge[<%= i %>]" value="<%= token[0] %>">
|
||||
<input type="hidden" name="token[<%= i %>]" value="<%= token[1] %>">
|
||||
<input type="hidden" name="token[<%= i %>]" value="<%= URI.escape(token) %>">
|
||||
<% end %>
|
||||
<input type="hidden" name="captcha_type" value="text">
|
||||
<label for="answer"><%= captcha[:question] %></label>
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
<div class="pure-u-2-5"></div>
|
||||
<div class="pure-u-1-5" style="text-align: right;">
|
||||
<h3 style="padding-right: 0.5em">
|
||||
<a onclick="remove_subscription(this)"
|
||||
data-id="<%= channel.id %>"
|
||||
onmouseenter='this["href"]="javascript:void(0)"'
|
||||
href="/subscription_ajax?action_remove_subscriptions=1&c=<%= channel.id %>">
|
||||
<%= translate(locale, "unsubscribe") %>
|
||||
</a>
|
||||
<form onsubmit="return false;" action="/subscription_ajax?action_remove_subscriptions=1&c=<%= channel.id %>&referer=<%= env.get("current_page") %>" method="post">
|
||||
<input type="hidden" name="token" value="<%= URI.escape(env.get?("token").try &.as(String) || "") %>">
|
||||
<a onclick="remove_subscription(this)" data-ucid="<%= channel.id %>" href="#">
|
||||
<input style="all:unset" type="submit" value="<%= translate(locale, "unsubscribe") %>">
|
||||
</a>
|
||||
</form>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
@@ -49,17 +49,18 @@
|
||||
|
||||
<script>
|
||||
function remove_subscription(target) {
|
||||
var row = target.parentNode.parentNode.parentNode.parentNode;
|
||||
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||
row.style.display = "none";
|
||||
var count = document.getElementById("count")
|
||||
count.innerText = count.innerText - 1;
|
||||
|
||||
var url = "/subscription_ajax?action_remove_subscriptions=1&redirect=false&c=" + target.getAttribute("data-id");
|
||||
var url = "/subscription_ajax?action_remove_subscriptions=1&redirect=false&referer=<%= env.get("current_page") %>&c=" + target.getAttribute("data-ucid");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = "json";
|
||||
xhr.timeout = 20000;
|
||||
xhr.open("GET", url, true);
|
||||
xhr.send();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.send("token=<%= URI.escape(env.get?("token").try &.as(String) || "") %>");
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
|
||||
@@ -53,15 +53,16 @@
|
||||
|
||||
<script>
|
||||
function mark_watched(target) {
|
||||
var tile = target.parentNode.parentNode.parentNode.parentNode;
|
||||
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||
tile.style.display = "none";
|
||||
|
||||
var url = "/mark_watched?redirect=false&id=" + target.getAttribute("data-id");
|
||||
var url = "/watch_ajax?action_mark_watched=1&redirect=false&id=" + target.getAttribute("data-id");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = "json";
|
||||
xhr.timeout = 20000;
|
||||
xhr.open("GET", url, true);
|
||||
xhr.send();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.send("token=<%= URI.escape(env.get?("token").try &.as(String) || "") %>");
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
|
||||
@@ -2,143 +2,146 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<%= yield_content "header" %>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#575757">
|
||||
<meta name="msapplication-TileColor" content="#575757">
|
||||
<meta name="theme-color" content="#575757">
|
||||
<link title="Invidious" type="application/opensearchdescription+xml" rel="search" href="/opensearch.xml">
|
||||
<link rel="stylesheet" href="/css/pure-min.css">
|
||||
<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("preferences").as(Preferences).dark_mode %>
|
||||
<link rel="stylesheet" href="/css/darktheme.css">
|
||||
<% else %>
|
||||
<link rel="stylesheet" href="/css/lighttheme.css">
|
||||
<% end %>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<%= yield_content "header" %>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#575757">
|
||||
<meta name="msapplication-TileColor" content="#575757">
|
||||
<meta name="theme-color" content="#575757">
|
||||
<link title="Invidious" type="application/opensearchdescription+xml" rel="search" href="/opensearch.xml">
|
||||
<link rel="stylesheet" href="/css/pure-min.css">
|
||||
<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("preferences").as(Preferences).dark_mode %>
|
||||
<link rel="stylesheet" href="/css/darktheme.css">
|
||||
<% else %>
|
||||
<link rel="stylesheet" href="/css/lighttheme.css">
|
||||
<% end %>
|
||||
</head>
|
||||
|
||||
<% locale = LOCALES[env.get("preferences").as(Preferences).locale]? %>
|
||||
|
||||
<body>
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1 pure-u-md-2-24"></div>
|
||||
<div class="pure-u-1 pure-u-md-20-24">
|
||||
<div class="pure-g navbar h-box">
|
||||
<div class="pure-u-1 pure-u-md-4-24">
|
||||
<a href="/" class="index-link pure-menu-heading">Invidious</a>
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1 pure-u-md-2-24"></div>
|
||||
<div class="pure-u-1 pure-u-md-20-24">
|
||||
<div class="pure-g navbar h-box">
|
||||
<div class="pure-u-1 pure-u-md-4-24">
|
||||
<a href="/" class="index-link pure-menu-heading">Invidious</a>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-12-24 searchbar">
|
||||
<form class="pure-form" action="/search" method="get">
|
||||
<fieldset>
|
||||
<input type="search" style="width:100%;" name="q" placeholder="<%= translate(locale, "search") %>" value="<%= env.get?("search").try {|x| HTML.escape(x.as(String)) } || env.params.query["q"]?.try {|x| HTML.escape(x)} %>">
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-8-24 user-field">
|
||||
<% if env.get? "user" %>
|
||||
<div class="pure-u-1-4">
|
||||
<a href="/toggle_theme?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
||||
<% if env.get("preferences").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-4">
|
||||
<a title="<%= translate(locale, "Subscriptions") %>" href="/feed/subscriptions" class="pure-menu-heading">
|
||||
<% notification_count = env.get("user").as(User).notifications.size %>
|
||||
<% if notification_count > 0 %>
|
||||
<%= notification_count %> <i class="icon ion-ios-notifications"></i>
|
||||
<% else %>
|
||||
<i class="icon ion-ios-notifications-outline"></i>
|
||||
<% end %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="pure-u-1-4">
|
||||
<a title="<%= translate(locale, "Preferences") %>" 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-4">
|
||||
<form action="/signout?referer=<%= env.get?("current_page") %>" method="post">
|
||||
<input type="hidden" name="token" value="<%= URI.escape(env.get?("token").try &.as(String) || "") %>">
|
||||
<a class="pure-menu-heading" href="#">
|
||||
<input style="all:unset" type="submit" value="<%= translate(locale, "Sign out") %>">
|
||||
</a>
|
||||
</form>
|
||||
</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").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 title="<%= translate(locale, "Preferences") %>" href="/preferences?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
||||
<i class="icon ion-ios-cog"></i>
|
||||
</a>
|
||||
</div>
|
||||
<% if config.login_enabled %>
|
||||
<div class="pure-u-1-3">
|
||||
<a href="/login?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
||||
<%= translate(locale, "Login") %>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<%= content %>
|
||||
<div class="footer">
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<a href="https://github.com/omarroth/invidious">
|
||||
<%= translate(locale, "Released under the AGPLv3 by Omar Roth.") %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-bitcoin"></i>
|
||||
BTC: 356DpZyMXu6rYd55Yqzjs29n79kGKWcYrY</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-bitcoin"></i>
|
||||
BCH: qq4ptclkzej5eza6a50et5ggc58hxsq5aylqut2npk</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-usd"></i>
|
||||
<a href="https://liberapay.com/omarroth">Liberapay</a>
|
||||
/
|
||||
<a href="https://patreon.com/omarroth">Patreon</a>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-javascript"></i>
|
||||
<a rel="jslicense" href="/licenses">
|
||||
<%= translate(locale, "View JavaScript license information.") %>
|
||||
</a>
|
||||
/
|
||||
<i class="icon ion-ios-paper"></i>
|
||||
<a href="/privacy">
|
||||
<%= translate(locale, "View privacy policy.") %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-github"></i>
|
||||
<%= translate(locale, "Current version: ") %> <%= CURRENT_VERSION %>-<%= CURRENT_COMMIT %>
|
||||
<i class="icon ion-logo-github"></i>
|
||||
<%= CURRENT_BRANCH %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-12-24 searchbar">
|
||||
<form class="pure-form" action="/search" method="get">
|
||||
<fieldset>
|
||||
<input type="search" style="width:100%;" name="q" placeholder="<%= translate(locale, "search") %>" value="<%= env.get?("search").try {|x| HTML.escape(x.as(String)) } || env.params.query["q"]?.try {|x| HTML.escape(x)} %>">
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-8-24 user-field">
|
||||
<% if env.get? "user" %>
|
||||
<div class="pure-u-1-4">
|
||||
<a href="/toggle_theme?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
||||
<% if env.get("preferences").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-4">
|
||||
<a title="<%= translate(locale, "Subscriptions") %>" href="/feed/subscriptions" class="pure-menu-heading">
|
||||
<% notification_count = env.get("user").as(User).notifications.size %>
|
||||
<% if notification_count > 0 %>
|
||||
<%= notification_count %> <i class="icon ion-ios-notifications"></i>
|
||||
<% else %>
|
||||
<i class="icon ion-ios-notifications-outline"></i>
|
||||
<% end %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="pure-u-1-4">
|
||||
<a title="<%= translate(locale, "Preferences") %>" 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-4">
|
||||
<a href="/signout?referer=<%= env.get?("current_page") %>&token=<%= env.get?("token") %>&challenge=<%= env.get?("challenge") %>" class="pure-menu-heading">
|
||||
<%= translate(locale, "Sign out") %>
|
||||
</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").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 title="<%= translate(locale, "Preferences") %>" href="/preferences?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
||||
<i class="icon ion-ios-cog"></i>
|
||||
</a>
|
||||
</div>
|
||||
<% if config.login_enabled %>
|
||||
<div class="pure-u-1-3">
|
||||
<a href="/login?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
||||
<%= translate(locale, "Login") %>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<%= content %>
|
||||
<div class="footer">
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<a href="https://github.com/omarroth/invidious">
|
||||
<%= translate(locale, "Released under the AGPLv3 by Omar Roth.") %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-bitcoin"></i>
|
||||
BTC: 356DpZyMXu6rYd55Yqzjs29n79kGKWcYrY</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-bitcoin"></i>
|
||||
BCH: qq4ptclkzej5eza6a50et5ggc58hxsq5aylqut2npk</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-usd"></i>
|
||||
<a href="https://liberapay.com/omarroth">Liberapay</a>
|
||||
/
|
||||
<a href="https://patreon.com/omarroth">Patreon</a>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-javascript"></i>
|
||||
<a rel="jslicense" href="/licenses">
|
||||
<%= translate(locale, "View JavaScript license information.") %>
|
||||
</a>
|
||||
/
|
||||
<i class="icon ion-ios-paper"></i>
|
||||
<a href="/privacy">
|
||||
<%= translate(locale, "View privacy policy.") %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-github"></i>
|
||||
<%= translate(locale, "Current version: ") %> <%= CURRENT_VERSION %>-<%= CURRENT_COMMIT %>
|
||||
<i class="icon ion-logo-github"></i>
|
||||
<%= CURRENT_BRANCH %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-2-24"></div>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-2-24"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user