diff --git a/Cargo.lock b/Cargo.lock index 7227c2de..63ce31de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4510,6 +4510,8 @@ dependencies = [ "mdhtml", "reqwest", "serde", + "serde-inline-default", + "serde_default", "serde_json", "thiserror", "tracing", diff --git a/web/Cargo.toml b/web/Cargo.toml index d6e3d8d2..39e9f20b 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -19,6 +19,8 @@ console_error_panic_hook = "0.1" thiserror = "1" serde = { version = "1", features = ["derive"] } serde_json = "1" +serde_default = "0.1" +serde-inline-default = "0.2" dashmap = "5.5" leptos = { version = "0.6", features = ["csr", "tracing"] } leptos_router = { version = "0.6", features = ["csr"] } diff --git a/web/src/app.rs b/web/src/app.rs index 8ae651ce..735d88a4 100644 --- a/web/src/app.rs +++ b/web/src/app.rs @@ -2,7 +2,7 @@ use leptos::*; use leptos_router::*; use crate::prelude::*; -use leptos_use::{use_cookie, use_cookie_with_options, utils::FromToStringCodec, UseCookieOptions}; +use leptos_use::{storage::use_local_storage, use_cookie, use_cookie_with_options, utils::{FromToStringCodec, JsonCodec}, UseCookieOptions}; #[component] @@ -12,10 +12,12 @@ pub fn App() -> impl IntoView { UseCookieOptions::default() .max_age(1000 * 60 * 60 * 6) ); + let (config, set_config, _) = use_local_storage::("config"); let (userid, set_userid) = use_cookie::("user_id"); let auth = Auth { token, userid }; provide_context(auth); + provide_context(config); let username = auth.userid.get_untracked() .map(|x| x.split('/').last().unwrap_or_default().to_string()) @@ -105,7 +107,7 @@ pub fn App() -> impl IntoView { } /> } /> - + } /> } /> diff --git a/web/src/config.rs b/web/src/config.rs new file mode 100644 index 00000000..5015e0e6 --- /dev/null +++ b/web/src/config.rs @@ -0,0 +1,47 @@ + +#[serde_inline_default::serde_inline_default] +#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, serde_default::DefaultFromSerde)] +pub struct Config { + #[serde(default)] + pub filters: FiltersConfig, + + #[serde_inline_default(true)] + pub collapse_content_warnings: bool, + + #[serde_inline_default(true)] + pub loop_videos: bool, +} + +#[serde_inline_default::serde_inline_default] +#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, serde_default::DefaultFromSerde)] +pub struct FiltersConfig { + #[serde_inline_default(false)] + pub likes: bool, + + #[serde_inline_default(true)] + pub creates: bool, + + #[serde_inline_default(true)] + pub announces: bool, + + #[serde_inline_default(true)] + pub follows: bool, + + #[serde_inline_default(true)] + pub orphans: bool, +} + +impl FiltersConfig { + pub fn visible(&self, object_type: apb::ObjectType) -> bool { + match object_type { + apb::ObjectType::Note | apb::ObjectType::Document(_) => self.orphans, + apb::ObjectType::Activity(apb::ActivityType::Like) => self.likes, + apb::ObjectType::Activity(apb::ActivityType::Create) => self.creates, + apb::ObjectType::Activity(apb::ActivityType::Announce) => self.announces, + apb::ObjectType::Activity( + apb::ActivityType::Follow | apb::ActivityType::Accept(_) | apb::ActivityType::Reject(_) + ) => self.follows, + _ => true, + } + } +} diff --git a/web/src/control.rs b/web/src/control.rs index 73c3c92a..d3a4ff2e 100644 --- a/web/src/control.rs +++ b/web/src/control.rs @@ -22,6 +22,7 @@ pub fn Navigator() -> impl IntoView { + } diff --git a/web/src/lib.rs b/web/src/lib.rs index 02cdab85..7fa325c9 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -3,8 +3,10 @@ mod auth; mod components; mod page; mod control; +mod config; pub use app::App; +pub use config::Config; pub mod prelude; diff --git a/web/src/page.rs b/web/src/page.rs index 57b2fa8b..9f06f026 100644 --- a/web/src/page.rs +++ b/web/src/page.rs @@ -4,7 +4,7 @@ use apb::{ActivityMut, Actor, Base, Object, ObjectMut}; use leptos::*; use leptos_router::*; -use crate::{prelude::*, DEFAULT_AVATAR_URL}; +use crate::{prelude::*, Config, DEFAULT_AVATAR_URL}; #[component] pub fn AboutPage() -> impl IntoView { @@ -21,17 +21,83 @@ pub fn AboutPage() -> impl IntoView { } #[component] -pub fn ConfigPage() -> impl IntoView { +pub fn ConfigPage(setter: WriteSignal) -> impl IntoView { + let config = use_context::>().expect("missing config context"); + + macro_rules! get_cfg { + (filter $field:ident) => { + move || config.get().filters.$field + }; + ($field:ident) => { + move || config.get().$field + }; + } + + macro_rules! set_cfg { + ($field:ident) => { + move |ev| { + let mut mock = config.get(); + mock.$field = event_target_checked(&ev); + setter.set(mock); + } + }; + (filter $field:ident) => { + move |ev| { + let mut mock = config.get(); + mock.filters.$field = event_target_checked(&ev); + setter.set(mock); + } + }; + } + view! {
config +

+ loop videos +

+

+ collapse content warnings +

-

"not implemented :("

+ + + + + + + + + + + + + + + + + + + + + + + + + +
filters
likes
creates
announces
follows
orphans
} } + fn send_follow_request(target: String) { let auth = use_context::().expect("missing auth context"); spawn_local(async move {