From 543d9beeb24f59b651c76082a393418bfba96cc3 Mon Sep 17 00:00:00 2001
From: chris <kokosias@yahoo.gr>
Date: Thu, 28 Sep 2023 00:52:32 +0300
Subject: [PATCH] display soft breaks

---
 editors/demo/src/Editoria/config/config.js    |  2 +-
 .../src/AiService/AskAiContentService.js      |  7 +-
 .../src/AiService/AskAiContentTool.js         | 41 --------
 .../src/AiService/ReplaceSelectedText.js      | 50 +++++-----
 .../src/AiService/components/AskAIOverlay.js  |  3 +-
 .../src/AiService/components/AskAiButton.js   | 57 -----------
 .../AiService/components/AskAiComponent.js    | 31 ------
 .../src/AiService/replaceText.js              | 97 -------------------
 8 files changed, 29 insertions(+), 259 deletions(-)
 delete mode 100644 wax-prosemirror-services/src/AiService/AskAiContentTool.js
 delete mode 100644 wax-prosemirror-services/src/AiService/components/AskAiButton.js
 delete mode 100644 wax-prosemirror-services/src/AiService/components/AskAiComponent.js
 delete mode 100644 wax-prosemirror-services/src/AiService/replaceText.js

diff --git a/editors/demo/src/Editoria/config/config.js b/editors/demo/src/Editoria/config/config.js
index 3c828db6d..e8214f1da 100644
--- a/editors/demo/src/Editoria/config/config.js
+++ b/editors/demo/src/Editoria/config/config.js
@@ -106,7 +106,7 @@ async function DummyPromise(userInput) {
       if (userInput === 'reject') {
         reject('Your request could not be processed for now');
       } else {
-        resolve(text);
+        resolve('hello how are you?');
       }
     }, 150);
   });
diff --git a/wax-prosemirror-services/src/AiService/AskAiContentService.js b/wax-prosemirror-services/src/AiService/AskAiContentService.js
index 5d8ec89bb..86f3e5553 100644
--- a/wax-prosemirror-services/src/AiService/AskAiContentService.js
+++ b/wax-prosemirror-services/src/AiService/AskAiContentService.js
@@ -1,5 +1,4 @@
 import { Service } from 'wax-prosemirror-core';
-import AskAiContentTool from './AskAiContentTool';
 import AskAIOverlay from './components/AskAIOverlay';
 import AskAiSelectionPlugin from './plugins/AskAiSelectionPlugin';
 import './AskAiContent.css';
@@ -14,7 +13,7 @@ class AskAiContentService extends Service {
     );
 
     const createOverlay = this.container.get('CreateOverlay');
-    const config = this.config;
+    const { config } = this;
 
     // Create the overlay
     createOverlay(
@@ -29,9 +28,7 @@ class AskAiContentService extends Service {
     );
   }
 
-  register() {
-    this.container.bind('AskAiContentTool').to(AskAiContentTool);
-  }
+  register() {}
 }
 
 export default AskAiContentService;
diff --git a/wax-prosemirror-services/src/AiService/AskAiContentTool.js b/wax-prosemirror-services/src/AiService/AskAiContentTool.js
deleted file mode 100644
index 1a6bb73d6..000000000
--- a/wax-prosemirror-services/src/AiService/AskAiContentTool.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import React from 'react';
-import { v4 as uuidv4 } from 'uuid';
-import { injectable } from 'inversify';
-import { Commands, Tools } from 'wax-prosemirror-core';
-import AskAiComponent from './components/AskAiComponent';
-
-@injectable()
-class AskAiContentTool extends Tools {
-  title = 'ChatGPT';
-  name = 'ChatGPT';
-  label = '';
-
-  get run() {
-    return true;
-  }
-
-  get enable() {
-    return state => {
-      return Commands.isOnSameTextBlock(state);
-    };
-  }
-
-  select = state => {
-    return Commands.isOnSameTextBlock(state);
-  };
-
-  renderTool(view) {
-    return (
-      <AskAiComponent
-        config={this.config}
-        displayed={this.isDisplayed()}
-        item={this}
-        key={uuidv4()}
-        pmplugins={this.pmplugins}
-        view={view}
-      />
-    );
-  }
-}
-
-export default AskAiContentTool;
diff --git a/wax-prosemirror-services/src/AiService/ReplaceSelectedText.js b/wax-prosemirror-services/src/AiService/ReplaceSelectedText.js
index 0cb31337c..34f04ad17 100644
--- a/wax-prosemirror-services/src/AiService/ReplaceSelectedText.js
+++ b/wax-prosemirror-services/src/AiService/ReplaceSelectedText.js
@@ -1,53 +1,48 @@
 import { DOMParser } from 'prosemirror-model';
-import { ReplaceStep, ReplaceAroundStep } from 'prosemirror-transform';
-import { Selection, TextSelection } from 'prosemirror-state';
+import { TextSelection } from 'prosemirror-state';
 
-// To Do keep soft break
 const elementFromString = string => {
   const wrappedValue = `<body>${string}</body>`;
 
   return new window.DOMParser().parseFromString(wrappedValue, 'text/html').body;
 };
 
-const replaceSelectedText = (view, transformedText) => {
+const replaceSelectedText = (view, transformedText, replace = false) => {
   let { state } = view;
   let { tr } = state;
-
   const { from, to } = tr.selection;
+  const paragraphNodes = [];
+  const parser = DOMParser.fromSchema(state.config.schema);
 
-  // Check if 'from' and 'to' are within the document size
   if (from > state.doc.content.size || to > state.doc.content.size) {
     console.error('Position out of range');
     return;
   }
 
-  // Delete the selected text if any
-  if (from !== to) {
-    tr = tr.delete(from, to);
-  }
-
-  // Fetch the most recent state again
-  state = view.state;
-
-  const paragraphNodes = [];
-
   if (transformedText.includes('\n\n')) {
     transformedText.split('\n\n').forEach(element => {
       paragraphNodes.push(
-        state.schema.nodes.paragraph.create({}, state.schema.text(element)),
+        parser.parse(elementFromString(element.replace(/\n/g, '<br />')), {
+          preserveWhitespace: true,
+        }),
       );
     });
   }
 
-  const newText = state.schema.text(transformedText);
-
   const finalReplacementText =
-    paragraphNodes.length !== 0 ? paragraphNodes : newText;
-
-  // Replace the selected text with the new text
-  tr = tr.replaceWith(from, from, finalReplacementText); // Note: 'to' is replaced with 'from'
+    paragraphNodes.length !== 0
+      ? paragraphNodes
+      : state.schema.text(transformedText);
+
+  if (replace) {
+    if (from !== to) {
+      tr = tr.delete(from, to);
+    }
+    tr = tr.replaceWith(from, from, finalReplacementText);
+  } else {
+    tr = tr.insert(to, finalReplacementText);
+  }
 
-  // Dispatch the transaction to update the state
   view.dispatch(tr);
 
   // Fetch the most recent state again
@@ -55,7 +50,12 @@ const replaceSelectedText = (view, transformedText) => {
 
   // Update the selection to the end of the new text
   const newTo = from + transformedText.length;
-  const newSelection = TextSelection.create(state.doc, newTo + 2, newTo + 2);
+  const cursorPosition = paragraphNodes.length !== 0 ? newTo + 2 : newTo;
+  const newSelection = TextSelection.create(
+    state.doc,
+    cursorPosition,
+    cursorPosition,
+  );
   tr = state.tr.setSelection(newSelection);
 
   // Dispatch the final transaction to update the state
diff --git a/wax-prosemirror-services/src/AiService/components/AskAIOverlay.js b/wax-prosemirror-services/src/AiService/components/AskAIOverlay.js
index 1b92a26a0..cc697b9b6 100644
--- a/wax-prosemirror-services/src/AiService/components/AskAIOverlay.js
+++ b/wax-prosemirror-services/src/AiService/components/AskAIOverlay.js
@@ -158,7 +158,6 @@ const AskAIOverlay = ({ setPosition, position, config }) => {
 
     try {
       const response = await AskAiContentTransformation(combinedInput);
-      console.log(response);
       setResult(response);
       setIsSubmitted(true);
     } catch (error) {
@@ -170,7 +169,7 @@ const AskAIOverlay = ({ setPosition, position, config }) => {
   };
 
   const handleReplaceText = () => {
-    replaceSelectedText(activeView, result);
+    replaceSelectedText(activeView, result, true);
   };
 
   const discardResults = () => {
diff --git a/wax-prosemirror-services/src/AiService/components/AskAiButton.js b/wax-prosemirror-services/src/AiService/components/AskAiButton.js
deleted file mode 100644
index dfdb32275..000000000
--- a/wax-prosemirror-services/src/AiService/components/AskAiButton.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/* eslint react/prop-types: 0 */
-import React, { useContext, useMemo, useEffect } from 'react';
-import { WaxContext, DocumentHelpers, MenuButton } from 'wax-prosemirror-core';
-import { TextSelection } from 'prosemirror-state';
-
-const AskAiButton = ({ view = {}, item, AskAiContent }) => {
-  const { active, icon, label, run, select, title } = item;
-
-  const {
-    app,
-    pmViews: { main },
-    activeViewId,
-    activeView,
-  } = useContext(WaxContext);
-
-  const { state } = view;
-
-  const handleMouseDown = (e, editorState) => {
-    e.preventDefault();
-    const {
-      selection: { $from, $to },
-    } = editorState;
-    const textSelection = new TextSelection($from, $to);
-
-    const content = textSelection.content();
-
-    AskAiContent(content.content.content[0].textContent);
-  };
-
-  useEffect(() => {}, []);
-
-  const isActive = !!active(state, activeViewId);
-  let isDisabled = !select(state, activeViewId, activeView);
-
-  const isEditable = main.props.editable(editable => {
-    return editable;
-  });
-  if (!isEditable) isDisabled = true;
-
-  const AskAiButtonComponent = useMemo(
-    () => (
-      <MenuButton
-        active={isActive || false}
-        disabled={isDisabled}
-        iconName={icon}
-        label={label}
-        onMouseDown={e => handleMouseDown(e, view.state, view.dispatch)}
-        title={title}
-      />
-    ),
-    [isActive, isDisabled],
-  );
-
-  return AskAiButtonComponent;
-};
-
-export default AskAiButton;
diff --git a/wax-prosemirror-services/src/AiService/components/AskAiComponent.js b/wax-prosemirror-services/src/AiService/components/AskAiComponent.js
deleted file mode 100644
index f41275dbc..000000000
--- a/wax-prosemirror-services/src/AiService/components/AskAiComponent.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* eslint-disable react/prop-types */
-import React, { useContext } from 'react';
-import { v4 as uuidv4 } from 'uuid';
-import { WaxContext } from 'wax-prosemirror-core';
-import { isEmpty } from 'lodash';
-import replaceText from '../replaceText';
-import AskAiButton from './AskAiButton';
-
-const AskAiComponent = ({ view, displayed, config, pmplugins, item }) => {
-  const context = useContext(WaxContext);
-  if (isEmpty(view)) return null;
-
-  const AskAiContent = replaceText(
-    view,
-    config.get('config.AskAiContentService')
-      .AskAiContentTransformation,
-    pmplugins.get('AskAiContentPlaceHolder'),
-    context,
-  );
-
-  return displayed ? (
-    <AskAiButton
-      AskAiContent={AskAiContent}
-      item={item.toJSON()}
-      key={uuidv4()}
-      view={view}
-    />
-  ) : null;
-};
-
-export default AskAiComponent;
diff --git a/wax-prosemirror-services/src/AiService/replaceText.js b/wax-prosemirror-services/src/AiService/replaceText.js
deleted file mode 100644
index ca63d2574..000000000
--- a/wax-prosemirror-services/src/AiService/replaceText.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import { DOMParser } from 'prosemirror-model';
-import { ReplaceStep, ReplaceAroundStep } from 'prosemirror-transform';
-import { Selection } from 'prosemirror-state';
-
-const findPlaceholder = (state, id, placeholderPlugin) => {
-  const decos = placeholderPlugin.getState(state);
-  const found = decos.find(null, null, spec => spec.id === id);
-  return found.length ? found[0].from : null;
-};
-
-const elementFromString = string => {
-  const wrappedValue = `<body>${string}</body>`;
-
-  return new window.DOMParser().parseFromString(wrappedValue, 'text/html').body;
-};
-
-const selectionToInsertionEnd = (tr, startLen, bias) => {
-  const last = tr.steps.length - 1;
-
-  if (last < startLen) {
-    return;
-  }
-
-  const step = tr.steps[last];
-
-  if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep)) {
-    return;
-  }
-
-  const map = tr.mapping.maps[last];
-  let end = 0;
-
-  map.forEach((_from, _to, _newFrom, newTo) => {
-    if (end === 0) {
-      end = newTo;
-    }
-  });
-  tr.setSelection(Selection.near(tr.doc.resolve(end), bias));
-};
-
-export default (
-  view,
-  AskAiContentTransformation,
-  placeholderPlugin,
-  context,
-) => data => {
-  const { state } = view;
-  // A fresh object to act as the ID for this upload
-  const id = {};
-
-  // Replace the selection with a placeholder
-  const { tr } = state;
-  if (!tr.selection.empty) tr.deleteSelection();
-
-  tr.setMeta(placeholderPlugin, {
-    add: { id, pos: tr.selection.from },
-  });
-
-  view.dispatch(tr);
-
-  AskAiContentTransformation(data).then(
-    text => {
-      const pos = findPlaceholder(view.state, id, placeholderPlugin);
-
-      if (pos == null) {
-        return;
-      }
-      const parser = DOMParser.fromSchema(
-        context.pmViews.main.state.config.schema,
-      );
-      const options =
-        text.includes('<ul>') || text.includes('ol')
-          ? {}
-          : {
-              preserveWhitespace: 'full',
-            };
-      const parsedContent = parser.parse(
-        elementFromString(text.replace(/^\s+|\s+$/g, '')),
-        options,
-      );
-
-      const newTr = context.pmViews.main.state.tr;
-
-      newTr
-        .replaceWith(pos - 1, pos - 1, parsedContent)
-        .setMeta(placeholderPlugin, { remove: { id } });
-
-      selectionToInsertionEnd(newTr, newTr.steps.length - 1, 1);
-      context.pmViews.main.dispatch(newTr);
-    },
-
-    () => {
-      // On failure, just clean up the placeholder
-      view.dispatch(tr.setMeta(placeholderPlugin, { remove: { id } }));
-    },
-  );
-};
-- 
GitLab