feat: replace legacy hold-to-delete logic with modern ButtonAction component
Some checks failed
Build MIPS Binary / build (push) Failing after 34s
Some checks failed
Build MIPS Binary / build (push) Failing after 34s
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
use crate::components::ui::context_menu::*;
|
use crate::components::ui::context_menu::{
|
||||||
|
ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger,
|
||||||
|
};
|
||||||
|
use crate::components::ui::button_action::ButtonAction;
|
||||||
|
use crate::components::ui::button::ButtonVariant;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn TorrentContextMenu(
|
pub fn TorrentContextMenu(
|
||||||
@@ -7,72 +11,55 @@ pub fn TorrentContextMenu(
|
|||||||
torrent_hash: String,
|
torrent_hash: String,
|
||||||
on_action: Callback<(String, String)>,
|
on_action: Callback<(String, String)>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
let hash = StoredValue::new(torrent_hash);
|
let hash_c1 = torrent_hash.clone();
|
||||||
|
let hash_c2 = torrent_hash.clone();
|
||||||
|
let hash_c3 = torrent_hash.clone();
|
||||||
|
let hash_c4 = torrent_hash.clone();
|
||||||
|
|
||||||
let menu_action = move |action: &'static str| {
|
let on_action_stored = StoredValue::new(on_action);
|
||||||
on_action.run((action.to_string(), hash.get_value()));
|
|
||||||
};
|
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<ContextMenuTrigger>
|
<ContextMenuTrigger>
|
||||||
{children()}
|
{children()}
|
||||||
</ContextMenuTrigger>
|
</ContextMenuTrigger>
|
||||||
|
<ContextMenuContent class="w-56 p-1.5">
|
||||||
<ContextMenuContent class="w-56">
|
<ContextMenuItem on:click={let h = hash_c1; move |_| on_action_stored.get_value().run(("start".to_string(), h.clone()))}>
|
||||||
<ContextMenuAction
|
"Başlat"
|
||||||
class="px-2 py-1.5 hover:bg-accent hover:text-accent-foreground rounded-sm"
|
</ContextMenuItem>
|
||||||
on:click=move |_| menu_action("start")
|
<ContextMenuItem on:click={let h = hash_c2; move |_| on_action_stored.get_value().run(("stop".to_string(), h.clone()))}>
|
||||||
>
|
"Durdur"
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mr-2 h-4 w-4 opacity-70">
|
</ContextMenuItem>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z" />
|
|
||||||
</svg>
|
<div class="my-1.5 h-px bg-border/50" />
|
||||||
"Start"
|
|
||||||
</ContextMenuAction>
|
// --- Modern Hold-to-Action Buttons ---
|
||||||
|
<div class="space-y-1">
|
||||||
|
<ButtonAction
|
||||||
|
variant=ButtonVariant::Ghost
|
||||||
|
class="w-full justify-start h-8 px-2 text-xs text-destructive hover:bg-destructive/10 hover:text-destructive transition-none"
|
||||||
|
hold_duration=800
|
||||||
|
on_action={let h = hash_c3; move || {
|
||||||
|
on_action_stored.get_value().run(("delete".to_string(), h.clone()));
|
||||||
|
crate::components::ui::context_menu::close_context_menu();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
"Sil (Basılı Tut)"
|
||||||
|
</ButtonAction>
|
||||||
|
|
||||||
<ContextMenuAction
|
<ButtonAction
|
||||||
class="px-2 py-1.5 hover:bg-accent hover:text-accent-foreground rounded-sm"
|
variant=ButtonVariant::Destructive
|
||||||
on:click=move |_| menu_action("stop")
|
class="w-full justify-start h-8 px-2 text-xs font-bold"
|
||||||
>
|
hold_duration=1200
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mr-2 h-4 w-4 opacity-70">
|
on_action={let h = hash_c4; move || {
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25v13.5m-7.5-13.5v13.5" />
|
on_action_stored.get_value().run(("delete_with_data".to_string(), h.clone()));
|
||||||
</svg>
|
crate::components::ui::context_menu::close_context_menu();
|
||||||
"Stop"
|
}}
|
||||||
</ContextMenuAction>
|
>
|
||||||
|
"Verilerle Sil (Basılı Tut)"
|
||||||
<ContextMenuAction
|
</ButtonAction>
|
||||||
class="px-2 py-1.5 hover:bg-accent hover:text-accent-foreground rounded-sm"
|
</div>
|
||||||
on:click=move |_| menu_action("recheck")
|
|
||||||
>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mr-2 h-4 w-4 opacity-70">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" />
|
|
||||||
</svg>
|
|
||||||
"Recheck"
|
|
||||||
</ContextMenuAction>
|
|
||||||
|
|
||||||
<div class="-mx-1 my-1 h-px bg-border" />
|
|
||||||
|
|
||||||
<ContextMenuAction
|
|
||||||
class="px-2 py-1.5 text-destructive hover:bg-destructive/10 hover:text-destructive rounded-sm"
|
|
||||||
on:click=move |_| menu_action("delete")
|
|
||||||
>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mr-2 h-4 w-4 opacity-70">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.164h-2.34c-1.18 0-2.09.984-2.09 2.164v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
|
|
||||||
</svg>
|
|
||||||
"Remove"
|
|
||||||
</ContextMenuAction>
|
|
||||||
|
|
||||||
<ContextMenuHoldAction
|
|
||||||
class="text-destructive hover:bg-destructive/10 hover:text-destructive"
|
|
||||||
on_hold_complete=move |_| menu_action("delete_with_data")
|
|
||||||
>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mr-2 h-4 w-4 opacity-70">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5m6 4.125l2.25 2.25m0 0l2.25 2.25M12 13.875l2.25-2.25M12 13.875l-2.25-2.25M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" />
|
|
||||||
</svg>
|
|
||||||
"Remove with Data"
|
|
||||||
<span class="ml-auto text-[10px] opacity-50">"Hold"</span>
|
|
||||||
</ContextMenuHoldAction>
|
|
||||||
</ContextMenuContent>
|
</ContextMenuContent>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,72 +78,6 @@ pub fn ContextMenuAction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
|
||||||
pub fn ContextMenuHoldAction(
|
|
||||||
children: Children,
|
|
||||||
#[prop(into)] on_hold_complete: Callback<()>,
|
|
||||||
#[prop(optional, into)] class: String,
|
|
||||||
#[prop(default = 1000)] hold_duration: u64,
|
|
||||||
) -> impl IntoView {
|
|
||||||
let is_holding = RwSignal::new(false);
|
|
||||||
|
|
||||||
let on_mousedown = move |_| {
|
|
||||||
is_holding.set(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
let on_mouseup = move |_| {
|
|
||||||
is_holding.set(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
Effect::new(move |_| {
|
|
||||||
if is_holding.get() {
|
|
||||||
leptos::task::spawn_local(async move {
|
|
||||||
gloo_timers::future::TimeoutFuture::new(hold_duration as u32).await;
|
|
||||||
if is_holding.get_untracked() {
|
|
||||||
on_hold_complete.run(());
|
|
||||||
is_holding.set(false);
|
|
||||||
close_context_menu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let class = tw_merge!(
|
|
||||||
"relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors overflow-hidden",
|
|
||||||
class
|
|
||||||
);
|
|
||||||
|
|
||||||
view! {
|
|
||||||
<style>
|
|
||||||
"@keyframes hold-progress {
|
|
||||||
from { width: 0%; }
|
|
||||||
to { width: 100%; }
|
|
||||||
}
|
|
||||||
.animate-hold {
|
|
||||||
animation: hold-progress var(--hold-duration) linear forwards;
|
|
||||||
}"
|
|
||||||
</style>
|
|
||||||
<div
|
|
||||||
class=class
|
|
||||||
attr:style=format!("--hold-duration: {}ms", hold_duration)
|
|
||||||
on:mousedown=on_mousedown
|
|
||||||
on:mouseup=on_mouseup
|
|
||||||
on:mouseleave=on_mouseup
|
|
||||||
on:touchstart=move |_| on_mousedown(web_sys::MouseEvent::new("mousedown").unwrap())
|
|
||||||
on:touchend=move |_| on_mouseup(web_sys::MouseEvent::new("mouseup").unwrap())
|
|
||||||
>
|
|
||||||
// Progress background
|
|
||||||
<Show when=move || is_holding.get()>
|
|
||||||
<div class="absolute inset-y-0 left-0 bg-destructive/20 pointer-events-none animate-hold" />
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
<span class="relative z-10 flex items-center gap-2 w-full">
|
|
||||||
{children()}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}.into_any()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct ContextMenuContext {
|
struct ContextMenuContext {
|
||||||
target_id: String,
|
target_id: String,
|
||||||
@@ -393,7 +327,7 @@ pub fn ContextMenuContent(
|
|||||||
target_id_for_script,
|
target_id_for_script,
|
||||||
)}
|
)}
|
||||||
</script>
|
</script>
|
||||||
}.into_any()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
|||||||
Reference in New Issue
Block a user