aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/formattedText/DailyJournal.tsx64
1 files changed, 52 insertions, 12 deletions
diff --git a/src/client/views/nodes/formattedText/DailyJournal.tsx b/src/client/views/nodes/formattedText/DailyJournal.tsx
index 697cf4a2a..da96b8b2f 100644
--- a/src/client/views/nodes/formattedText/DailyJournal.tsx
+++ b/src/client/views/nodes/formattedText/DailyJournal.tsx
@@ -8,12 +8,15 @@ import { FormattedTextBox, FormattedTextBoxProps } from './FormattedTextBox';
import { gptAPICall, GPTCallType, gptImageLabel } from '../../../apis/gpt/GPT';
import { RichTextField } from '../../../../fields/RichTextField';
import { TextSelection } from 'prosemirror-state';
+import { Plugin } from 'prosemirror-state';
export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@observable journalDate: string;
@observable typingTimeout: NodeJS.Timeout | null = null; // Track typing delay
@observable lastUserText: string = ''; // Store last user-entered text
_ref = React.createRef<FormattedTextBox>(); // reference to the formatted textbox
+ predictiveTextRange: { from: number; to: number } | null = null; // where predictive text starts and ends
+ private predictiveText: string | null = ' ... why?';
public static LayoutString(fieldStr: string) {
return FieldView.LayoutString(DailyJournal, fieldStr);
@@ -89,19 +92,11 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>()
const editorView = this._ref.current?.EditorView;
if (!editorView) return;
- const { state } = editorView;
- const currentText = state.doc.textBetween(0, state.doc.content.size);
-
- // Store the last user text (before adding the prediction)
- this.lastUserText = currentText;
-
- // If user types, clear any existing timeout
if (this.typingTimeout) clearTimeout(this.typingTimeout);
- // Set a new timeout to add predictive text after 3.5 seconds
this.typingTimeout = setTimeout(() => {
this.insertPredictiveQuestion();
- }, 3500); // 3.5 seconds
+ }, 3500);
};
/**
@@ -115,12 +110,11 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>()
const { state, dispatch } = editorView;
const { schema } = state;
const { from, to } = state.selection;
- const insertPos = from === to ? from : to; // cursor position
+ const insertPos = to; // cursor position
const resolvedPos = state.doc.resolve(insertPos);
const parentNode = resolvedPos.parent;
const indexInParent = resolvedPos.index();
-
const isAtEndOfParent = indexInParent >= parentNode.childCount;
// Check if there's a line break or paragraph node after the current position
@@ -140,11 +134,50 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>()
const fontItalicsMark = schema.marks.em.create();
// styled text node
- const predictedText = schema.text(' ... why?', [fontSizeMark, fontColorMark, fontItalicsMark]);
+ const text = ' ... why?';
+ const predictedText = schema.text(text, [fontSizeMark, fontColorMark, fontItalicsMark]);
// Insert styled text at cursor position
const transaction = state.tr.insert(insertPos, predictedText);
dispatch(transaction);
+
+ this.predictiveText = text;
+ };
+
+ createPredictiveCleanupPlugin = () => {
+ return new Plugin({
+ view: () => {
+ return {
+ update: (view, prevState) => {
+ const { state, dispatch } = view;
+ if (!this.predictiveText) return;
+
+ // Check if doc or selection changed
+ if (!prevState.doc.eq(state.doc) || !prevState.selection.eq(state.selection)) {
+ let found = false;
+ const textToRemove = this.predictiveText;
+
+ state.doc.descendants((node, pos) => {
+ if (node.isText && node.text === textToRemove) {
+ // Remove the predictive text node
+ const tr = state.tr.delete(pos, pos + node.nodeSize);
+ dispatch(tr);
+ this.predictiveText = null;
+ found = true;
+ return false; // stop traversal
+ }
+ return true;
+ });
+
+ if (!found) {
+ // fallback cleanup
+ this.predictiveText = null;
+ }
+ }
+ },
+ };
+ },
+ });
};
componentDidMount(): void {
@@ -154,6 +187,13 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>()
const editorView = this._ref.current?.EditorView;
if (editorView) {
editorView.dom.addEventListener('input', this.onTextInput);
+
+ // Add plugin to state if not already added
+ const cleanupPlugin = this.createPredictiveCleanupPlugin();
+ const newState = editorView.state.reconfigure({
+ plugins: [...editorView.state.plugins, cleanupPlugin],
+ });
+ editorView.updateState(newState);
}
const rawText = (this.Document.text as any)?.Text ?? '';