1
0
Fork 0
mirror of https://github.com/Nutomic/ibis.git synced 2025-02-04 19:54:41 +00:00

remove more code

This commit is contained in:
Felix Ableitner 2024-11-20 15:44:41 +01:00
parent d7d79af7a9
commit ee34c98b52
5 changed files with 21 additions and 320 deletions

View file

@ -1,8 +1,6 @@
use crate::{
common::SiteView,
frontend::{
api::CLIENT, components::nav::Nav, dark_mode::DarkMode, pages::notifications::Notifications,
},
frontend::{api::CLIENT, components::nav::Nav, pages::notifications::Notifications},
};
use leptos::prelude::*;
use leptos_meta::{provide_meta_context, *};
@ -66,9 +64,6 @@ pub fn App() -> impl IntoView {
let site_resource = Resource::new(|| (), |_| async move { CLIENT.site().await.unwrap() });
provide_context(site_resource);
let darkmode = DarkMode::init();
provide_context(darkmode.clone());
view! {
<Html attr:data-theme=darkmode.theme {..} class="h-full" />
<Body {..} class="h-full max-sm:flex max-sm:flex-col" />

View file

@ -1,55 +1,16 @@
use crate::frontend::{
api::CLIENT,
app::{is_logged_in, site, DefaultResource},
dark_mode::DarkMode,
};
use leptos::{component, prelude::*, view, IntoView, *};
use leptos_router::{components::A, hooks::use_navigate};
use crate::frontend::{api::CLIENT, app::is_logged_in};
use leptos::{component, prelude::*, view, IntoView};
use leptos_router::components::A;
#[component]
pub fn Nav() -> impl IntoView {
let logout_action = Action::new(move |_| async move {
CLIENT.logout().await.unwrap();
site().refetch();
});
let notification_count = Resource::new(
|| (),
move |_| async move { CLIENT.notifications_count().await.unwrap_or_default() },
);
let (search_query, set_search_query) = signal(String::new());
let mut dark_mode = expect_context::<DarkMode>();
view! {
<nav class="max-sm:navbar p-2.5 h-full md:fixed md:w-64 max-sm: border-b md:border-e border-slate-400 border-solid">
<div
id="navbar-start"
class="max-sm:navbar-start max-sm:flex max-sm:dropdown max-sm:dropdown-bottom max-sm:dropdown-end max-sm:w-full md:h-full"
>
<h1 class="w-min md:hidden text-3xl font-bold font-serif">
{CLIENT.hostname.clone()}
</h1>
<div class="flex-grow md:hidden"></div>
<button tabindex="0" class="btn btn-outline lg:hidden">
Menu
</button>
<div
tabindex="0"
class="menu dropdown-content p-2 max-sm:rounded-box max-sm:z-[1] max-sm:shadow md:h-full"
>
<img src="/logo.png" class="m-auto max-sm:hidden" />
<h1 class="px-4 py-2 text-3xl font-bold font-serif sm:hidden">
{CLIENT.hostname.clone()}
</h1>
<ul>
<li>
<A href="/">"Main Page"</A>
</li>
<li>
<A href="/instance/list">"Instances"</A>
</li>
<li>
<A href="/article/list">"Articles"</A>
</li>
<nav>
<Transition>
<Show when=is_logged_in>
<li>
@ -65,100 +26,6 @@ pub fn Nav() -> impl IntoView {
</li>
</Show>
</Transition>
<li>
<form
class="form-control m-0 p-1"
on:submit=move |ev| {
ev.prevent_default();
let navigate = use_navigate();
let query = search_query.get();
if !query.is_empty() {
navigate(
&format!("/search?query={query}"),
Default::default(),
);
}
}
>
<input
type="text"
class="input input-secondary input-bordered input-xs w-full rounded"
placeholder="Search"
prop:value=search_query
on:keyup=move |ev: ev::KeyboardEvent| {
let val = event_target_value(&ev);
set_search_query.update(|v| *v = val);
}
/>
<button class="btn btn-xs btn-secondary">Go</button>
</form>
</li>
</ul>
<div class="divider"></div>
<Transition>
<Show
when=is_logged_in
fallback=move || {
view! {
<li>
<A href="/login">"Login"</A>
</li>
<Show when=move || {
site().with_default(|s| s.config.registration_open)
}>
<li>
<A href="/register">"Register"</A>
</li>
</Show>
}
}
>
{
let my_profile = site()
.with_default(|site| site.clone().my_profile.unwrap());
let profile_link = format!("/user/{}", my_profile.person.username);
view! {
<p class="self-center pb-2">
"Logged in as " <a class="link" href=profile_link>
{my_profile.person.username}
</a>
</p>
<button
class="btn btn-outline btn-xs w-min self-center"
on:click=move |_| {
logout_action.dispatch(());
}
>
Logout
</button>
}
}
</Show>
</Transition>
<div class="grow min-h-2"></div>
<div class="m-1 grid gap-2">
<label class="flex cursor-pointer gap-2">
<span class="label-text">Light</span>
<input
type="checkbox"
class="toggle"
prop:checked=dark_mode.is_dark
on:click=move |_| { dark_mode.toggle() }
/>
<span class="label-text">Dark</span>
</label>
<p>"Version "{env!("CARGO_PKG_VERSION")}</p>
<p>
<a href="https://github.com/Nutomic/ibis" class="link">
Source Code
</a>
</p>
</div>
</div>
</div>
</nav>
}
}

View file

@ -1,39 +0,0 @@
use chrono::{Duration, Local};
use codee::string::FromToStringCodec;
use leptos::prelude::*;
use leptos_use::{use_cookie_with_options, use_preferred_dark, SameSite, UseCookieOptions};
#[derive(Debug, Clone)]
pub struct DarkMode {
cookie: WriteSignal<Option<bool>>,
pub is_dark: Signal<bool>,
pub theme: Signal<&'static str>,
}
impl DarkMode {
pub fn init() -> Self {
let expires = (Local::now() + Duration::days(356)).timestamp();
let cookie_options = UseCookieOptions::default()
.path("/")
.expires(expires)
.same_site(SameSite::Strict);
let cookie =
use_cookie_with_options::<bool, FromToStringCodec>("dark_mode", cookie_options);
let is_dark = Signal::derive(move || {
let default = || use_preferred_dark().get_untracked();
cookie.0.get().unwrap_or_else(default)
});
let theme = Signal::derive(move || if is_dark.get() { "dim" } else { "emerald" });
Self {
cookie: cookie.1,
is_dark,
theme,
}
}
pub fn toggle(&mut self) {
let new = !self.is_dark.get_untracked();
self.cookie.set(Some(new));
}
}

View file

@ -1,9 +1,6 @@
use crate::common::{utils::extract_domain, DbArticle};
pub mod api;
pub mod app;
mod components;
pub mod dark_mode;
pub mod error;
pub mod markdown;
pub mod pages;
@ -16,24 +13,3 @@ pub fn hydrate() {
console_error_panic_hook::set_once();
leptos::mount::hydrate_body(App);
}
fn article_link(article: &DbArticle) -> String {
if article.local {
format!("/article/{}", article.title)
} else {
format!(
"/article/{}@{}",
article.title,
extract_domain(&article.ap_id)
)
}
}
fn article_title(article: &DbArticle) -> String {
let title = article.title.replace('_', " ");
if article.local {
title
} else {
format!("{}@{}", title, extract_domain(&article.ap_id))
}
}

View file

@ -1,104 +1,6 @@
use crate::{
common::Notification,
frontend::{api::CLIENT, article_link, article_title},
};
use leptos::prelude::*;
#[component]
pub fn Notifications() -> impl IntoView {
let notifications = Resource::new(
move || {},
|_| async move { CLIENT.notifications_list().await.unwrap() },
);
view! {
<h1 class="text-4xl font-bold font-serif my-6 grow flex-auto">Notifications</h1>
<Suspense fallback=|| view! { "Loading..." }>
<ul class="divide-y divide-solid">
{move || {
notifications
.get()
.map(|n| {
n.into_iter()
.map(|ref notif| {
use Notification::*;
let (my_style, link, title) = match notif {
EditConflict(c) => {
(
"visibility: hidden",
format!("{}/edit/{}", article_link(&c.article), c.id.0),
format!(
"Conflict: {} - {}",
article_title(&c.article),
c.summary,
),
)
}
ArticleApprovalRequired(a) => {
(
"",
article_link(a),
format!("Approval required: {}", a.title),
)
}
};
let notif_ = notif.clone();
let click_approve = Action::new(move |_: &()| {
let notif_ = notif_.clone();
async move {
if let ArticleApprovalRequired(a) = notif_ {
CLIENT.approve_article(a.id, true).await.unwrap();
}
notifications.refetch();
}
});
let notif_ = notif.clone();
let click_reject = Action::new(move |_: &()| {
let notif_ = notif_.clone();
async move {
match notif_ {
EditConflict(c) => {
CLIENT.delete_conflict(c.id).await.unwrap();
}
ArticleApprovalRequired(a) => {
CLIENT.approve_article(a.id, false).await.unwrap();
}
}
notifications.refetch();
}
});
view! {
<li class="py-2">
<a class="link text-lg" href=link>
{title}
</a>
<div class="card-actions mt-2">
<button
class="btn btn-sm btn-outline"
style=my_style
on:click=move |_| {
click_approve.dispatch(());
}
>
Approve
</button>
<button
class="btn btn-sm btn-outline"
on:click=move |_| {
click_reject.dispatch(());
}
>
Reject
</button>
</div>
</li>
}
})
.collect::<Vec<_>>()
})
}}
</ul>
</Suspense>
}
view! {}
}