Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@ import * as main from "../../../../../../store/tinybase/store/main";
import { useTabs } from "../../../../../../store/zustand/tabs";
import { useUndoDelete } from "../../../../../../store/zustand/undo-delete";

const UNDO_TIMEOUT_MS = 5000;

export function DeleteNote({ sessionId }: { sessionId: string }) {
const store = main.UI.useStore(main.STORE_ID);
const indexes = main.UI.useIndexes(main.STORE_ID);
const invalidateResource = useTabs((state) => state.invalidateResource);
const { setDeletedSession, setTimeoutId, clear } = useUndoDelete();
const addDeletion = useUndoDelete((state) => state.addDeletion);

const handleDeleteNote = useCallback(() => {
if (!store) {
Expand All @@ -34,27 +32,14 @@ export function DeleteNote({ sessionId }: { sessionId: string }) {
void deleteSessionCascade(store, indexes, sessionId);

if (capturedData) {
setDeletedSession(capturedData);

const timeoutId = setTimeout(() => {
clear();
}, UNDO_TIMEOUT_MS);
setTimeoutId(timeoutId);
addDeletion(capturedData);
}

void analyticsCommands.event({
event: "session_deleted",
includes_recording: true,
});
}, [
store,
indexes,
sessionId,
invalidateResource,
setDeletedSession,
setTimeoutId,
clear,
]);
}, [store, indexes, sessionId, invalidateResource, addDeletion]);

return (
<DropdownMenuItem
Expand Down
17 changes: 3 additions & 14 deletions apps/desktop/src/components/main/sidebar/timeline/item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ const SessionItem = memo(
const openCurrent = useTabs((state) => state.openCurrent);
const openNew = useTabs((state) => state.openNew);
const invalidateResource = useTabs((state) => state.invalidateResource);
const { setDeletedSession, setTimeoutId } = useUndoDelete();
const addDeletion = useUndoDelete((state) => state.addDeletion);

const sessionId = item.id;
const title =
Expand Down Expand Up @@ -357,20 +357,9 @@ const SessionItem = memo(
void deleteSessionCascade(store, indexes, sessionId);
};

setDeletedSession(capturedData, performDelete);
const timeoutId = setTimeout(() => {
useUndoDelete.getState().confirmDelete();
}, 5000);
setTimeoutId(timeoutId);
addDeletion(capturedData, performDelete);
}
}, [
store,
indexes,
sessionId,
invalidateResource,
setDeletedSession,
setTimeoutId,
]);
}, [store, indexes, sessionId, invalidateResource, addDeletion]);

const handleRevealInFinder = useCallback(async () => {
await save();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";

import { restoreSessionData } from "../../../../store/tinybase/store/deleteSession";
Expand All @@ -11,21 +11,36 @@ import {

export function useUndoDeleteHandler() {
const store = main.UI.useStore(main.STORE_ID);
const { deletedSession, clear } = useUndoDelete();
const pendingDeletions = useUndoDelete((state) => state.pendingDeletions);
const clearDeletion = useUndoDelete((state) => state.clearDeletion);
const openCurrent = useTabs((state) => state.openCurrent);

const latestSessionId = useMemo(() => {
let latest: string | null = null;
let latestTime = 0;
for (const [sessionId, pending] of Object.entries(pendingDeletions)) {
if (pending.addedAt > latestTime) {
latestTime = pending.addedAt;
latest = sessionId;
}
}
return latest;
}, [pendingDeletions]);

const handleUndo = useCallback(() => {
if (!store || !deletedSession) return;
if (!store || !latestSessionId) return;
const pending = pendingDeletions[latestSessionId];
if (!pending) return;

restoreSessionData(store, deletedSession);
openCurrent({ type: "sessions", id: deletedSession.session.id });
clear();
}, [store, deletedSession, openCurrent, clear]);
restoreSessionData(store, pending.data);
openCurrent({ type: "sessions", id: latestSessionId });
clearDeletion(latestSessionId);
}, [store, latestSessionId, pendingDeletions, openCurrent, clearDeletion]);

useHotkeys(
"mod+z",
() => {
if (deletedSession) {
if (latestSessionId) {
handleUndo();
}
},
Expand All @@ -34,10 +49,10 @@ export function useUndoDeleteHandler() {
enableOnFormTags: true,
enableOnContentEditable: true,
},
[deletedSession, handleUndo],
[latestSessionId, handleUndo],
);

return { handleUndo, deletedSession };
return { handleUndo, hasPendingDeletion: latestSessionId !== null };
}

export function UndoDeleteKeyboardHandler() {
Expand All @@ -46,24 +61,25 @@ export function UndoDeleteKeyboardHandler() {
}

export function useDissolvingProgress(sessionId: string | null) {
const { deletedSession, isPaused, remainingTime } = useUndoDelete();
const pending = useUndoDelete((state) =>
sessionId ? state.pendingDeletions[sessionId] : undefined,
);
const [progress, setProgress] = useState(100);

const isDissolving =
deletedSession !== null && deletedSession.session.id === sessionId;
const isDissolving = pending !== undefined;

useEffect(() => {
if (!isDissolving || !deletedSession) {
if (!isDissolving || !pending) {
setProgress(100);
return;
}

if (isPaused) {
setProgress((remainingTime / UNDO_TIMEOUT_MS) * 100);
if (pending.isPaused) {
setProgress((pending.remainingTime / UNDO_TIMEOUT_MS) * 100);
return;
}

const startTime = deletedSession.deletedAt;
const startTime = pending.data.deletedAt;
const endTime = startTime + UNDO_TIMEOUT_MS;

const updateProgress = () => {
Expand All @@ -83,7 +99,7 @@ export function useDissolvingProgress(sessionId: string | null) {
cancelAnimationFrame(animationIdRef.current);
}
};
}, [isDissolving, deletedSession, isPaused, remainingTime]);
}, [isDissolving, pending]);

return { isDissolving, progress };
}
29 changes: 16 additions & 13 deletions apps/desktop/src/components/ui/dissolving-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,27 @@ export function DissolvingContainer({
variant = "sidebar",
}: DissolvingContainerProps) {
const store = main.UI.useStore(main.STORE_ID);
const { deletedSession, clear, pause, resume, isPaused } = useUndoDelete();
const pending = useUndoDelete((state) => state.pendingDeletions[sessionId]);
const pause = useUndoDelete((state) => state.pause);
const resume = useUndoDelete((state) => state.resume);
const clearDeletion = useUndoDelete((state) => state.clearDeletion);
const openCurrent = useTabs((state) => state.openCurrent);
const { isDissolving, progress } = useDissolvingProgress(sessionId);

const handleMouseEnter = useCallback(() => {
pause();
}, [pause]);
pause(sessionId);
}, [pause, sessionId]);

const handleMouseLeave = useCallback(() => {
resume();
}, [resume]);
resume(sessionId);
}, [resume, sessionId]);

const handleRestore = useCallback(() => {
if (!store || !deletedSession) return;
restoreSessionData(store, deletedSession);
openCurrent({ type: "sessions", id: deletedSession.session.id });
clear();
}, [store, deletedSession, openCurrent, clear]);
if (!store || !pending) return;
restoreSessionData(store, pending.data);
openCurrent({ type: "sessions", id: sessionId });
clearDeletion(sessionId);
}, [store, pending, sessionId, openCurrent, clearDeletion]);

if (!isDissolving) {
return <>{children}</>;
Expand Down Expand Up @@ -80,7 +83,7 @@ export function DissolvingContainer({
"pointer-events-none",
])}
>
{isPaused ? (
{pending?.isPaused ? (
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
Expand Down Expand Up @@ -128,13 +131,13 @@ export function DissolvingContainer({
{children}
</motion.div>

{!isPaused && (
{!pending?.isPaused && (
<span className="text-xs text-neutral-400 tabular-nums mr-2">
{remainingSeconds}
</span>
)}

{isPaused && (
{pending?.isPaused && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
Expand Down
Loading
Loading