Compare commits

...

11 Commits

Author SHA1 Message Date
4c516a7d57 cargo fmt 2025-01-17 23:05:53 +13:00
05e2c31bec #18
i seem to have left my brain somewhere
2025-01-13 15:10:35 +13:00
dcad2ac142 Merge pull request 'subreddit banners' (#18) from subreddit-banners into main
Reviewed-on: #18
2025-01-13 14:48:31 +13:00
0dcda02d27 Merge branch 'main' into subreddit-banners 2025-01-13 14:48:11 +13:00
7e09609daa Merge pull request 'subreddit-created-date' (#19) from subreddit-created-date into main
Reviewed-on: #19
2025-01-13 14:44:15 +13:00
49afd83ad3 subreddit-created-date 2025-01-13 14:41:49 +13:00
138172b365 unnecessary log generation 2025-01-13 14:18:05 +13:00
200509255c allow disabling of banner 2025-01-13 14:15:35 +13:00
bfcc946baa subreddit banners 2025-01-11 15:05:18 +13:00
0791f6af41 video quality recategorization 2025-01-09 08:56:51 +13:00
76bf796572 video quality recategorization 2025-01-09 08:56:33 +13:00
14 changed files with 70 additions and 29 deletions

2
Cargo.lock generated
View File

@ -1357,7 +1357,7 @@ dependencies = [
[[package]] [[package]]
name = "redsunlib" name = "redsunlib"
version = "0.35.3" version = "0.35.4"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"async-recursion", "async-recursion",

View File

@ -338,4 +338,5 @@ Assign a default value for each user-modifiable setting by passing environment v
| `DISABLE_VISIT_REDDIT_CONFIRMATION` | `["on", "off"]` | `off` | | `DISABLE_VISIT_REDDIT_CONFIRMATION` | `["on", "off"]` | `off` |
| `HIDE_SCORE` | `["on", "off"]` | `off` | | `HIDE_SCORE` | `["on", "off"]` | `off` |
| `HIDE_SIDEBAR_AND_SUMMARY` | `["on", "off"]` | `off` | | `HIDE_SIDEBAR_AND_SUMMARY` | `["on", "off"]` | `off` |
| `HIDE_BANNER` | `["on", "off"]` | `off` |
| `FIXED_NAVBAR` | `["on", "off"]` | `on` | | `FIXED_NAVBAR` | `["on", "off"]` | `on` |

View File

@ -7,7 +7,7 @@ use hyper::header::HeaderValue;
use hyper::{body, body::Buf, header, Body, Client, Method, Request, Response, Uri}; use hyper::{body, body::Buf, header, Body, Client, Method, Request, Response, Uri};
use hyper_rustls::HttpsConnector; use hyper_rustls::HttpsConnector;
use libflate::gzip; use libflate::gzip;
use log::{error, trace, warn}; use log::{debug, error, warn};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use percent_encoding::{percent_encode, CONTROLS}; use percent_encoding::{percent_encode, CONTROLS};
use serde_json::Value; use serde_json::Value;
@ -396,7 +396,7 @@ pub async fn json(path: String, quarantine: bool) -> Result<Value, String> {
response.headers().get("x-ratelimit-reset").and_then(|val| val.to_str().ok().map(|s| s.to_string())), response.headers().get("x-ratelimit-reset").and_then(|val| val.to_str().ok().map(|s| s.to_string())),
response.headers().get("x-ratelimit-used").and_then(|val| val.to_str().ok().map(|s| s.to_string())), response.headers().get("x-ratelimit-used").and_then(|val| val.to_str().ok().map(|s| s.to_string())),
) { ) {
trace!( debug!(
"Ratelimit remaining: Header says {remaining}, we have {current_rate_limit}. Resets in {reset}. Rollover: {}. Ratelimit used: {used}", "Ratelimit remaining: Header says {remaining}, we have {current_rate_limit}. Resets in {reset}. Rollover: {}. Ratelimit used: {used}",
if is_rolling_over { "yes" } else { "no" }, if is_rolling_over { "yes" } else { "no" },
); );

View File

@ -84,6 +84,10 @@ pub struct Config {
#[serde(alias = "LIBREDDIT_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY")] #[serde(alias = "LIBREDDIT_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY")]
pub(crate) default_hide_sidebar_and_summary: Option<String>, pub(crate) default_hide_sidebar_and_summary: Option<String>,
#[serde(rename = "REDLIB_DEFAULT_HIDE_BANNER")]
#[serde(alias = "LIBREDDIT_DEFAULT_HIDE_BANNER")]
pub(crate) default_hide_banner: Option<String>,
#[serde(rename = "REDLIB_DEFAULT_HIDE_SCORE")] #[serde(rename = "REDLIB_DEFAULT_HIDE_SCORE")]
#[serde(alias = "LIBREDDIT_DEFAULT_HIDE_SCORE")] #[serde(alias = "LIBREDDIT_DEFAULT_HIDE_SCORE")]
pub(crate) default_hide_score: Option<String>, pub(crate) default_hide_score: Option<String>,
@ -161,6 +165,7 @@ impl Config {
default_hide_hls_notification: parse("REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION"), default_hide_hls_notification: parse("REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION"),
default_hide_awards: parse("REDLIB_DEFAULT_HIDE_AWARDS"), default_hide_awards: parse("REDLIB_DEFAULT_HIDE_AWARDS"),
default_hide_sidebar_and_summary: parse("REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY"), default_hide_sidebar_and_summary: parse("REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY"),
default_hide_banner: parse("REDLIB_DEFAULT_HIDE_BANNER"),
default_hide_score: parse("REDLIB_DEFAULT_HIDE_SCORE"), default_hide_score: parse("REDLIB_DEFAULT_HIDE_SCORE"),
default_subscriptions: parse("REDLIB_DEFAULT_SUBSCRIPTIONS"), default_subscriptions: parse("REDLIB_DEFAULT_SUBSCRIPTIONS"),
default_filters: parse("REDLIB_DEFAULT_FILTERS"), default_filters: parse("REDLIB_DEFAULT_FILTERS"),
@ -193,6 +198,7 @@ fn get_setting_from_config(name: &str, config: &Config) -> Option<String> {
"REDLIB_DEFAULT_WIDE" => config.default_wide.clone(), "REDLIB_DEFAULT_WIDE" => config.default_wide.clone(),
"REDLIB_DEFAULT_HIDE_AWARDS" => config.default_hide_awards.clone(), "REDLIB_DEFAULT_HIDE_AWARDS" => config.default_hide_awards.clone(),
"REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY" => config.default_hide_sidebar_and_summary.clone(), "REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY" => config.default_hide_sidebar_and_summary.clone(),
"REDLIB_DEFAULT_HIDE_BANNER" => config.default_hide_banner.clone(),
"REDLIB_DEFAULT_HIDE_SCORE" => config.default_hide_score.clone(), "REDLIB_DEFAULT_HIDE_SCORE" => config.default_hide_score.clone(),
"REDLIB_DEFAULT_SUBSCRIPTIONS" => config.default_subscriptions.clone(), "REDLIB_DEFAULT_SUBSCRIPTIONS" => config.default_subscriptions.clone(),
"REDLIB_DEFAULT_FILTERS" => config.default_filters.clone(), "REDLIB_DEFAULT_FILTERS" => config.default_filters.clone(),

View File

@ -148,7 +148,7 @@ impl InstanceInfo {
["Show NSFW", &convert(&self.config.default_show_nsfw)], ["Show NSFW", &convert(&self.config.default_show_nsfw)],
["Blur NSFW", &convert(&self.config.default_blur_nsfw)], ["Blur NSFW", &convert(&self.config.default_blur_nsfw)],
["Use HLS", &convert(&self.config.default_use_hls)], ["Use HLS", &convert(&self.config.default_use_hls)],
["Use FFmpeg", &convert(&self.config.default_ffmpeg_video_downloads)], ["Use FFmpeg", &convert(&self.config.default_ffmpeg_video_downloads)],
["Hide HLS notification", &convert(&self.config.default_hide_hls_notification)], ["Hide HLS notification", &convert(&self.config.default_hide_hls_notification)],
["Subscriptions", &convert(&self.config.default_subscriptions)], ["Subscriptions", &convert(&self.config.default_subscriptions)],
["Filters", &convert(&self.config.default_filters)], ["Filters", &convert(&self.config.default_filters)],

View File

@ -13,7 +13,7 @@ use log::info;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use redsunlib::client::{canonical_path, proxy, CLIENT}; use redsunlib::client::{canonical_path, proxy, CLIENT};
use redsunlib::server::{self, RequestExt}; use redsunlib::server::{self, RequestExt};
use redsunlib::utils::{error, redirect, ThemeAssets, MascotAssets}; use redsunlib::utils::{error, redirect, MascotAssets, ThemeAssets};
use redsunlib::{config, duplicates, headers, instance_info, post, search, settings, subreddit, user}; use redsunlib::{config, duplicates, headers, instance_info, post, search, settings, subreddit, user};
use redsunlib::client::OAUTH_CLIENT; use redsunlib::client::OAUTH_CLIENT;
@ -110,8 +110,7 @@ async fn style() -> Result<Response<Body>, String> {
/// Serve mascot /// Serve mascot
async fn mascot_image(req: Request<Body>) -> Result<Response<Body>, String> { async fn mascot_image(req: Request<Body>) -> Result<Response<Body>, String> {
let res = MascotAssets::get(&req.param("name").unwrap()) let res = MascotAssets::get(&req.param("name").unwrap()).unwrap_or(MascotAssets::get("redsunlib.png").unwrap());
.unwrap_or(MascotAssets::get("redsunlib.png").unwrap());
Ok( Ok(
Response::builder() Response::builder()
.status(200) .status(200)
@ -249,7 +248,7 @@ async fn main() {
app.at("/commits.json").get(|_| async move { proxy_commit_info().await }.boxed()); app.at("/commits.json").get(|_| async move { proxy_commit_info().await }.boxed());
app.at("/instances.json").get(|_| async move { proxy_instances().await }.boxed()); app.at("/instances.json").get(|_| async move { proxy_instances().await }.boxed());
// FFmpeg // FFmpeg
app app
.at("/ffmpeg/814.ffmpeg.js") .at("/ffmpeg/814.ffmpeg.js")

View File

@ -6,7 +6,7 @@ use crate::{
}; };
use base64::{engine::general_purpose, Engine as _}; use base64::{engine::general_purpose, Engine as _};
use hyper::{client, Body, Method, Request}; use hyper::{client, Body, Method, Request};
use log::{error, info, trace}; use log::{debug, error, info, trace};
use serde_json::json; use serde_json::json;
use tokio::time::{error::Elapsed, timeout}; use tokio::time::{error::Elapsed, timeout};
@ -160,7 +160,7 @@ pub async fn force_refresh_token() {
return; return;
} }
trace!("Rolling over refresh token. Current rate limit: {}", OAUTH_RATELIMIT_REMAINING.load(Ordering::SeqCst)); debug!("Rolling over refresh token. Current rate limit: {}", OAUTH_RATELIMIT_REMAINING.load(Ordering::SeqCst));
let new_client = Oauth::new().await; let new_client = Oauth::new().await;
OAUTH_CLIENT.swap(new_client.into()); OAUTH_CLIENT.swap(new_client.into());
OAUTH_RATELIMIT_REMAINING.store(99, Ordering::SeqCst); OAUTH_RATELIMIT_REMAINING.store(99, Ordering::SeqCst);

View File

@ -21,7 +21,7 @@ struct SettingsTemplate {
// CONSTANTS // CONSTANTS
const PREFS: [&str; 21] = [ const PREFS: [&str; 22] = [
"theme", "theme",
"mascot", "mascot",
"redsunlib_colorway", "redsunlib_colorway",
@ -38,6 +38,7 @@ const PREFS: [&str; 21] = [
"hide_hls_notification", "hide_hls_notification",
"autoplay_videos", "autoplay_videos",
"hide_sidebar_and_summary", "hide_sidebar_and_summary",
"hide_banner",
"fixed_navbar", "fixed_navbar",
"hide_awards", "hide_awards",
"hide_score", "hide_score",

View File

@ -12,7 +12,9 @@ use rinja::Template;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use time::{Duration, OffsetDateTime}; use time::{macros::format_description, Duration, OffsetDateTime};
use log::trace;
// STRUCTS // STRUCTS
#[derive(Template)] #[derive(Template)]
@ -299,8 +301,7 @@ pub async fn subscriptions_filters_quicklists(req: Request<Body>) -> Result<Resp
} else if action.contains(&"unquicklist".to_string()) { } else if action.contains(&"unquicklist".to_string()) {
// Remove sub name from filtered list // Remove sub name from filtered list
quicklist.retain(|s| s.to_lowercase() != part.to_lowercase()); quicklist.retain(|s| s.to_lowercase() != part.to_lowercase());
} }
} }
// Redirect back to subreddit // Redirect back to subreddit
@ -461,14 +462,24 @@ async fn subreddit(sub: &str, quarantined: bool) -> Result<Subreddit, String> {
// Send a request to the url // Send a request to the url
let res = json(path, quarantined).await?; let res = json(path, quarantined).await?;
trace!("Subreddit info from r/{} : {}", sub, res["data"]);
// Metadata regarding the subreddit // Metadata regarding the subreddit
let members: i64 = res["data"]["subscribers"].as_u64().unwrap_or_default() as i64; let members: i64 = res["data"]["subscribers"].as_u64().unwrap_or_default() as i64;
let active: i64 = res["data"]["accounts_active"].as_u64().unwrap_or_default() as i64; let active: i64 = res["data"]["accounts_active"].as_u64().unwrap_or_default() as i64;
// Grab creation date as unix timestamp
let created_unix = res["data"]["created"].as_f64().unwrap_or(0.0).round() as i64;
let created = OffsetDateTime::from_unix_timestamp(created_unix).unwrap_or(OffsetDateTime::UNIX_EPOCH);
// Fetch subreddit icon either from the community_icon or icon_img value // Fetch subreddit icon either from the community_icon or icon_img value
let community_icon: &str = res["data"]["community_icon"].as_str().unwrap_or_default(); let community_icon: &str = res["data"]["community_icon"].as_str().unwrap_or_default();
let icon = if community_icon.is_empty() { val(&res, "icon_img") } else { community_icon.to_string() }; let icon = if community_icon.is_empty() { val(&res, "icon_img") } else { community_icon.to_string() };
// Fetch subreddit banner either from the banner_background_image or banner_img value
let banner_background_image: &str = res["data"]["banner_background_image"].as_str().unwrap_or_default();
let banner = if banner_background_image.is_empty() { val(&res, "banner_img") } else { banner_background_image.to_string() };
Ok(Subreddit { Ok(Subreddit {
name: val(&res, "display_name"), name: val(&res, "display_name"),
title: val(&res, "title"), title: val(&res, "title"),
@ -476,8 +487,10 @@ async fn subreddit(sub: &str, quarantined: bool) -> Result<Subreddit, String> {
info: rewrite_urls(&val(&res, "description_html")), info: rewrite_urls(&val(&res, "description_html")),
// moderators: moderators_list(sub, quarantined).await.unwrap_or_default(), // moderators: moderators_list(sub, quarantined).await.unwrap_or_default(),
icon: format_url(&icon), icon: format_url(&icon),
banner: format_url(&banner),
members: format_num(members), members: format_num(members),
active: format_num(active), active: format_num(active),
created: created.format(format_description!("[month repr:short] [day] '[year repr:last_two]")).unwrap_or_default(),
wiki: res["data"]["wiki_enabled"].as_bool().unwrap_or_default(), wiki: res["data"]["wiki_enabled"].as_bool().unwrap_or_default(),
nsfw: res["data"]["over18"].as_bool().unwrap_or_default(), nsfw: res["data"]["over18"].as_bool().unwrap_or_default(),
}) })

View File

@ -6,6 +6,7 @@ use crate::server::RequestExt;
use crate::utils::{error, filter_posts, format_url, get_filters, nsfw_landing, param, setting, template, Post, Preferences, User}; use crate::utils::{error, filter_posts, format_url, get_filters, nsfw_landing, param, setting, template, Post, Preferences, User};
use crate::{config, utils}; use crate::{config, utils};
use hyper::{Body, Request, Response}; use hyper::{Body, Request, Response};
use log::trace;
use rinja::Template; use rinja::Template;
use time::{macros::format_description, OffsetDateTime}; use time::{macros::format_description, OffsetDateTime};
@ -111,6 +112,7 @@ async fn user(name: &str) -> Result<User, String> {
// Send a request to the url // Send a request to the url
json(path, false).await.map(|res| { json(path, false).await.map(|res| {
trace!("User info from r/{} : {}", name, res["data"]);
// Grab creation date as unix timestamp // Grab creation date as unix timestamp
let created_unix = res["data"]["created"].as_f64().unwrap_or(0.0).round() as i64; let created_unix = res["data"]["created"].as_f64().unwrap_or(0.0).round() as i64;
let created = OffsetDateTime::from_unix_timestamp(created_unix).unwrap_or(OffsetDateTime::UNIX_EPOCH); let created = OffsetDateTime::from_unix_timestamp(created_unix).unwrap_or(OffsetDateTime::UNIX_EPOCH);

View File

@ -585,8 +585,10 @@ pub struct Subreddit {
pub info: String, pub info: String,
// pub moderators: Vec<String>, // pub moderators: Vec<String>,
pub icon: String, pub icon: String,
pub banner: String,
pub members: (String, String), pub members: (String, String),
pub active: (String, String), pub active: (String, String),
pub created: String,
pub wiki: bool, pub wiki: bool,
pub nsfw: bool, pub nsfw: bool,
} }
@ -617,6 +619,7 @@ pub struct Preferences {
pub hide_hls_notification: String, pub hide_hls_notification: String,
pub video_quality: String, pub video_quality: String,
pub hide_sidebar_and_summary: String, pub hide_sidebar_and_summary: String,
pub hide_banner: String,
pub use_hls: String, pub use_hls: String,
pub ffmpeg_video_downloads: String, pub ffmpeg_video_downloads: String,
pub autoplay_videos: String, pub autoplay_videos: String,
@ -670,6 +673,7 @@ impl Preferences {
blur_spoiler: setting(req, "blur_spoiler"), blur_spoiler: setting(req, "blur_spoiler"),
show_nsfw: setting(req, "show_nsfw"), show_nsfw: setting(req, "show_nsfw"),
hide_sidebar_and_summary: setting(req, "hide_sidebar_and_summary"), hide_sidebar_and_summary: setting(req, "hide_sidebar_and_summary"),
hide_banner: setting(req, "hide_banner"),
blur_nsfw: setting(req, "blur_nsfw"), blur_nsfw: setting(req, "blur_nsfw"),
use_hls: setting(req, "use_hls"), use_hls: setting(req, "use_hls"),
ffmpeg_video_downloads: setting(req, "ffmpeg_video_downloads"), ffmpeg_video_downloads: setting(req, "ffmpeg_video_downloads"),

View File

@ -499,7 +499,7 @@ aside {
height: 100px; height: 100px;
border: 2px solid var(--accent); border: 2px solid var(--accent);
border-radius: 100%; border-radius: 100%;
padding: 10px; padding: 0px;
margin: 10px; margin: 10px;
} }
@ -531,11 +531,14 @@ aside {
grid-template-columns: auto 4fr 1fr; grid-template-columns: auto 4fr 1fr;
} }
#user_details, #user_details {
#sub_details {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
} }
#sub_details {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
@media screen and (max-width: 279px) { @media screen and (max-width: 279px) {
#sub_actions { display: unset; } #sub_actions { display: unset; }
} }
@ -547,13 +550,9 @@ aside {
/* Subscriptions */ /* Subscriptions */
#sub_subscription,
#user_subscription, #user_subscription,
#sub_filter,
#user_filter, #user_filter,
#sub_quicklist,
#user_quicklist, #user_quicklist,
#sub_rss,
#user_rss { #user_rss {
margin-top: 20px; margin-top: 20px;
} }

View File

@ -65,6 +65,11 @@
<input type="hidden" value="off" name="hide_sidebar_and_summary"> <input type="hidden" value="off" name="hide_sidebar_and_summary">
<input type="checkbox" name="hide_sidebar_and_summary" {% if prefs.hide_sidebar_and_summary == "on" %}checked{% endif %}> <input type="checkbox" name="hide_sidebar_and_summary" {% if prefs.hide_sidebar_and_summary == "on" %}checked{% endif %}>
</div> </div>
<div class="prefs-group">
<label for="hide_banner">Hide subreddit banners</label>
<input type="hidden" value="off" name="hide_banner">
<input type="checkbox" name="hide_banner" {% if prefs.hide_banner == "on" %}checked{% endif %}>
</div>
<div class="prefs-group"> <div class="prefs-group">
<label for="disable_visit_reddit_confirmation">Do not confirm before visiting content on Reddit</label> <label for="disable_visit_reddit_confirmation">Do not confirm before visiting content on Reddit</label>
<input type="hidden" value="off" name="disable_visit_reddit_confirmation"> <input type="hidden" value="off" name="disable_visit_reddit_confirmation">
@ -73,12 +78,6 @@
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>Content</legend> <legend>Content</legend>
<div class="prefs-group">
<label for="video_quality">Video quality:</label>
<select name="video_quality" id="video_quality">
{% call utils::options(prefs.video_quality, ["best", "medium", "worst"], "best") %}
</select>
</div>
<div class="prefs-group"> <div class="prefs-group">
<label for="post_sort" title="Applies only to subreddit feeds">Default subreddit post sort:</label> <label for="post_sort" title="Applies only to subreddit feeds">Default subreddit post sort:</label>
<select name="post_sort"> <select name="post_sort">
@ -121,6 +120,12 @@
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>Media</legend> <legend>Media</legend>
<div class="prefs-group">
<label for="video_quality">Video quality:</label>
<select name="video_quality" id="video_quality">
{% call utils::options(prefs.video_quality, ["best", "medium", "worst"], "best") %}
</select>
</div>
<div class="prefs-group"> <div class="prefs-group">
<label for="autoplay_videos">Autoplay videos</label> <label for="autoplay_videos">Autoplay videos</label>
<input type="hidden" value="off" name="autoplay_videos"> <input type="hidden" value="off" name="autoplay_videos">
@ -158,7 +163,7 @@
</form> </form>
<div id="settings_note"> <div id="settings_note">
<p><b>Note:</b> settings and subscriptions are saved in browser cookies. Clearing your cookies will reset them.</p><br> <p><b>Note:</b> settings and subscriptions are saved in browser cookies. Clearing your cookies will reset them.</p><br>
<p>You can restore your current settings and subscriptions after clearing your cookies using <a href="/settings/restore/?theme={{ prefs.theme }}&mascot={{ prefs.mascot }}&redsunlib_colorway={{ prefs.redsunlib_colorway }}&front_page={{ prefs.front_page }}&layout={{ prefs.layout }}&wide={{ prefs.wide }}&post_sort={{ prefs.post_sort }}&comment_sort={{ prefs.comment_sort }}&show_nsfw={{ prefs.show_nsfw }}&use_hls={{ prefs.use_hls }}&ffmpeg_video_downloads={{ prefs.ffmpeg_video_downloads }}&hide_hls_notification={{ prefs.hide_hls_notification }}&hide_awards={{ prefs.hide_awards }}&fixed_navbar={{ prefs.fixed_navbar }}&hide_sidebar_and_summary={{ prefs.hide_sidebar_and_summary}}&subscriptions={{ prefs.subscriptions.join("%2B") }}&filters={{ prefs.filters.join("%2B") }}&quicklist={{ prefs.quicklist.join("%2B") }}">this link</a>.</p> <p>You can restore your current settings and subscriptions after clearing your cookies using <a href="/settings/restore/?theme={{ prefs.theme }}&mascot={{ prefs.mascot }}&redsunlib_colorway={{ prefs.redsunlib_colorway }}&front_page={{ prefs.front_page }}&layout={{ prefs.layout }}&wide={{ prefs.wide }}&post_sort={{ prefs.post_sort }}&comment_sort={{ prefs.comment_sort }}&show_nsfw={{ prefs.show_nsfw }}&use_hls={{ prefs.use_hls }}&ffmpeg_video_downloads={{ prefs.ffmpeg_video_downloads }}&hide_hls_notification={{ prefs.hide_hls_notification }}&hide_awards={{ prefs.hide_awards }}&fixed_navbar={{ prefs.fixed_navbar }}&hide_sidebar_and_summary={{ prefs.hide_sidebar_and_summary}}&hide_banner={{ prefs.hide_banner}}&subscriptions={{ prefs.subscriptions.join("%2B") }}&filters={{ prefs.filters.join("%2B") }}&quicklist={{ prefs.quicklist.join("%2B") }}">this link</a>.</p>
</div> </div>
{% if prefs.subscriptions.len() > 0 %} {% if prefs.subscriptions.len() > 0 %}
<div class="prefs" id="settings_subs"> <div class="prefs" id="settings_subs">

View File

@ -100,8 +100,16 @@
<a href="/r/{{ sub.name }}/wiki/index">Wiki</a> <a href="/r/{{ sub.name }}/wiki/index">Wiki</a>
</div> </div>
{% endif %} {% endif %}
<div id="sub_meta"> {% if prefs.hide_banner != "on" %}
{% block head %}
{% call super() %}
<link rel="preload" as="image" href="{{ sub.banner }}">
{% endblock %}
{% endif %}
<div {% if prefs.hide_banner != "on" %}style="background: linear-gradient(to bottom, rgba(255,255,255,0) 10%, var(--outside)), url({{ sub.banner }});background-size: 100%;background-size: cover;background-position: center center;"{% endif %} id="iconbanner">
<img loading="lazy" id="sub_icon" src="{{ sub.icon }}" alt="Icon for r/{{ sub.name }}"> <img loading="lazy" id="sub_icon" src="{{ sub.icon }}" alt="Icon for r/{{ sub.name }}">
</div>
<div id="sub_meta">
<h1 id="sub_title">{{ sub.title }}</h1> <h1 id="sub_title">{{ sub.title }}</h1>
<p id="sub_name">r/{{ sub.name }}</p> <p id="sub_name">r/{{ sub.name }}</p>
{% if crate::utils::enable_rss() %} {% if crate::utils::enable_rss() %}
@ -120,9 +128,12 @@
<div id="sub_details"> <div id="sub_details">
<label>Members</label> <label>Members</label>
<label>Active</label> <label>Active</label>
<label>Created</label>
<div title="{{ sub.members.1 }}">{{ sub.members.0 }}</div> <div title="{{ sub.members.1 }}">{{ sub.members.0 }}</div>
<div title="{{ sub.active.1 }}">{{ sub.active.0 }}</div> <div title="{{ sub.active.1 }}">{{ sub.active.0 }}</div>
<div>{{ sub.created }}</div>
</div> </div>
<hr>
<div id="sub_actions"> <div id="sub_actions">
<div id="sub_subscription"> <div id="sub_subscription">
{% if prefs.subscriptions.contains(sub.name) %} {% if prefs.subscriptions.contains(sub.name) %}