11import { toast } from "@renderer/utils/toast" ;
22import { useEditor } from "@tiptap/react" ;
3- import { useCallback , useRef } from "react" ;
3+ import { useCallback , useRef , useState } from "react" ;
44import type { MentionChip } from "../utils/content" ;
55import { contentToXml } from "../utils/content" ;
66import { getEditorExtensions } from "./extensions" ;
@@ -21,6 +21,7 @@ export interface UseTiptapEditorOptions {
2121 onSubmit ?: ( text : string ) => void ;
2222 onBashCommand ?: ( command : string ) => void ;
2323 onBashModeChange ?: ( isBashMode : boolean ) => void ;
24+ onEmptyChange ?: ( isEmpty : boolean ) => void ;
2425}
2526
2627const EDITOR_CLASS =
@@ -38,6 +39,7 @@ export function useTiptapEditor(options: UseTiptapEditorOptions) {
3839 onSubmit,
3940 onBashCommand,
4041 onBashModeChange,
42+ onEmptyChange,
4143 } = options ;
4244
4345 const {
@@ -46,13 +48,27 @@ export function useTiptapEditor(options: UseTiptapEditorOptions) {
4648 bashMode : enableBashMode = true ,
4749 } = capabilities ;
4850
49- const callbackRefs = useRef ( { onSubmit, onBashCommand, onBashModeChange } ) ;
50- callbackRefs . current = { onSubmit, onBashCommand, onBashModeChange } ;
51+ const callbackRefs = useRef ( {
52+ onSubmit,
53+ onBashCommand,
54+ onBashModeChange,
55+ onEmptyChange,
56+ } ) ;
57+ callbackRefs . current = {
58+ onSubmit,
59+ onBashCommand,
60+ onBashModeChange,
61+ onEmptyChange,
62+ } ;
5163
5264 const prevBashModeRef = useRef ( false ) ;
65+ const prevIsEmptyRef = useRef ( true ) ;
5366 const submitRef = useRef < ( ) => void > ( ( ) => { } ) ;
5467 const draftRef = useRef < ReturnType < typeof useDraftSync > | null > ( null ) ;
5568
69+ // Track isEmpty state to trigger re-renders when content changes
70+ const [ isEmptyState , setIsEmptyState ] = useState ( true ) ;
71+
5672 const handleCommandSubmit = useCallback ( ( text : string ) => {
5773 callbackRefs . current . onSubmit ?.( text ) ;
5874 } , [ ] ) ;
@@ -86,15 +102,30 @@ export function useTiptapEditor(options: UseTiptapEditorOptions) {
86102 return false ;
87103 } ,
88104 } ,
105+ onCreate : ( { editor : e } ) => {
106+ const newIsEmpty = ! e . getText ( ) . trim ( ) ;
107+ setIsEmptyState ( newIsEmpty ) ;
108+ prevIsEmptyRef . current = newIsEmpty ;
109+ callbackRefs . current . onEmptyChange ?.( newIsEmpty ) ;
110+ } ,
89111 onUpdate : ( { editor : e } ) => {
90112 const text = e . getText ( ) ;
113+ const trimmedText = text . trim ( ) ;
91114 const newBashMode = enableBashMode && text . trimStart ( ) . startsWith ( "!" ) ;
92115
93116 if ( newBashMode !== prevBashModeRef . current ) {
94117 prevBashModeRef . current = newBashMode ;
95118 callbackRefs . current . onBashModeChange ?.( newBashMode ) ;
96119 }
97120
121+ const newIsEmpty = ! trimmedText ;
122+ setIsEmptyState ( newIsEmpty ) ;
123+
124+ if ( newIsEmpty !== prevIsEmptyRef . current ) {
125+ prevIsEmptyRef . current = newIsEmpty ;
126+ callbackRefs . current . onEmptyChange ?.( newIsEmpty ) ;
127+ }
128+
98129 draftRef . current ?. saveDraft ( e ) ;
99130 } ,
100131 } ,
@@ -159,7 +190,7 @@ export function useTiptapEditor(options: UseTiptapEditorOptions) {
159190 [ editor , draft ] ,
160191 ) ;
161192
162- const isEmpty = ! editor || editor . isEmpty ;
193+ const isEmpty = ! editor || isEmptyState ;
163194 const isBashMode =
164195 enableBashMode && ( editor ?. getText ( ) . trimStart ( ) . startsWith ( "!" ) ?? false ) ;
165196
0 commit comments