aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/FormattedTextBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/formattedText/FormattedTextBox.tsx')
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx48
1 files changed, 33 insertions, 15 deletions
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index e354aedb7..9f2a9b8e1 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -181,6 +181,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
@observable
private gptRes: string = '';
+ public makeAIFlashcards: () => void = unimplementedFunction;
+ public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
+
public static PasteOnLoad: ClipboardEvent | undefined;
public static DontSelectInitialText = false; // whether initial text should be selected or not
public static SelectOnLoadChar = '';
@@ -240,7 +243,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
@action
setupAnchorMenu = () => {
AnchorMenu.Instance.Status = 'marquee';
-
AnchorMenu.Instance.OnClick = () => {
!this.layoutDoc.layout_showSidebar && this.toggleSidebar();
setTimeout(() => this._sidebarRef.current?.anchorMenuClick(this.makeLinkAnchor(undefined, OpenWhere.addRight, undefined, 'Anchored Selection', true))); // give time for sidebarRef to be created
@@ -292,6 +294,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.DocumentView?.()!, () => this.getAnchor(true), targetCreator), e.pageX, e.pageY);
});
+
+ AnchorMenu.Instance.setSelectedText(window.getSelection()?.toString() ?? '');
const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to);
this._props.rootSelected?.() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom);
let ele: Opt<HTMLDivElement>;
@@ -319,7 +323,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
return '';
};
dispatchTransaction = (tx: Transaction) => {
- if (this._editorView) {
+ if (this._editorView && !this._editorView.isDestroyed) {
const state = this._editorView.state.apply(tx);
this._editorView.updateState(state);
this.tryUpdateDoc(false);
@@ -352,6 +356,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
let unchanged = true;
const textChange = newText !== prevData?.Text; // the Text string can change even if the RichText doesn't because dashFieldViews may return new strings as the data they reference changes
+ const rtField = (layoutData !== prevData ? layoutData : undefined) ?? protoData;
if (this._applyingChange !== this.fieldKey && (force || textChange || removeSelection(newJson) !== removeSelection(prevData?.Data))) {
this._applyingChange = this.fieldKey;
textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now())));
@@ -365,10 +370,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
this._applyingChange = ''; // turning this off here allows a Doc to retrieve data from template if noTemplate below is changed to false
unchanged = false;
}
- } else {
+ } else if (rtField) {
// if we've deleted all the text in a note driven by a template, then restore the template data
dataDoc[this.fieldKey] = undefined;
- this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(((layoutData !== prevData ? layoutData : undefined) ?? protoData)?.Data)));
+ this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(rtField.Data)));
ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, text: newText });
unchanged = false;
}
@@ -916,6 +921,17 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
},
icon: !this.Document._layout_enableAltContentUI ? 'eye-slash' : 'eye',
});
+ if (this.Document._layout_enableAltContentUI) {
+ const usepath = this.layoutDoc[`_${this._props.fieldKey}_usePath`];
+ appearanceItems.push({
+ description: (this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate:hover' ? 'no hover' : 'hover') + ' to show alt content',
+ event: () => {
+ this.layoutDoc[`_${this._props.fieldKey}_usePath`] = usepath === 'alternate' || usepath === undefined ? 'alternate:hover' : undefined;
+ },
+ icon: !this.Document._layout_enableAltContentUI ? 'eye-slash' : 'eye',
+ });
+ }
+
!Doc.noviceMode && appearanceItems.push({ description: 'Show Highlights...', noexpand: true, subitems: highlighting, icon: 'hand-point-right' });
!Doc.noviceMode &&
appearanceItems.push({
@@ -953,7 +969,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
icon: 'star',
});
optionItems.push({ description: `Generate Dall-E Image`, event: () => this.generateImage(), icon: 'star' });
- optionItems.push({ description: `Ask GPT-3`, event: () => this.askGPT(), icon: 'lightbulb' });
+ optionItems.push({ description: `Make AI Flashcards`, event: () => this.makeAIFlashcards(), icon: 'lightbulb' });
+ optionItems.push({ description: `Ask GPT-3`, event: this.askGPT, icon: 'lightbulb' });
this._props.renderDepth &&
optionItems.push({
description: !this.Document._createDocOnCR ? 'Create New Doc on Carriage Return' : 'Allow Carriage Returns',
@@ -987,6 +1004,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
askGPT = action(async () => {
try {
+ GPTPopup.Instance.setSidebarId(this.SidebarKey);
+ GPTPopup.Instance.addDoc = this.sidebarAddDocument;
const res = await gptAPICall((this.dataDoc.text as RichTextField)?.Text, GPTCallType.COMPLETION);
if (!res) {
this.animateRes(0, 'Something went wrong.');
@@ -1571,7 +1590,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
e.preventDefault();
}
};
- onSelectEnd = (): void => document.removeEventListener('pointerup', this.onSelectEnd);
+ onSelectEnd = () => {
+ GPTPopup.Instance.setSidebarId(this.SidebarKey);
+ GPTPopup.Instance.addDoc = this.sidebarAddDocument;
+ document.removeEventListener('pointerup', this.onSelectEnd);
+ };
onPointerUp = (e: React.PointerEvent): void => {
const state = this.EditorView?.state;
if (state && this.ProseRef?.children[0].className.includes('-focused') && this._props.isContentActive() && !e.button) {
@@ -1953,10 +1976,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
<div className="dash-tooltip">
toggle (%/) between
<span style={{ color: usePath === undefined ? 'black' : undefined }}>
- <em> primary, </em>
+ <em> primary </em>
</span>
+ and
<span style={{ color: usePath === 'alternate' ? 'black' : undefined }}>
- <em>alternate, </em>
+ <em>alternate </em>
</span>
and show
<span style={{ color: usePath === 'alternate:hover' ? 'black' : undefined }}>
@@ -1982,9 +2006,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
@computed get _fieldKey() {
const usePath = this._props.ignoreUsePath ? '' : StrCast(this.layoutDoc[`${this._props.fieldKey}_usePath`]);
- return this._props.fieldKey + (usePath && (!usePath.includes(':hover') || this._isHovering || this._props.isContentActive()) ? `_${usePath.replace(':hover', '')}` : '');
+ return this._props.fieldKey + (usePath && (!usePath.includes(':hover') || this._props.isHovering?.() || this._props.isContentActive()) ? `_${usePath.replace(':hover', '')}` : '');
}
- @observable _isHovering = false;
onPassiveWheel = (e: WheelEvent) => {
if (e.clientX > this.ProseRef!.getBoundingClientRect().right) {
return;
@@ -2030,11 +2053,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
return styleFromLayout?.height === '0px' ? null : (
<div
className="formattedTextBox"
- onPointerEnter={action(() => {
- this._isHovering = true;
- this.layoutDoc[`_${this._props.fieldKey}_usePath`] && (this.Document.isHovering = true);
- })}
- onPointerLeave={action(() => { this.Document.isHovering = this._isHovering = false; })} // prettier-ignore
ref={r => {
this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
this._oldWheel = r;