Add recent history clear confirmation
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use ely_domain::{ProfileId, SpaceId};
|
||||
use gpui::Context;
|
||||
|
||||
use super::{ElyShell, ShellState};
|
||||
|
||||
const RECENT_HISTORY_CLEAR_WINDOW: Duration = Duration::from_secs(3_600);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(super) struct PendingHistoryDomainClear {
|
||||
profile_id: ProfileId,
|
||||
@@ -24,6 +28,37 @@ impl PendingHistoryDomainClear {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(super) struct PendingHistoryTimeClear {
|
||||
profile_id: ProfileId,
|
||||
space_id: SpaceId,
|
||||
cutoff: SystemTime,
|
||||
label: &'static str,
|
||||
}
|
||||
|
||||
impl PendingHistoryTimeClear {
|
||||
fn recent_hour(profile_id: ProfileId, space_id: SpaceId) -> Self {
|
||||
Self {
|
||||
profile_id,
|
||||
space_id,
|
||||
cutoff: SystemTime::now() - RECENT_HISTORY_CLEAR_WINDOW,
|
||||
label: "last hour",
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn cutoff(&self) -> SystemTime {
|
||||
self.cutoff
|
||||
}
|
||||
|
||||
pub(super) fn label(&self) -> &'static str {
|
||||
self.label
|
||||
}
|
||||
|
||||
pub(super) fn matches_context(&self, profile_id: &ProfileId, space_id: &SpaceId) -> bool {
|
||||
&self.profile_id == profile_id && &self.space_id == space_id
|
||||
}
|
||||
}
|
||||
|
||||
impl ElyShell {
|
||||
pub(super) fn request_clear_history_confirmation(&mut self, cx: &mut Context<Self>) {
|
||||
if let ShellState::Ready(core) = &mut self.state
|
||||
@@ -31,6 +66,7 @@ impl ElyShell {
|
||||
{
|
||||
self.history_clear_confirmation = Some(snapshot.active_profile_id);
|
||||
self.pending_history_domain_clear = None;
|
||||
self.pending_history_time_clear = None;
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
@@ -48,6 +84,7 @@ impl ElyShell {
|
||||
{
|
||||
self.history_clear_confirmation = None;
|
||||
self.pending_history_domain_clear = None;
|
||||
self.pending_history_time_clear = None;
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
@@ -60,6 +97,8 @@ impl ElyShell {
|
||||
if let ShellState::Ready(core) = &mut self.state
|
||||
&& let Ok(snapshot) = core.snapshot()
|
||||
{
|
||||
self.history_clear_confirmation = None;
|
||||
self.pending_history_time_clear = None;
|
||||
self.pending_history_domain_clear = Some(PendingHistoryDomainClear::new(
|
||||
snapshot.active_profile_id,
|
||||
snapshot.active_space_id,
|
||||
@@ -88,4 +127,38 @@ impl ElyShell {
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn request_clear_recent_history_confirmation(&mut self, cx: &mut Context<Self>) {
|
||||
if let ShellState::Ready(core) = &mut self.state
|
||||
&& let Ok(snapshot) = core.snapshot()
|
||||
{
|
||||
self.history_clear_confirmation = None;
|
||||
self.pending_history_domain_clear = None;
|
||||
self.pending_history_time_clear = Some(PendingHistoryTimeClear::recent_hour(
|
||||
snapshot.active_profile_id,
|
||||
snapshot.active_space_id,
|
||||
));
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn cancel_clear_recent_history_confirmation(&mut self, cx: &mut Context<Self>) {
|
||||
self.pending_history_time_clear = None;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub(super) fn clear_active_space_history_for_pending_time(&mut self, cx: &mut Context<Self>) {
|
||||
let Some(pending) = self.pending_history_time_clear.clone() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let ShellState::Ready(core) = &mut self.state
|
||||
&& let Ok(snapshot) = core.snapshot()
|
||||
&& pending.matches_context(&snapshot.active_profile_id, &snapshot.active_space_id)
|
||||
&& core.clear_active_space_history_since(pending.cutoff()).is_ok()
|
||||
{
|
||||
self.pending_history_time_clear = None;
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use gpui_component::{
|
||||
scroll::ScrollableElement,
|
||||
};
|
||||
|
||||
use super::super::PendingHistoryDomainClear;
|
||||
use super::super::{PendingHistoryDomainClear, PendingHistoryTimeClear};
|
||||
use super::{ElyShell, render_canvas_surface};
|
||||
|
||||
impl ElyShell {
|
||||
@@ -24,6 +24,9 @@ impl ElyShell {
|
||||
let pending_domain_clear = self.pending_history_domain_clear.clone().filter(|pending| {
|
||||
pending.matches_context(&snapshot.active_profile_id, &snapshot.active_space_id)
|
||||
});
|
||||
let pending_time_clear = self.pending_history_time_clear.clone().filter(|pending| {
|
||||
pending.matches_context(&snapshot.active_profile_id, &snapshot.active_space_id)
|
||||
});
|
||||
|
||||
render_canvas_surface(
|
||||
div()
|
||||
@@ -32,7 +35,10 @@ impl ElyShell {
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_5()
|
||||
.child(render_history_header(snapshot))
|
||||
.child(render_history_header(snapshot, cx))
|
||||
.when_some(pending_time_clear, |this, pending| {
|
||||
this.child(render_time_clear_confirmation(&pending, cx))
|
||||
})
|
||||
.when_some(pending_domain_clear, |this, pending| {
|
||||
this.child(render_domain_clear_confirmation(&pending, cx))
|
||||
})
|
||||
@@ -41,13 +47,15 @@ impl ElyShell {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_history_header(snapshot: &BrowserSnapshot) -> AnyElement {
|
||||
fn render_history_header(snapshot: &BrowserSnapshot, cx: &mut Context<ElyShell>) -> AnyElement {
|
||||
div()
|
||||
.flex()
|
||||
.items_end()
|
||||
.justify_between()
|
||||
.gap_4()
|
||||
.child(
|
||||
div()
|
||||
.min_w_0()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_2()
|
||||
@@ -59,9 +67,89 @@ fn render_history_header(snapshot: &BrowserSnapshot) -> AnyElement {
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(rgb(colors::MUTED))
|
||||
.child(format!("{} entries", snapshot.history_entries.len())),
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_3()
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(rgb(colors::MUTED))
|
||||
.child(format!("{} entries", snapshot.history_entries.len())),
|
||||
)
|
||||
.when(!snapshot.history_entries.is_empty(), |this| {
|
||||
this.child(
|
||||
Button::new("request-clear-recent-history")
|
||||
.danger()
|
||||
.xsmall()
|
||||
.label("Clear Last Hour")
|
||||
.tooltip("Clear Recent History")
|
||||
.on_click(cx.listener(|shell, _, _, cx| {
|
||||
shell.request_clear_recent_history_confirmation(cx);
|
||||
})),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn render_time_clear_confirmation(
|
||||
pending: &PendingHistoryTimeClear,
|
||||
cx: &mut Context<ElyShell>,
|
||||
) -> AnyElement {
|
||||
div()
|
||||
.rounded_md()
|
||||
.border_1()
|
||||
.border_color(rgb(colors::ERROR))
|
||||
.bg(rgb(colors::CANVAS_SOFT))
|
||||
.px_4()
|
||||
.py_3()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.gap_4()
|
||||
.child(
|
||||
div()
|
||||
.min_w_0()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.child(
|
||||
div()
|
||||
.text_sm()
|
||||
.font_semibold()
|
||||
.text_color(rgb(colors::INK))
|
||||
.child(format!("Confirm clearing {}", pending.label())),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(rgb(colors::MUTED))
|
||||
.child("This removes recent history in the current Space."),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_2()
|
||||
.child(
|
||||
Button::new("cancel-clear-recent-history")
|
||||
.ghost()
|
||||
.xsmall()
|
||||
.label("Cancel")
|
||||
.on_click(cx.listener(|shell, _, _, cx| {
|
||||
shell.cancel_clear_recent_history_confirmation(cx);
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("confirm-clear-recent-history")
|
||||
.danger()
|
||||
.xsmall()
|
||||
.label("Clear")
|
||||
.on_click(cx.listener(|shell, _, _, cx| {
|
||||
shell.clear_active_space_history_for_pending_time(cx);
|
||||
})),
|
||||
),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use gpui::{App, AppContext, Context, Entity, FocusHandle, Focusable, Subscriptio
|
||||
use gpui_component::input::{InputEvent, InputState, SelectAll};
|
||||
|
||||
use downloads::PendingDownloadFileAction;
|
||||
use history::PendingHistoryDomainClear;
|
||||
use history::{PendingHistoryDomainClear, PendingHistoryTimeClear};
|
||||
use plugins::{PendingPluginInstall, PendingPluginUninstall};
|
||||
|
||||
use crate::{
|
||||
@@ -40,6 +40,7 @@ pub struct ElyShell {
|
||||
download_security_confirmation: Option<PendingDownloadFileAction>,
|
||||
history_clear_confirmation: Option<ProfileId>,
|
||||
pending_history_domain_clear: Option<PendingHistoryDomainClear>,
|
||||
pending_history_time_clear: Option<PendingHistoryTimeClear>,
|
||||
site_permissions_clear_confirmation: Option<ProfileId>,
|
||||
plugin_install_error: Option<String>,
|
||||
pending_plugin_install: Option<PendingPluginInstall>,
|
||||
@@ -104,6 +105,7 @@ impl ElyShell {
|
||||
download_security_confirmation: None,
|
||||
history_clear_confirmation: None,
|
||||
pending_history_domain_clear: None,
|
||||
pending_history_time_clear: None,
|
||||
site_permissions_clear_confirmation: None,
|
||||
plugin_install_error: None,
|
||||
pending_plugin_install: None,
|
||||
|
||||
Reference in New Issue
Block a user