Add last undo/redo for notebook page
This commit is contained in:
parent
f041a864ed
commit
7892b259cb
Binary file not shown.
|
|
@ -2,7 +2,7 @@
|
||||||
import { notebookStore } from '$lib/stores/notebook.svelte';
|
import { notebookStore } from '$lib/stores/notebook.svelte';
|
||||||
import Button from '$lib/components/ui/button/button.svelte';
|
import Button from '$lib/components/ui/button/button.svelte';
|
||||||
import Textarea from '$lib/components/ui/textarea/textarea.svelte';
|
import Textarea from '$lib/components/ui/textarea/textarea.svelte';
|
||||||
import { Play, Square, Settings } from '@lucide/svelte';
|
import { Play, Square, Settings, Undo, Redo } from '@lucide/svelte';
|
||||||
import { config } from '$lib/stores/settings.svelte';
|
import { config } from '$lib/stores/settings.svelte';
|
||||||
import DialogChatSettings from '$lib/components/app/dialogs/DialogChatSettings.svelte';
|
import DialogChatSettings from '$lib/components/app/dialogs/DialogChatSettings.svelte';
|
||||||
import { ModelsSelector, ChatMessageStatistics, DialogChatError } from '$lib/components/app';
|
import { ModelsSelector, ChatMessageStatistics, DialogChatError } from '$lib/components/app';
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
let isRouter = $derived(isRouterMode());
|
let isRouter = $derived(isRouterMode());
|
||||||
|
|
||||||
let errorDialog = $derived(notebookStore.error);
|
let errorDialog = $derived(notebookStore.error);
|
||||||
|
let canUndo = $derived(notebookStore.previousContent !== null && !notebookStore.isGenerating);
|
||||||
|
let canRedo = $derived(notebookStore.undoneContent !== null && !notebookStore.isGenerating);
|
||||||
|
|
||||||
// Sync local input with store content
|
// Sync local input with store content
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
|
@ -44,6 +46,7 @@
|
||||||
function handleInput(e: Event) {
|
function handleInput(e: Event) {
|
||||||
const target = e.target as HTMLTextAreaElement;
|
const target = e.target as HTMLTextAreaElement;
|
||||||
notebookStore.content = target.value;
|
notebookStore.content = target.value;
|
||||||
|
notebookStore.resetUndoRedo();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleErrorDialogOpenChange(open: boolean) {
|
function handleErrorDialogOpenChange(open: boolean) {
|
||||||
|
|
@ -65,6 +68,13 @@
|
||||||
await notebookStore.generate(notebookModel);
|
await notebookStore.generate(notebookModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleUndo() {
|
||||||
|
notebookStore.undo();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRedo() {
|
||||||
|
notebookStore.redo();
|
||||||
|
}
|
||||||
|
|
||||||
function handleStop() {
|
function handleStop() {
|
||||||
notebookStore.stop();
|
notebookStore.stop();
|
||||||
|
|
@ -223,13 +233,45 @@
|
||||||
<div class="bg-background p-2 md:p-4">
|
<div class="bg-background p-2 md:p-4">
|
||||||
<div class="flex flex-col-reverse gap-4 md:flex-row md:items-center md:justify-between">
|
<div class="flex flex-col-reverse gap-4 md:flex-row md:items-center md:justify-between">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
|
<Tooltip.Root>
|
||||||
|
<Tooltip.Trigger>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
disabled={!canUndo}
|
||||||
|
onclick={handleUndo}
|
||||||
|
>
|
||||||
|
<Undo class="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</Tooltip.Trigger>
|
||||||
|
<Tooltip.Content>
|
||||||
|
<p>Undo last generation</p>
|
||||||
|
</Tooltip.Content>
|
||||||
|
</Tooltip.Root>
|
||||||
|
|
||||||
|
<Tooltip.Root>
|
||||||
|
<Tooltip.Trigger>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
disabled={!canRedo}
|
||||||
|
onclick={handleRedo}
|
||||||
|
>
|
||||||
|
<Redo class="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</Tooltip.Trigger>
|
||||||
|
<Tooltip.Content>
|
||||||
|
<p>Redo last generation</p>
|
||||||
|
</Tooltip.Content>
|
||||||
|
</Tooltip.Root>
|
||||||
|
|
||||||
{#snippet generateButton(props = {})}
|
{#snippet generateButton(props = {})}
|
||||||
<Button
|
<Button
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
onclick={notebookStore.isGenerating ? handleStop : handleGenerate}
|
onclick={notebookStore.isGenerating ? handleStop : handleGenerate}
|
||||||
size="sm"
|
size="sm"
|
||||||
variant={notebookStore.isGenerating ? 'destructive' : 'default'}
|
variant={notebookStore.isGenerating ? 'destructive' : 'default'}
|
||||||
class="gap-2"
|
class="gap-2 min-w-[120px]"
|
||||||
>
|
>
|
||||||
{#if notebookStore.isGenerating}
|
{#if notebookStore.isGenerating}
|
||||||
<Square class="h-4 w-4 fill-current" />
|
<Square class="h-4 w-4 fill-current" />
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,14 @@ export class NotebookStore {
|
||||||
contextInfo?: { n_prompt_tokens: number; n_ctx: number };
|
contextInfo?: { n_prompt_tokens: number; n_ctx: number };
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
|
previousContent = $state<string | null>(null);
|
||||||
|
undoneContent = $state<string | null>(null);
|
||||||
|
|
||||||
async generate(model?: string) {
|
async generate(model?: string) {
|
||||||
if (this.isGenerating) return;
|
if (this.isGenerating) return;
|
||||||
|
|
||||||
|
this.previousContent = this.content;
|
||||||
|
this.undoneContent = null;
|
||||||
this.isGenerating = true;
|
this.isGenerating = true;
|
||||||
this.abortController = new AbortController();
|
this.abortController = new AbortController();
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
@ -90,6 +95,27 @@ export class NotebookStore {
|
||||||
this.error = null;
|
this.error = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
undo() {
|
||||||
|
if (this.previousContent !== null) {
|
||||||
|
this.undoneContent = this.content;
|
||||||
|
this.content = this.previousContent;
|
||||||
|
this.previousContent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
redo() {
|
||||||
|
if (this.undoneContent !== null) {
|
||||||
|
this.previousContent = this.content;
|
||||||
|
this.content = this.undoneContent;
|
||||||
|
this.undoneContent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetUndoRedo() {
|
||||||
|
this.previousContent = null;
|
||||||
|
this.undoneContent = null;
|
||||||
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
if (this.abortController) {
|
if (this.abortController) {
|
||||||
this.abortController.abort();
|
this.abortController.abort();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue