1
0
Fork 0

Highlight the last edited text

This commit is contained in:
Pabloader 2026-03-26 12:03:50 +00:00
parent 215d320e9e
commit 5707bfef5e
4 changed files with 26 additions and 5 deletions

View File

@ -75,6 +75,11 @@
word-break: break-word; word-break: break-word;
} }
.editable mark {
background: var(--bg-active);
color: inherit;
}
.tab { .tab {
padding: 12px 16px; padding: 12px 16px;
background: transparent; background: transparent;

View File

@ -50,9 +50,22 @@ export const Editor = () => {
if (contentRef.current) { if (contentRef.current) {
contentRef.current.scrollTop = contentRef.current.scrollHeight; contentRef.current.scrollTop = contentRef.current.scrollHeight;
} }
}, [currentStory?.currentTab]); }, [currentStory?.id, currentStory?.currentTab]);
const storyValue = useMemo(() => {
if (!currentStory) return '';
const { text, lastEditedText } = currentStory;
if (!lastEditedText) return highlight(text);
const idx = text.lastIndexOf(lastEditedText);
if (idx === -1) return highlight(text);
const marked = text.slice(0, idx) + '<mark>' + lastEditedText + '</mark>' + text.slice(idx + lastEditedText.length);
return highlight(marked);
}, [currentStory?.text, currentStory?.lastEditedText]);
const storyValue = useMemo(() => currentStory ? highlight(currentStory.text) : '', [currentStory?.text]);
const promptPreview = useMemo(() => { const promptPreview = useMemo(() => {
if (currentStory?.currentTab !== 'prompt') return ''; if (currentStory?.currentTab !== 'prompt') return '';
const text = Prompt.formatSystemPrompt(appState); const text = Prompt.formatSystemPrompt(appState);

View File

@ -74,6 +74,7 @@ export interface Story {
currentTab: Tab; currentTab: Tab;
chatMessages: ChatMessage[]; chatMessages: ChatMessage[];
chapters: Chapters.Chapter[]; chapters: Chapters.Chapter[];
lastEditedText?: string;
} }
// ─── State ─────────────────────────────────────────────────────────────────── // ─── State ───────────────────────────────────────────────────────────────────
@ -93,7 +94,7 @@ interface IState {
type Action = type Action =
| { type: 'CREATE_STORY'; title: string } | { type: 'CREATE_STORY'; title: string }
| { type: 'RENAME_STORY'; id: string; title: string } | { type: 'RENAME_STORY'; id: string; title: string }
| { type: 'EDIT_STORY'; id: string; text: string } | { type: 'EDIT_STORY'; id: string; text: string; highlightText?: string }
| { type: 'EDIT_SCRATCHPAD'; id: string; text: string } | { type: 'EDIT_SCRATCHPAD'; id: string; text: string }
| { type: 'ADD_LORE_ENTRY'; storyId: string; entry: LoreEntry } | { type: 'ADD_LORE_ENTRY'; storyId: string; entry: LoreEntry }
| { type: 'EDIT_LORE_ENTRY'; storyId: string; entryId: string; updates: Partial<LoreEntry> } | { type: 'EDIT_LORE_ENTRY'; storyId: string; entryId: string; updates: Partial<LoreEntry> }
@ -190,7 +191,9 @@ function reducer(state: IState, action: Action): IState {
return { return {
...state, ...state,
stories: state.stories.map(s => stories: state.stories.map(s =>
s.id === action.id ? { ...s, text: action.text } : s s.id === action.id
? { ...s, text: action.text, lastEditedText: action.highlightText }
: s
), ),
}; };
} }

View File

@ -342,7 +342,7 @@ export namespace Tools {
const dispatchEdit = (text: string) => appState.dispatch( const dispatchEdit = (text: string) => appState.dispatch(
isScratchpad isScratchpad
? { type: 'EDIT_SCRATCHPAD', id: appState.currentStory!.id, text } ? { type: 'EDIT_SCRATCHPAD', id: appState.currentStory!.id, text }
: { type: 'EDIT_STORY', id: appState.currentStory!.id, text } : { type: 'EDIT_STORY', id: appState.currentStory!.id, text, highlightText: args.new_text }
); );
// Append mode: when old_text is not provided, append new_text // Append mode: when old_text is not provided, append new_text