From c6174b0e563500ea54e2ec4ce1242990a73ba8ec Mon Sep 17 00:00:00 2001
From: "yan.li" <yan.li@zoom.us>
Date: Mon, 2 Dec 2024 13:33:29 +0800
Subject: [PATCH 1/2] fix: SuggestionPlugin support Composition event

---
 .../SuggestionMenu/SuggestionPlugin.ts           | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts b/packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts
index 332b408592..fd3de537f7 100644
--- a/packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts
+++ b/packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts
@@ -163,6 +163,7 @@ const suggestionMenuPluginKey = new PluginKey("SuggestionMenuPlugin");
  * - This version hides some unnecessary complexity from the user of the plugin.
  * - This version handles key events differently
  */
+let _isComposing = false;
 export class SuggestionMenuProseMirrorPlugin<
   BSchema extends BlockSchema,
   I extends InlineContentSchema,
@@ -197,6 +198,9 @@ export class SuggestionMenuProseMirrorPlugin<
 
         // Apply changes to the plugin state from an editor transaction.
         apply(transaction, prev, _oldState, newState): SuggestionPluginState {
+          if (_isComposing) {
+            return prev;
+          }
           // TODO: More clearly define which transactions should be ignored.
           if (transaction.getMeta("orderedListIndexing") !== undefined) {
             return prev;
@@ -271,6 +275,18 @@ export class SuggestionMenuProseMirrorPlugin<
       },
 
       props: {
+        handleDOMEvents:{
+          compositionstart:(view)=>{
+            _isComposing = true;
+            view.dispatch(view.state.tr.setMeta("isComposing", true));
+            return false;
+          },
+          compositionend:(view)=>{
+            _isComposing = false;
+            view.dispatch(view.state.tr.setMeta("isComposing", false));
+            return false;
+          }
+        },
         handleTextInput(view, _from, _to, text) {
           const suggestionPluginState: SuggestionPluginState = (
             this as Plugin

From b3a91c5b468b927a5feb8b3da57617b25f2158bf Mon Sep 17 00:00:00 2001
From: "yan.li" <yan.li@zoom.us>
Date: Tue, 3 Dec 2024 14:07:51 +0800
Subject: [PATCH 2/2] fix: safari selection change in composition event

---
 .../SuggestionMenu/SuggestionPlugin.ts        | 31 +++++++++++++------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts b/packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts
index fd3de537f7..64179324d0 100644
--- a/packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts
+++ b/packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts
@@ -164,6 +164,7 @@ const suggestionMenuPluginKey = new PluginKey("SuggestionMenuPlugin");
  * - This version handles key events differently
  */
 let _isComposing = false;
+let _compositionEndFlag = false;
 export class SuggestionMenuProseMirrorPlugin<
   BSchema extends BlockSchema,
   I extends InlineContentSchema,
@@ -198,9 +199,6 @@ export class SuggestionMenuProseMirrorPlugin<
 
         // Apply changes to the plugin state from an editor transaction.
         apply(transaction, prev, _oldState, newState): SuggestionPluginState {
-          if (_isComposing) {
-            return prev;
-          }
           // TODO: More clearly define which transactions should be ignored.
           if (transaction.getMeta("orderedListIndexing") !== undefined) {
             return prev;
@@ -247,7 +245,8 @@ export class SuggestionMenuProseMirrorPlugin<
           // Checks if the menu should be hidden.
           if (
             // Highlighting text should hide the menu.
-            newState.selection.from !== newState.selection.to ||
+            // In safari,when in composition event,this condition will match.
+            (!_isComposing && newState.selection.from !== newState.selection.to) ||
             // Transactions with plugin metadata should hide the menu.
             suggestionPluginTransactionMeta === null ||
             // Certain mouse events should hide the menu.
@@ -265,10 +264,22 @@ export class SuggestionMenuProseMirrorPlugin<
           const next = { ...prev };
 
           // Updates the current query.
-          next.query = newState.doc.textBetween(
-            prev.queryStartPos!,
-            newState.selection.from
-          );
+          if(_compositionEndFlag){
+            _compositionEndFlag = false
+            next.query = newState.doc.textBetween(
+              prev.queryStartPos!,
+              newState.selection.from
+            );
+            return next;
+          }
+          if(!_isComposing)
+          {
+            next.query = newState.doc.textBetween(
+              prev.queryStartPos!,
+              newState.selection.from
+            );
+            return next;
+          }
 
           return next;
         },
@@ -276,13 +287,13 @@ export class SuggestionMenuProseMirrorPlugin<
 
       props: {
         handleDOMEvents:{
-          compositionstart:(view)=>{
+          compositionstart:()=>{
             _isComposing = true;
-            view.dispatch(view.state.tr.setMeta("isComposing", true));
             return false;
           },
           compositionend:(view)=>{
             _isComposing = false;
+            _compositionEndFlag = true;
             view.dispatch(view.state.tr.setMeta("isComposing", false));
             return false;
           }