Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
c15f305be0 | |||
222d216854 | |||
6d8aaba8bb | |||
6cf3748642 | |||
9c938c6210 | |||
a49d399f72 | |||
9178b50b73 | |||
b5d04f1a50 | |||
9e434e7db6 | |||
ab30b8bbec | |||
37d1939dc0 | |||
08a20b89a6 | |||
5d518cfc18 | |||
7e752b3d81 | |||
87729d0daa | |||
dc06ae3b29 | |||
225380b7d9 |
2
.github/workflows/docker-arm.yml
vendored
2
.github/workflows/docker-arm.yml
vendored
@ -33,6 +33,6 @@ jobs:
|
|||||||
file: ./Dockerfile.arm
|
file: ./Dockerfile.arm
|
||||||
platforms: linux/arm64
|
platforms: linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: spikecodes/libreddit:arm
|
tags: libreddit/libreddit:arm
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
2
.github/workflows/docker-armv7.yml
vendored
2
.github/workflows/docker-armv7.yml
vendored
@ -36,6 +36,6 @@ jobs:
|
|||||||
file: ./Dockerfile.armv7
|
file: ./Dockerfile.armv7
|
||||||
platforms: linux/arm/v7
|
platforms: linux/arm/v7
|
||||||
push: true
|
push: true
|
||||||
tags: spikecodes/libreddit:armv7
|
tags: libreddit/libreddit:armv7
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
8
.github/workflows/docker.yml
vendored
8
.github/workflows/docker.yml
vendored
@ -26,6 +26,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: Docker Hub Description
|
||||||
|
uses: peter-evans/dockerhub-description@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
repository: libreddit/libreddit
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
@ -33,6 +39,6 @@ jobs:
|
|||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
push: true
|
push: true
|
||||||
tags: spikecodes/libreddit:latest
|
tags: libreddit/libreddit:latest
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -664,7 +664,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libreddit"
|
name = "libreddit"
|
||||||
version = "0.25.0"
|
version = "0.25.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
@ -677,6 +677,7 @@ dependencies = [
|
|||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
"libflate",
|
"libflate",
|
||||||
"lipsum",
|
"lipsum",
|
||||||
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"regex",
|
"regex",
|
||||||
"route-recognizer",
|
"route-recognizer",
|
||||||
|
@ -3,7 +3,7 @@ name = "libreddit"
|
|||||||
description = " Alternative private front-end to Reddit"
|
description = " Alternative private front-end to Reddit"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
repository = "https://github.com/spikecodes/libreddit"
|
repository = "https://github.com/spikecodes/libreddit"
|
||||||
version = "0.25.0"
|
version = "0.25.3"
|
||||||
authors = ["spikecodes <19519553+spikecodes@users.noreply.github.com>"]
|
authors = ["spikecodes <19519553+spikecodes@users.noreply.github.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
@ -27,6 +27,12 @@ url = "2.3.1"
|
|||||||
rust-embed = { version = "6.4.2", features = ["include-exclude"] }
|
rust-embed = { version = "6.4.2", features = ["include-exclude"] }
|
||||||
libflate = "1.2.0"
|
libflate = "1.2.0"
|
||||||
brotli = { version = "3.3.4", features = ["std"] }
|
brotli = { version = "3.3.4", features = ["std"] }
|
||||||
|
once_cell = "1.16.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lipsum = "0.8.2"
|
lipsum = "0.8.2"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
codegen-units = 1
|
||||||
|
lto = true
|
||||||
|
strip = true
|
||||||
|
16
README.md
16
README.md
@ -39,7 +39,7 @@ Both files are part of the [libreddit-instances](https://github.com/libreddit/li
|
|||||||
|
|
||||||
# About
|
# About
|
||||||
|
|
||||||
Find Libreddit on 💬 [Matrix](https://matrix.to/#/#libreddit:kde.org), 🐋 [Docker](https://hub.docker.com/r/spikecodes/libreddit), :octocat: [GitHub](https://github.com/libreddit/libreddit), and 🦊 [GitLab](https://gitlab.com/spikecodes/libreddit).
|
Find Libreddit on 💬 [Matrix](https://matrix.to/#/#libreddit:kde.org), 🐋 [Docker](https://hub.docker.com/r/libreddit/libreddit), :octocat: [GitHub](https://github.com/libreddit/libreddit), and 🦊 [GitLab](https://gitlab.com/libreddit/libreddit).
|
||||||
|
|
||||||
## Built with
|
## Built with
|
||||||
|
|
||||||
@ -136,21 +136,21 @@ cargo install libreddit
|
|||||||
|
|
||||||
## 2) Docker
|
## 2) Docker
|
||||||
|
|
||||||
Deploy the [Docker image](https://hub.docker.com/r/spikecodes/libreddit) of Libreddit:
|
Deploy the [Docker image](https://hub.docker.com/r/libreddit/libreddit) of Libreddit:
|
||||||
```
|
```
|
||||||
docker pull spikecodes/libreddit
|
docker pull libreddit/libreddit
|
||||||
docker run -d --name libreddit -p 8080:8080 spikecodes/libreddit
|
docker run -d --name libreddit -p 8080:8080 libreddit/libreddit
|
||||||
```
|
```
|
||||||
|
|
||||||
Deploy using a different port (in this case, port 80):
|
Deploy using a different port (in this case, port 80):
|
||||||
```
|
```
|
||||||
docker pull spikecodes/libreddit
|
docker pull libreddit/libreddit
|
||||||
docker run -d --name libreddit -p 80:8080 spikecodes/libreddit
|
docker run -d --name libreddit -p 80:8080 libreddit/libreddit
|
||||||
```
|
```
|
||||||
|
|
||||||
To deploy on `arm64` platforms, simply replace `spikecodes/libreddit` in the commands above with `spikecodes/libreddit:arm`.
|
To deploy on `arm64` platforms, simply replace `libreddit/libreddit` in the commands above with `libreddit/libreddit:arm`.
|
||||||
|
|
||||||
To deploy on `armv7` platforms, simply replace `spikecodes/libreddit` in the commands above with `spikecodes/libreddit:armv7`.
|
To deploy on `armv7` platforms, simply replace `libreddit/libreddit` in the commands above with `libreddit/libreddit:armv7`.
|
||||||
|
|
||||||
## 3) AUR
|
## 3) AUR
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ async fn main() {
|
|||||||
Some("best" | "hot" | "new" | "top" | "rising" | "controversial") => subreddit::community(req).await,
|
Some("best" | "hot" | "new" | "top" | "rising" | "controversial") => subreddit::community(req).await,
|
||||||
|
|
||||||
// Short link for post
|
// Short link for post
|
||||||
Some(id) if (5..7).contains(&id.len()) => match canonical_path(format!("/{}", id)).await {
|
Some(id) if (5..8).contains(&id.len()) => match canonical_path(format!("/{}", id)).await {
|
||||||
Ok(path_opt) => match path_opt {
|
Ok(path_opt) => match path_opt {
|
||||||
Some(path) => Ok(redirect(path)),
|
Some(path) => Ok(redirect(path)),
|
||||||
None => error(req, "Post ID is invalid. It may point to a post on a community that has been banned.").await,
|
None => error(req, "Post ID is invalid. It may point to a post on a community that has been banned.").await,
|
||||||
|
@ -7,6 +7,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use hyper::{Body, Request, Response};
|
use hyper::{Body, Request, Response};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
// STRUCTS
|
// STRUCTS
|
||||||
struct SearchParams {
|
struct SearchParams {
|
||||||
@ -44,13 +46,18 @@ struct SearchTemplate {
|
|||||||
all_posts_filtered: bool,
|
all_posts_filtered: bool,
|
||||||
/// Whether all posts were hidden because they are NSFW (and user has disabled show NSFW)
|
/// Whether all posts were hidden because they are NSFW (and user has disabled show NSFW)
|
||||||
all_posts_hidden_nsfw: bool,
|
all_posts_hidden_nsfw: bool,
|
||||||
|
no_posts: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Regex matched against search queries to determine if they are reddit urls.
|
||||||
|
static REDDIT_URL_MATCH: Lazy<Regex> = Lazy::new(|| Regex::new(r"^https?://([^\./]+\.)*reddit.com/").unwrap());
|
||||||
|
|
||||||
// SERVICES
|
// SERVICES
|
||||||
pub async fn find(req: Request<Body>) -> Result<Response<Body>, String> {
|
pub async fn find(req: Request<Body>) -> Result<Response<Body>, String> {
|
||||||
let nsfw_results = if setting(&req, "show_nsfw") == "on" { "&include_over_18=on" } else { "" };
|
let nsfw_results = if setting(&req, "show_nsfw") == "on" { "&include_over_18=on" } else { "" };
|
||||||
let path = format!("{}.json?{}{}&raw_json=1", req.uri().path(), req.uri().query().unwrap_or_default(), nsfw_results);
|
let path = format!("{}.json?{}{}&raw_json=1", req.uri().path(), req.uri().query().unwrap_or_default(), nsfw_results);
|
||||||
let query = param(&path, "q").unwrap_or_default();
|
let mut query = param(&path, "q").unwrap_or_default();
|
||||||
|
query = REDDIT_URL_MATCH.replace(&query, "").to_string();
|
||||||
|
|
||||||
if query.is_empty() {
|
if query.is_empty() {
|
||||||
return Ok(redirect("/".to_string()));
|
return Ok(redirect("/".to_string()));
|
||||||
@ -103,12 +110,14 @@ pub async fn find(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
is_filtered: true,
|
is_filtered: true,
|
||||||
all_posts_filtered: false,
|
all_posts_filtered: false,
|
||||||
all_posts_hidden_nsfw: false,
|
all_posts_hidden_nsfw: false,
|
||||||
|
no_posts: false,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
match Post::fetch(&path, quarantined).await {
|
match Post::fetch(&path, quarantined).await {
|
||||||
Ok((mut posts, after)) => {
|
Ok((mut posts, after)) => {
|
||||||
let (_, all_posts_filtered) = filter_posts(&mut posts, &filters);
|
let (_, all_posts_filtered) = filter_posts(&mut posts, &filters);
|
||||||
let all_posts_hidden_nsfw = posts.iter().all(|p| p.flags.nsfw) && setting(&req, "show_nsfw") != "on";
|
let no_posts = posts.is_empty();
|
||||||
|
let all_posts_hidden_nsfw = !no_posts && (posts.iter().all(|p| p.flags.nsfw) && setting(&req, "show_nsfw") != "on");
|
||||||
template(SearchTemplate {
|
template(SearchTemplate {
|
||||||
posts,
|
posts,
|
||||||
subreddits,
|
subreddits,
|
||||||
@ -127,6 +136,7 @@ pub async fn find(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
is_filtered: false,
|
is_filtered: false,
|
||||||
all_posts_filtered,
|
all_posts_filtered,
|
||||||
all_posts_hidden_nsfw,
|
all_posts_hidden_nsfw,
|
||||||
|
no_posts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
|
@ -243,7 +243,7 @@ impl Server {
|
|||||||
match func.await {
|
match func.await {
|
||||||
Ok(mut res) => {
|
Ok(mut res) => {
|
||||||
res.headers_mut().extend(def_headers);
|
res.headers_mut().extend(def_headers);
|
||||||
let _ = compress_response(req_headers, &mut res).await;
|
let _ = compress_response(&req_headers, &mut res).await;
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
@ -282,7 +282,7 @@ async fn new_boilerplate(
|
|||||||
) -> Result<Response<Body>, String> {
|
) -> Result<Response<Body>, String> {
|
||||||
match Response::builder().status(status).body(body) {
|
match Response::builder().status(status).body(body) {
|
||||||
Ok(mut res) => {
|
Ok(mut res) => {
|
||||||
let _ = compress_response(req_headers, &mut res).await;
|
let _ = compress_response(&req_headers, &mut res).await;
|
||||||
|
|
||||||
res.headers_mut().extend(default_headers.clone());
|
res.headers_mut().extend(default_headers.clone());
|
||||||
Ok(res)
|
Ok(res)
|
||||||
@ -306,7 +306,8 @@ async fn new_boilerplate(
|
|||||||
/// Accept-Encoding: gzip, compress, br
|
/// Accept-Encoding: gzip, compress, br
|
||||||
/// Accept-Encoding: br;q=1.0, gzip;q=0.8, *;q=0.1
|
/// Accept-Encoding: br;q=1.0, gzip;q=0.8, *;q=0.1
|
||||||
/// ```
|
/// ```
|
||||||
fn determine_compressor(accept_encoding: &str) -> Option<CompressionType> {
|
#[cached]
|
||||||
|
fn determine_compressor(accept_encoding: String) -> Option<CompressionType> {
|
||||||
if accept_encoding.is_empty() {
|
if accept_encoding.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
@ -473,7 +474,7 @@ fn determine_compressor(accept_encoding: &str) -> Option<CompressionType> {
|
|||||||
///
|
///
|
||||||
/// This function logs errors to stderr, but only in debug mode. No information
|
/// This function logs errors to stderr, but only in debug mode. No information
|
||||||
/// is logged in release builds.
|
/// is logged in release builds.
|
||||||
async fn compress_response(req_headers: HeaderMap<header::HeaderValue>, res: &mut Response<Body>) -> Result<(), String> {
|
async fn compress_response(req_headers: &HeaderMap<header::HeaderValue>, res: &mut Response<Body>) -> Result<(), String> {
|
||||||
// Check if the data is eligible for compression.
|
// Check if the data is eligible for compression.
|
||||||
if let Some(hdr) = res.headers().get(header::CONTENT_TYPE) {
|
if let Some(hdr) = res.headers().get(header::CONTENT_TYPE) {
|
||||||
match from_utf8(hdr.as_bytes()) {
|
match from_utf8(hdr.as_bytes()) {
|
||||||
@ -503,30 +504,22 @@ async fn compress_response(req_headers: HeaderMap<header::HeaderValue>, res: &mu
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Quick and dirty closure for extracting a header from the request and
|
|
||||||
// returning it as a &str.
|
|
||||||
let get_req_header = |k: header::HeaderName| -> Option<&str> {
|
|
||||||
match req_headers.get(k) {
|
|
||||||
Some(hdr) => match from_utf8(hdr.as_bytes()) {
|
|
||||||
Ok(val) => Some(val),
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
Err(e) => {
|
|
||||||
dbg_msg!(e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
Err(_) => None,
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check to see which compressor is requested, and if we can use it.
|
// Check to see which compressor is requested, and if we can use it.
|
||||||
let accept_encoding: &str = match get_req_header(header::ACCEPT_ENCODING) {
|
let accept_encoding: String = match req_headers.get(header::ACCEPT_ENCODING) {
|
||||||
Some(val) => val,
|
|
||||||
None => return Ok(()), // Client requested no compression.
|
None => return Ok(()), // Client requested no compression.
|
||||||
|
|
||||||
|
Some(hdr) => match String::from_utf8(hdr.as_bytes().into()) {
|
||||||
|
Ok(val) => val,
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
Err(e) => {
|
||||||
|
dbg_msg!(e);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
Err(_) => return Ok(()),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let compressor: CompressionType = match determine_compressor(accept_encoding) {
|
let compressor: CompressionType = match determine_compressor(accept_encoding) {
|
||||||
@ -636,18 +629,18 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_determine_compressor() {
|
fn test_determine_compressor() {
|
||||||
// Single compressor given.
|
// Single compressor given.
|
||||||
assert_eq!(determine_compressor("unsupported"), None);
|
assert_eq!(determine_compressor("unsupported".to_string()), None);
|
||||||
assert_eq!(determine_compressor("gzip"), Some(CompressionType::Gzip));
|
assert_eq!(determine_compressor("gzip".to_string()), Some(CompressionType::Gzip));
|
||||||
assert_eq!(determine_compressor("*"), Some(DEFAULT_COMPRESSOR));
|
assert_eq!(determine_compressor("*".to_string()), Some(DEFAULT_COMPRESSOR));
|
||||||
|
|
||||||
// Multiple compressors.
|
// Multiple compressors.
|
||||||
assert_eq!(determine_compressor("gzip, br"), Some(CompressionType::Brotli));
|
assert_eq!(determine_compressor("gzip, br".to_string()), Some(CompressionType::Brotli));
|
||||||
assert_eq!(determine_compressor("gzip;q=0.8, br;q=0.3"), Some(CompressionType::Gzip));
|
assert_eq!(determine_compressor("gzip;q=0.8, br;q=0.3".to_string()), Some(CompressionType::Gzip));
|
||||||
assert_eq!(determine_compressor("br, gzip"), Some(CompressionType::Brotli));
|
assert_eq!(determine_compressor("br, gzip".to_string()), Some(CompressionType::Brotli));
|
||||||
assert_eq!(determine_compressor("br;q=0.3, gzip;q=0.4"), Some(CompressionType::Gzip));
|
assert_eq!(determine_compressor("br;q=0.3, gzip;q=0.4".to_string()), Some(CompressionType::Gzip));
|
||||||
|
|
||||||
// Invalid q-values.
|
// Invalid q-values.
|
||||||
assert_eq!(determine_compressor("gzip;q=NAN"), None);
|
assert_eq!(determine_compressor("gzip;q=NAN".to_string()), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -672,9 +665,9 @@ mod tests {
|
|||||||
] {
|
] {
|
||||||
// Determine what the expected encoding should be based on both the
|
// Determine what the expected encoding should be based on both the
|
||||||
// specific encodings we accept.
|
// specific encodings we accept.
|
||||||
let expected_encoding: CompressionType = match determine_compressor(accept_encoding) {
|
let expected_encoding: CompressionType = match determine_compressor(accept_encoding.to_string()) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => panic!("determine_compressor(accept_encoding) => None"),
|
None => panic!("determine_compressor(accept_encoding.to_string()) => None"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build headers with our Accept-Encoding.
|
// Build headers with our Accept-Encoding.
|
||||||
@ -691,8 +684,8 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Perform the compression.
|
// Perform the compression.
|
||||||
if let Err(e) = block_on(compress_response(req_headers, &mut res)) {
|
if let Err(e) = block_on(compress_response(&req_headers, &mut res)) {
|
||||||
panic!("compress_response(req_headers, &mut res) => Err(\"{}\")", e);
|
panic!("compress_response(&req_headers, &mut res) => Err(\"{}\")", e);
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the content was compressed, we expect the Content-Encoding
|
// If the content was compressed, we expect the Content-Encoding
|
||||||
@ -739,9 +732,8 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut decompressed = Vec::<u8>::new();
|
let mut decompressed = Vec::<u8>::new();
|
||||||
match io::copy(&mut decoder, &mut decompressed) {
|
if let Err(e) = io::copy(&mut decoder, &mut decompressed) {
|
||||||
Ok(_) => {}
|
panic!("{}", e);
|
||||||
Err(e) => panic!("{}", e),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(decompressed.eq(&expected_lorem_ipsum));
|
assert!(decompressed.eq(&expected_lorem_ipsum));
|
||||||
|
@ -26,6 +26,7 @@ struct SubredditTemplate {
|
|||||||
all_posts_filtered: bool,
|
all_posts_filtered: bool,
|
||||||
/// Whether all posts were hidden because they are NSFW (and user has disabled show NSFW)
|
/// Whether all posts were hidden because they are NSFW (and user has disabled show NSFW)
|
||||||
all_posts_hidden_nsfw: bool,
|
all_posts_hidden_nsfw: bool,
|
||||||
|
no_posts: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
@ -114,12 +115,14 @@ pub async fn community(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
is_filtered: true,
|
is_filtered: true,
|
||||||
all_posts_filtered: false,
|
all_posts_filtered: false,
|
||||||
all_posts_hidden_nsfw: false,
|
all_posts_hidden_nsfw: false,
|
||||||
|
no_posts: false,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
match Post::fetch(&path, quarantined).await {
|
match Post::fetch(&path, quarantined).await {
|
||||||
Ok((mut posts, after)) => {
|
Ok((mut posts, after)) => {
|
||||||
let (_, all_posts_filtered) = filter_posts(&mut posts, &filters);
|
let (_, all_posts_filtered) = filter_posts(&mut posts, &filters);
|
||||||
let all_posts_hidden_nsfw = posts.iter().all(|p| p.flags.nsfw) && setting(&req, "show_nsfw") != "on";
|
let no_posts = posts.is_empty();
|
||||||
|
let all_posts_hidden_nsfw = !no_posts && (posts.iter().all(|p| p.flags.nsfw) && setting(&req, "show_nsfw") != "on");
|
||||||
template(SubredditTemplate {
|
template(SubredditTemplate {
|
||||||
sub,
|
sub,
|
||||||
posts,
|
posts,
|
||||||
@ -131,6 +134,7 @@ pub async fn community(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
is_filtered: false,
|
is_filtered: false,
|
||||||
all_posts_filtered,
|
all_posts_filtered,
|
||||||
all_posts_hidden_nsfw,
|
all_posts_hidden_nsfw,
|
||||||
|
no_posts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(msg) => match msg.as_str() {
|
Err(msg) => match msg.as_str() {
|
||||||
|
@ -26,6 +26,7 @@ struct UserTemplate {
|
|||||||
all_posts_filtered: bool,
|
all_posts_filtered: bool,
|
||||||
/// Whether all posts were hidden because they are NSFW (and user has disabled show NSFW)
|
/// Whether all posts were hidden because they are NSFW (and user has disabled show NSFW)
|
||||||
all_posts_hidden_nsfw: bool,
|
all_posts_hidden_nsfw: bool,
|
||||||
|
no_posts: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTIONS
|
// FUNCTIONS
|
||||||
@ -61,13 +62,15 @@ pub async fn profile(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
is_filtered: true,
|
is_filtered: true,
|
||||||
all_posts_filtered: false,
|
all_posts_filtered: false,
|
||||||
all_posts_hidden_nsfw: false,
|
all_posts_hidden_nsfw: false,
|
||||||
|
no_posts: false,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// Request user posts/comments from Reddit
|
// Request user posts/comments from Reddit
|
||||||
match Post::fetch(&path, false).await {
|
match Post::fetch(&path, false).await {
|
||||||
Ok((mut posts, after)) => {
|
Ok((mut posts, after)) => {
|
||||||
let (_, all_posts_filtered) = filter_posts(&mut posts, &filters);
|
let (_, all_posts_filtered) = filter_posts(&mut posts, &filters);
|
||||||
let all_posts_hidden_nsfw = posts.iter().all(|p| p.flags.nsfw) && setting(&req, "show_nsfw") != "on";
|
let no_posts = posts.is_empty();
|
||||||
|
let all_posts_hidden_nsfw = !no_posts && (posts.iter().all(|p| p.flags.nsfw) && setting(&req, "show_nsfw") != "on");
|
||||||
template(UserTemplate {
|
template(UserTemplate {
|
||||||
user,
|
user,
|
||||||
posts,
|
posts,
|
||||||
@ -80,6 +83,7 @@ pub async fn profile(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
is_filtered: false,
|
is_filtered: false,
|
||||||
all_posts_filtered,
|
all_posts_filtered,
|
||||||
all_posts_hidden_nsfw,
|
all_posts_hidden_nsfw,
|
||||||
|
no_posts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// If there is an error show error page
|
// If there is an error show error page
|
||||||
|
@ -1118,22 +1118,16 @@ summary.comment_data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.prefs {
|
.prefs {
|
||||||
display: flex;
|
padding: 10px 20px 20px;
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 20px;
|
|
||||||
background: var(--post);
|
background: var(--post);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prefs > div {
|
.prefs fieldset {
|
||||||
display: flex;
|
border: 0;
|
||||||
justify-content: space-between;
|
padding: 10px 0;
|
||||||
width: 100%;
|
margin: 0 0 5px;
|
||||||
height: 35px;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 7px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.prefs legend {
|
.prefs legend {
|
||||||
@ -1141,11 +1135,25 @@ summary.comment_data {
|
|||||||
border-bottom: 1px solid var(--highlighted);
|
border-bottom: 1px solid var(--highlighted);
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
margin-bottom: 7px;
|
||||||
|
width: 100%;
|
||||||
|
float: left; /* places the legend inside the (invisible) border, instead of vertically centered on top border*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.prefs legend:not(:first-child) {
|
.prefs-group {
|
||||||
padding-top: 10px;
|
display: flex;
|
||||||
margin-top: 15px;
|
width: 100%;
|
||||||
|
height: 35px;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prefs-group > *:not(:last-child) {
|
||||||
|
margin-right: 1ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prefs-group > *:last-child {
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prefs select {
|
.prefs select {
|
||||||
@ -1163,7 +1171,8 @@ aside.prefs {
|
|||||||
background: var(--highlighted);
|
background: var(--highlighted);
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-top: 20px;
|
margin-top: 5px;
|
||||||
|
width: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="submit"] {
|
input[type="submit"] {
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<a id="code" href="https://github.com/spikecodes/libreddit">
|
<a id="code" href="https://github.com/libreddit/libreddit" target="_blank" rel="noopener noreferrer">
|
||||||
<span>code</span>
|
<span>code</span>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<title>code</title>
|
<title>code</title>
|
||||||
|
@ -61,6 +61,10 @@
|
|||||||
<span class="listing_warn">All posts are hidden because they are NSFW. Enable "Show NSFW posts" in settings to view.</span>
|
<span class="listing_warn">All posts are hidden because they are NSFW. Enable "Show NSFW posts" in settings to view.</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if no_posts %}
|
||||||
|
<center>No posts were found.</center>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if all_posts_filtered %}
|
{% if all_posts_filtered %}
|
||||||
<span class="listing_warn">(All content on this page has been filtered)</span>
|
<span class="listing_warn">(All content on this page has been filtered)</span>
|
||||||
{% else if is_filtered %}
|
{% else if is_filtered %}
|
||||||
|
@ -11,74 +11,79 @@
|
|||||||
<div id="settings">
|
<div id="settings">
|
||||||
<form action="/settings" method="POST">
|
<form action="/settings" method="POST">
|
||||||
<div class="prefs">
|
<div class="prefs">
|
||||||
<legend>Appearance</legend>
|
<fieldset>
|
||||||
<div id="theme">
|
<legend>Appearance</legend>
|
||||||
<label for="theme">Theme:</label>
|
<div class="prefs-group">
|
||||||
<select name="theme">
|
<label for="theme">Theme:</label>
|
||||||
{% call utils::options(prefs.theme, prefs.available_themes, "system") %}
|
<select name="theme" id="theme">
|
||||||
</select>
|
{% call utils::options(prefs.theme, prefs.available_themes, "system") %}
|
||||||
</div>
|
</select>
|
||||||
<legend>Interface</legend>
|
</div>
|
||||||
<div id="front_page">
|
</fieldset>
|
||||||
<label for="front_page">Front page:</label>
|
<fieldset>
|
||||||
<select name="front_page">
|
<legend>Interface</legend>
|
||||||
{% call utils::options(prefs.front_page, ["default", "popular", "all"], "default") %}
|
<div class="prefs-group">
|
||||||
</select>
|
<label for="front_page">Front page:</label>
|
||||||
</div>
|
<select name="front_page" id="front_page">
|
||||||
<div id="layout">
|
{% call utils::options(prefs.front_page, ["default", "popular", "all"], "default") %}
|
||||||
<label for="layout">Layout:</label>
|
</select>
|
||||||
<select name="layout">
|
</div>
|
||||||
{% call utils::options(prefs.layout, ["card", "clean", "compact"], "card") %}
|
<div class="prefs-group">
|
||||||
</select>
|
<label for="layout">Layout:</label>
|
||||||
</div>
|
<select name="layout" id="layout">
|
||||||
<div id="wide">
|
{% call utils::options(prefs.layout, ["card", "clean", "compact"], "card") %}
|
||||||
<label for="wide">Wide UI:</label>
|
</select>
|
||||||
<input type="hidden" value="off" name="wide">
|
</div>
|
||||||
<input type="checkbox" name="wide" {% if prefs.wide == "on" %}checked{% endif %}>
|
<div class="prefs-group">
|
||||||
</div>
|
<label for="wide">Wide UI:</label>
|
||||||
<legend>Content</legend>
|
<input type="hidden" value="off" name="wide">
|
||||||
<div id="post_sort">
|
<input type="checkbox" name="wide" id="wide" {% if prefs.wide == "on" %}checked{% endif %}>
|
||||||
<label for="post_sort" title="Applies only to subreddit feeds">Default subreddit post sort:</label>
|
</div>
|
||||||
<select name="post_sort">
|
</fieldset>
|
||||||
{% call utils::options(prefs.post_sort, ["hot", "new", "top", "rising", "controversial"], "hot") %}
|
<fieldset>
|
||||||
</select>
|
<legend>Content</legend>
|
||||||
</div>
|
<div class="prefs-group">
|
||||||
<div id="comment_sort">
|
<label for="post_sort" title="Applies only to subreddit feeds">Default subreddit post sort:</label>
|
||||||
<label for="comment_sort">Default comment sort:</label>
|
<select name="post_sort">
|
||||||
<select name="comment_sort">
|
{% call utils::options(prefs.post_sort, ["hot", "new", "top", "rising", "controversial"], "hot") %}
|
||||||
{% call utils::options(prefs.comment_sort, ["confidence", "top", "new", "controversial", "old"], "confidence") %}
|
</select>
|
||||||
</select>
|
</div>
|
||||||
</div>
|
<div class="prefs-group">
|
||||||
<div id="show_nsfw">
|
<label for="comment_sort">Default comment sort:</label>
|
||||||
<label for="show_nsfw">Show NSFW posts:</label>
|
<select name="comment_sort" id="comment_sort">
|
||||||
<input type="hidden" value="off" name="show_nsfw">
|
{% call utils::options(prefs.comment_sort, ["confidence", "top", "new", "controversial", "old"], "confidence") %}
|
||||||
<input type="checkbox" name="show_nsfw" {% if prefs.show_nsfw == "on" %}checked{% endif %}>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="blur_nsfw">
|
<div class="prefs-group">
|
||||||
<label for="blur_nsfw">Blur NSFW previews:</label>
|
<label for="show_nsfw">Show NSFW posts:</label>
|
||||||
<input type="hidden" value="off" name="blur_nsfw">
|
<input type="hidden" value="off" name="show_nsfw">
|
||||||
<input type="checkbox" name="blur_nsfw" {% if prefs.blur_nsfw == "on" %}checked{% endif %}>
|
<input type="checkbox" name="show_nsfw" id="show_nsfw" {% if prefs.show_nsfw == "on" %}checked{% endif %}>
|
||||||
</div>
|
</div>
|
||||||
<div id="autoplay_videos">
|
<div class="prefs-group">
|
||||||
<label for="autoplay_videos">Autoplay videos</label>
|
<label for="blur_nsfw">Blur NSFW previews:</label>
|
||||||
<input type="hidden" value="off" name="autoplay_videos">
|
<input type="hidden" value="off" name="blur_nsfw">
|
||||||
<input type="checkbox" name="autoplay_videos" {% if prefs.autoplay_videos == "on" %}checked{% endif %}>
|
<input type="checkbox" name="blur_nsfw" id="blur_nsfw" {% if prefs.blur_nsfw == "on" %}checked{% endif %}>
|
||||||
</div>
|
</div>
|
||||||
<div id="use_hls">
|
<div class="prefs-group">
|
||||||
<label for="use_hls">Use HLS for videos
|
<label for="autoplay_videos">Autoplay videos</label>
|
||||||
|
<input type="hidden" value="off" name="autoplay_videos">
|
||||||
|
<input type="checkbox" name="autoplay_videos" id="autoplay_videos" {% if prefs.autoplay_videos == "on" %}checked{% endif %}>
|
||||||
|
</div>
|
||||||
|
<div class="prefs-group">
|
||||||
|
<label for="use_hls">Use HLS for videos</label>
|
||||||
<details id="feeds">
|
<details id="feeds">
|
||||||
<summary>Why?</summary>
|
<summary>Why?</summary>
|
||||||
<div id="feed_list" class="helper">Reddit videos require JavaScript (via HLS.js) to be enabled to be played with audio. Therefore, this toggle lets you either use Libreddit JS-free or utilize this feature.</div>
|
<div id="feed_list" class="helper">Reddit videos require JavaScript (via HLS.js) to be enabled to be played with audio. Therefore, this toggle lets you either use Libreddit JS-free or utilize this feature.</div>
|
||||||
</details>
|
</details>
|
||||||
</label>
|
<input type="hidden" value="off" name="use_hls">
|
||||||
<input type="hidden" value="off" name="use_hls">
|
<input type="checkbox" name="use_hls" id="use_hls" {% if prefs.use_hls == "on" %}checked{% endif %}>
|
||||||
<input type="checkbox" name="use_hls" {% if prefs.use_hls == "on" %}checked{% endif %}>
|
</div>
|
||||||
</div>
|
<div class="prefs-group">
|
||||||
<div id="hide_hls_notification">
|
<label for="hide_hls_notification">Hide notification about possible HLS usage</label>
|
||||||
<label for="hide_hls_notification">Hide notification about possible HLS usage</label>
|
<input type="hidden" value="off" name="hide_hls_notification">
|
||||||
<input type="hidden" value="off" name="hide_hls_notification">
|
<input type="checkbox" name="hide_hls_notification" id="hide_hls_notification" {% if prefs.hide_hls_notification == "on" %}checked{% endif %}>
|
||||||
<input type="checkbox" name="hide_hls_notification" {% if prefs.hide_hls_notification == "on" %}checked{% endif %}>
|
</div>
|
||||||
</div>
|
</fieldset>
|
||||||
<input id="save" type="submit" value="Save">
|
<input id="save" type="submit" value="Save">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -50,6 +50,10 @@
|
|||||||
<center>All posts are hidden because they are NSFW. Enable "Show NSFW posts" in settings to view.</center>
|
<center>All posts are hidden because they are NSFW. Enable "Show NSFW posts" in settings to view.</center>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if no_posts %}
|
||||||
|
<center>No posts were found.</center>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if all_posts_filtered %}
|
{% if all_posts_filtered %}
|
||||||
<center>(All content on this page has been filtered)</center>
|
<center>(All content on this page has been filtered)</center>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -36,6 +36,10 @@
|
|||||||
<center>All posts are hidden because they are NSFW. Enable "Show NSFW posts" in settings to view.</center>
|
<center>All posts are hidden because they are NSFW. Enable "Show NSFW posts" in settings to view.</center>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if no_posts %}
|
||||||
|
<center>No posts were found.</center>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if all_posts_filtered %}
|
{% if all_posts_filtered %}
|
||||||
<center>(All content on this page has been filtered)</center>
|
<center>(All content on this page has been filtered)</center>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -115,7 +115,7 @@
|
|||||||
{% if prefs.use_hls == "on" && !post.media.alt_url.is_empty() %}
|
{% if prefs.use_hls == "on" && !post.media.alt_url.is_empty() %}
|
||||||
<script src="/hls.min.js"></script>
|
<script src="/hls.min.js"></script>
|
||||||
<div class="post_media_content">
|
<div class="post_media_content">
|
||||||
<video class="post_media_video short {% if prefs.autoplay_videos == "on" %}hls_autoplay{% endif %}" width="{{ post.media.width }}" height="{{ post.media.height }}" poster="{{ post.media.poster }}" preload="none" controls>
|
<video class="post_media_video short {% if prefs.autoplay_videos == "on" %}hls_autoplay{% endif %}" {% if post.media.width > 0 && post.media.height > 0 %}width="{{ post.media.width }}" height="{{ post.media.height }}"{% endif %} poster="{{ post.media.poster }}" preload="none" controls>
|
||||||
<source src="{{ post.media.alt_url }}" type="application/vnd.apple.mpegurl" />
|
<source src="{{ post.media.alt_url }}" type="application/vnd.apple.mpegurl" />
|
||||||
<source src="{{ post.media.url }}" type="video/mp4" />
|
<source src="{{ post.media.url }}" type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
@ -213,19 +213,19 @@
|
|||||||
</div>
|
</div>
|
||||||
{% else if (prefs.layout.is_empty() || prefs.layout == "card") && post.post_type == "gif" %}
|
{% else if (prefs.layout.is_empty() || prefs.layout == "card") && post.post_type == "gif" %}
|
||||||
<div class="post_media_content">
|
<div class="post_media_content">
|
||||||
<video class="post_media_video short {%if post.flags.nsfw && prefs.blur_nsfw=="on" %}post_nsfw_blur{% endif %}" src="{{ post.media.url }}" width="{{ post.media.width }}" height="{{ post.media.height }}" poster="{{ post.media.poster }}" preload="none" controls loop {% if prefs.autoplay_videos == "on" %}autoplay{% endif %}><a href={{ post.media.url }}>Video</a></video>
|
<video class="post_media_video short {%if post.flags.nsfw && prefs.blur_nsfw=="on" %}post_nsfw_blur{% endif %}" src="{{ post.media.url }}" {% if post.media.width > 0 && post.media.height > 0 %}width="{{ post.media.width }}" height="{{ post.media.height }}"{% endif %} poster="{{ post.media.poster }}" preload="none" controls loop {% if prefs.autoplay_videos == "on" %}autoplay{% endif %}><a href={{ post.media.url }}>Video</a></video>
|
||||||
</div>
|
</div>
|
||||||
{% else if (prefs.layout.is_empty() || prefs.layout == "card") && post.post_type == "video" %}
|
{% else if (prefs.layout.is_empty() || prefs.layout == "card") && post.post_type == "video" %}
|
||||||
{% if prefs.use_hls == "on" && !post.media.alt_url.is_empty() %}
|
{% if prefs.use_hls == "on" && !post.media.alt_url.is_empty() %}
|
||||||
<div class="post_media_content">
|
<div class="post_media_content">
|
||||||
<video class="post_media_video short {%if post.flags.nsfw && prefs.blur_nsfw=="on" %}post_nsfw_blur{% endif %} {% if prefs.autoplay_videos == "on" %}hls_autoplay{% endif %}" width="{{ post.media.width }}" height="{{ post.media.height }}" poster="{{ post.media.poster }}" controls preload="none">
|
<video class="post_media_video short {%if post.flags.nsfw && prefs.blur_nsfw=="on" %}post_nsfw_blur{% endif %} {% if prefs.autoplay_videos == "on" %}hls_autoplay{% endif %}" {% if post.media.width > 0 && post.media.height > 0 %}width="{{ post.media.width }}" height="{{ post.media.height }}"{% endif %} poster="{{ post.media.poster }}" controls preload="none">
|
||||||
<source src="{{ post.media.alt_url }}" type="application/vnd.apple.mpegurl" />
|
<source src="{{ post.media.alt_url }}" type="application/vnd.apple.mpegurl" />
|
||||||
<source src="{{ post.media.url }}" type="video/mp4" />
|
<source src="{{ post.media.url }}" type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="post_media_content">
|
<div class="post_media_content">
|
||||||
<video class="post_media_video short {%if post.flags.nsfw && prefs.blur_nsfw=="on" %}post_nsfw_blur{% endif %}" src="{{ post.media.url }}" width="{{ post.media.width }}" height="{{ post.media.height }}" poster="{{ post.media.poster }}" preload="none" controls {% if prefs.autoplay_videos == "on" %}autoplay{% endif %}><a href={{ post.media.url }}>Video</a></video>
|
<video class="post_media_video short {%if post.flags.nsfw && prefs.blur_nsfw=="on" %}post_nsfw_blur{% endif %}" src="{{ post.media.url }}" {% if post.media.width > 0 && post.media.height > 0 %}width="{{ post.media.width }}" height="{{ post.media.height }}"{% endif %} poster="{{ post.media.poster }}" preload="none" controls {% if prefs.autoplay_videos == "on" %}autoplay{% endif %}><a href={{ post.media.url }}>Video</a></video>
|
||||||
</div>
|
</div>
|
||||||
{% call render_hls_notification(format!("{}%23{}", &self.url[1..].replace("&", "%26").replace("+", "%2B"), post.id)) %}
|
{% call render_hls_notification(format!("{}%23{}", &self.url[1..].replace("&", "%26").replace("+", "%2B"), post.id)) %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Reference in New Issue
Block a user