add: hide_social_follows setting
This commit is contained in:
parent
e78c43ab62
commit
a337e0c7c1
11 changed files with 179 additions and 96 deletions
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "tetratto-core"
|
||||
description = "The core behind Tetratto"
|
||||
version = "12.0.1"
|
||||
version = "12.0.2"
|
||||
edition = "2024"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
|
@ -18,7 +18,7 @@ default = ["database", "types", "sdk"]
|
|||
pathbufd = "0.1.4"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
toml = "0.9.2"
|
||||
tetratto-shared = { version = "12.0.0", path = "../shared" }
|
||||
tetratto-shared = { version = "12.0.6", path = "../shared" }
|
||||
tetratto-l10n = { version = "12.0.0", path = "../l10n" }
|
||||
serde_json = "1.0.141"
|
||||
totp-rs = { version = "5.7.0", features = ["qr", "gen_secret"], optional = true }
|
||||
|
@ -35,6 +35,4 @@ oiseau = { version = "0.1.2", default-features = false, features = [
|
|||
"redis",
|
||||
], optional = true }
|
||||
paste = { version = "1.0.15", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.46.1", features = ["macros", "rt-multi-thread"] }
|
||||
|
|
97
crates/core/src/html.rs
Normal file
97
crates/core/src/html.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
fs::{exists, read_to_string, write},
|
||||
sync::LazyLock,
|
||||
};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use pathbufd::PathBufD;
|
||||
|
||||
/// A container for all loaded icons.
|
||||
pub static ICONS: LazyLock<RwLock<HashMap<String, String>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
/// Pull an icon given its name and insert it into [`ICONS`].
|
||||
pub async fn pull_icon(icon: &str, icons_dir: &str) {
|
||||
let writer = &mut ICONS.write().await;
|
||||
|
||||
let icon_url = format!(
|
||||
"https://raw.githubusercontent.com/lucide-icons/lucide/refs/heads/main/icons/{icon}.svg"
|
||||
);
|
||||
|
||||
let file_path = PathBufD::current().extend(&[icons_dir, &format!("{icon}.svg")]);
|
||||
|
||||
if exists(&file_path).unwrap_or(false) {
|
||||
writer.insert(icon.to_string(), read_to_string(&file_path).unwrap());
|
||||
return;
|
||||
}
|
||||
|
||||
println!("download icon: {icon}");
|
||||
let svg = reqwest::get(icon_url)
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap()
|
||||
.replace("\n", "");
|
||||
|
||||
write(&file_path, &svg).unwrap();
|
||||
writer.insert(icon.to_string(), svg);
|
||||
}
|
||||
|
||||
/// Read a string and pull all icons found within it.
|
||||
pub async fn pull_icons(mut input: String, icon_dir: &str) -> String {
|
||||
// icon (with class)
|
||||
let icon_with_class =
|
||||
regex::Regex::new("(\\{\\{)\\s*(icon)\\s*(.*?)\\s*c\\((.*?)\\)\\s*(\\}\\})").unwrap();
|
||||
|
||||
for cap in icon_with_class.captures_iter(&input.clone()) {
|
||||
let cap_str = &cap.get(3).unwrap().as_str().replace("\"", "");
|
||||
let icon = &(if cap_str.contains(" }}") {
|
||||
cap_str.split(" }}").next().unwrap().to_string()
|
||||
} else {
|
||||
cap_str.to_string()
|
||||
});
|
||||
|
||||
pull_icon(icon, icon_dir).await;
|
||||
|
||||
let reader = ICONS.read().await;
|
||||
let icon_text = reader.get(icon).unwrap().replace(
|
||||
"<svg",
|
||||
&format!("<svg class=\"icon {}\"", cap.get(4).unwrap().as_str()),
|
||||
);
|
||||
|
||||
input = input.replace(
|
||||
&format!(
|
||||
"{{{{ icon \"{cap_str}\" c({}) }}}}",
|
||||
cap.get(4).unwrap().as_str()
|
||||
),
|
||||
&icon_text,
|
||||
);
|
||||
}
|
||||
|
||||
// icon (without class)
|
||||
let icon_without_class = regex::Regex::new("(\\{\\{)\\s*(icon)\\s*(.*?)\\s*(\\}\\})").unwrap();
|
||||
|
||||
for cap in icon_without_class.captures_iter(&input.clone()) {
|
||||
let cap_str = &cap.get(3).unwrap().as_str().replace("\"", "");
|
||||
let icon = &(if cap_str.contains(" }}") {
|
||||
cap_str.split(" }}").next().unwrap().to_string()
|
||||
} else {
|
||||
cap_str.to_string()
|
||||
});
|
||||
|
||||
pull_icon(icon, icon_dir).await;
|
||||
|
||||
let reader = ICONS.read().await;
|
||||
let icon_text = reader
|
||||
.get(icon)
|
||||
.unwrap()
|
||||
.replace("<svg", "<svg class=\"icon\"");
|
||||
|
||||
input = input.replace(&format!("{{{{ icon \"{cap_str}\" }}}}",), &icon_text);
|
||||
}
|
||||
|
||||
// ...
|
||||
input
|
||||
}
|
|
@ -3,6 +3,8 @@ pub mod config;
|
|||
#[cfg(feature = "database")]
|
||||
pub mod database;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod html;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod model;
|
||||
#[cfg(feature = "sdk")]
|
||||
pub mod sdk;
|
||||
|
|
|
@ -337,6 +337,10 @@ pub struct UserSettings {
|
|||
/// Biography shown on `profile/private.lisp` page.
|
||||
#[serde(default)]
|
||||
pub private_biography: String,
|
||||
/// If the followers/following links are hidden from the user's profile.
|
||||
/// Will also revoke access to their respective pages.
|
||||
#[serde(default)]
|
||||
pub hide_social_follows: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue