diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/util/DocumentManager.ts | 5 | ||||
| -rw-r--r-- | src/client/views/DocComponent.tsx | 3 | ||||
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 1 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 1 | ||||
| -rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 7 | ||||
| -rw-r--r-- | src/client/views/nodes/WebBox.tsx | 6 | ||||
| -rw-r--r-- | src/client/views/pdf/AnchorMenu.tsx | 122 | 
7 files changed, 39 insertions, 106 deletions
| diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index bfe0e1b48..b9f6059f4 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -11,7 +11,6 @@ import { CollectionDockingView } from '../views/collections/CollectionDockingVie  import { TabDocView } from '../views/collections/TabDocView';  import { LightboxView } from '../views/LightboxView';  import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere, OpenWhereMod } from '../views/nodes/DocumentView'; -import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox';  import { KeyValueBox } from '../views/nodes/KeyValueBox';  import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox';  import { PresBox } from '../views/nodes/trails'; @@ -320,7 +319,9 @@ export class DocumentManager {      @action      restoreDocView(viewSpec: Opt<Doc>, docView: DocumentView, options: DocFocusOptions, contextView: Opt<DocumentView>, targetDoc: Doc) {          if (viewSpec && docView) { -            if (docView.ComponentView instanceof FormattedTextBox) docView.ComponentView?.focus(viewSpec, options); +            //if (docView.ComponentView instanceof FormattedTextBox) +            //viewSpec !== docView.rootDoc && +            docView.ComponentView?.focus?.(viewSpec, options);              PresBox.restoreTargetDocView(docView, viewSpec, options.zoomTime ?? 500);              Doc.linkFollowHighlight(viewSpec ? [docView.rootDoc, viewSpec] : docView.rootDoc, undefined, options.effect);              if (options.playMedia) docView.ComponentView?.playFrom?.(NumCast(docView.rootDoc._layout_currentTimecode)); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 6a1efdf9c..483b92957 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -139,7 +139,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()              const indocs = doc instanceof Doc ? [doc] : doc;              const docs = indocs.filter(doc => [AclEdit, AclAdmin].includes(effectiveAcl) || GetEffectiveAcl(doc) === AclAdmin); -            docs.forEach(doc => doc.annotationOn === this.props.Document && Doc.SetInPlace(doc, 'annotationOn', undefined, true)); +            // docs.forEach(doc => doc.annotationOn === this.props.Document && Doc.SetInPlace(doc, 'annotationOn', undefined, true));              const targetDataDoc = this.dataDoc;              const value = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]);              const toRemove = value.filter(v => docs.includes(v)); @@ -194,6 +194,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()                      added.forEach(doc => {                          doc._dragOnlyWithinContainer = undefined;                          if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.rootDoc; +                        else Doc.GetProto(doc).annotationOn = undefined;                          Doc.SetContainer(doc, this.rootDoc);                          inheritParentAcls(targetDataDoc, doc, true);                      }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 16d6f1270..7768ca547 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -311,6 +311,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection      focus = (anchor: Doc, options: DocFocusOptions) => {          if (this._lightboxDoc) return; +        if (anchor.type !== DocumentType.CONFIG && !DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]).includes(anchor)) return;          const xfToCollection = options?.docTransform ?? Transform.Identity();          const savedState = { panX: NumCast(this.Document[this.panXFieldKey]), panY: NumCast(this.Document[this.panYFieldKey]), scale: options?.willZoomCentered ? this.Document[this.scaleFieldKey] : undefined };          const cantTransform = this.fitContentsToBox || ((this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f7773ff18..ab99f3c6d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -121,6 +121,7 @@ export interface DocComponentView {      reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height.  However, some content views (e.g., FreeFormView w/ fitContentsToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling.      shrinkWrap?: () => void; // requests a document to display all of its contents with no white space.  currently only implemented (needed?) for freeform views      select?: (ctrlKey: boolean, shiftKey: boolean) => void; +    focus?: (textAnchor: Doc, options: DocFocusOptions) => Opt<number>;      menuControls?: () => JSX.Element; // controls to display in the top menu bar when the document is selected.      isAnyChildContentActive?: () => boolean; // is any child content of the document active      onClickScriptDisable?: () => 'never' | 'always'; // disable click scripts : never, always, or undefined = only when selected diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index f5c6a9273..a19cc3555 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -85,8 +85,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp      };      getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { +        const visibleAnchor = this._getAnchor?.(this._savedAnnotations, false); // use marquee anchor, otherwise, save zoom/pan as anchor          const anchor = -            this._getAnchor?.(this._savedAnnotations, false) ?? // use marquee anchor, otherwise, save zoom/pan as anchor +            visibleAnchor ??              Docs.Create.ConfigDocument({                  title: 'ImgAnchor:' + this.rootDoc.title,                  config_panX: NumCast(this.layoutDoc._freeform_panX), @@ -96,8 +97,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp              });          if (anchor) {              if (!addAsAnnotation) anchor.backgroundColor = 'transparent'; -            /* addAsAnnotation &&*/ this.addDocument(anchor); -            PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: true } }, this.rootDoc); +            (addAsAnnotation || visibleAnchor) && this.addDocument(anchor); +            PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: visibleAnchor ? false : true } }, this.rootDoc);              return anchor;          }          return this.rootDoc; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index f5db2ccfd..5f891e9a0 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -330,8 +330,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps                  ele.append(contents);              }          } catch (e) {} +        const visibleAnchor = this._getAnchor(this._savedAnnotations, false);          const anchor = -            this._getAnchor(this._savedAnnotations, false) ?? +            visibleAnchor ??              Docs.Create.ConfigDocument({                  title: StrCast(this.rootDoc.title + ' ' + this.layoutDoc._layout_scrollTop),                  y: NumCast(this.layoutDoc._layout_scrollTop), @@ -340,8 +341,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps          PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: pinProps?.pinData ? true : false, pannable: true } }, this.rootDoc);          anchor.text = ele?.textContent ?? '';          anchor.text_html = ele?.innerHTML; -        //addAsAnnotation && -        this.addDocumentWrapper(anchor); +        (addAsAnnotation || visibleAnchor) && this.addDocumentWrapper(anchor);          return anchor;      }; diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 6a8b06377..a52250145 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -3,7 +3,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';  import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';  import { action, computed, IReactionDisposer, observable, ObservableMap, reaction } from 'mobx';  import { observer } from 'mobx-react'; -import { EditorView } from 'prosemirror-view';  import { ColorState } from 'react-color';  import { Doc, Opt } from '../../../fields/Doc';  import { StrCast } from '../../../fields/Types'; @@ -15,68 +14,24 @@ import { AntimodeMenu, AntimodeMenuProps } from '../AntimodeMenu';  import { LinkPopup } from '../linking/LinkPopup';  import './AnchorMenu.scss';  import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup'; +import { SettingsManager } from '../../util/SettingsManager';  @observer  export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {      static Instance: AnchorMenu;      private _disposer: IReactionDisposer | undefined; -    private _disposer2: IReactionDisposer | undefined; -    private _commentCont = React.createRef<HTMLButtonElement>(); -    private _palette = [ -        'rgba(208, 2, 27, 0.8)', -        'rgba(238, 0, 0, 0.8)', -        'rgba(245, 166, 35, 0.8)', -        'rgba(248, 231, 28, 0.8)', -        'rgba(245, 230, 95, 0.616)', -        'rgba(139, 87, 42, 0.8)', -        'rgba(126, 211, 33, 0.8)', -        'rgba(65, 117, 5, 0.8)', -        'rgba(144, 19, 254, 0.8)', -        'rgba(238, 169, 184, 0.8)', -        'rgba(224, 187, 228, 0.8)', -        'rgba(225, 223, 211, 0.8)', -        'rgba(255, 255, 255, 0.8)', -        'rgba(155, 155, 155, 0.8)', -        'rgba(0, 0, 0, 0.8)', -    ]; +    private _commentRef = React.createRef<HTMLDivElement>(); +    private _cropRef = React.createRef<HTMLDivElement>();      @observable private highlightColor: string = 'rgba(245, 230, 95, 0.616)';      @observable public Status: 'marquee' | 'annotation' | '' = '';      // GPT additions -    @observable private GPTMode: GPTPopupMode = GPTPopupMode.SUMMARY;      @observable private selectedText: string = ''; -    @observable private editorView?: EditorView; -    @observable private textDoc?: Doc; -    @observable private highlightRange: number[] | undefined; -    private selectionRange: number[] | undefined; - -    @action -    setGPTMode = (mode: GPTPopupMode) => { -        this.GPTMode = mode; -    }; -      @action -    setHighlightRange(r: number[] | undefined) { -        this.highlightRange = r; -    } - -    @action -    public setSelectedText = (txt: string) => { -        this.selectedText = txt; -    }; - -    @action -    public setEditorView = (editor: EditorView) => { -        this.editorView = editor; -    }; - -    @action -    public setTextDoc = (textDoc: Doc) => { -        this.textDoc = textDoc; -    }; +    public setSelectedText = (txt: string) => (this.selectedText = txt);      public onMakeAnchor: () => Opt<Doc> = () => undefined; // Method to get anchor from text search @@ -105,20 +60,12 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {      componentWillUnmount() {          this._disposer?.(); -        this._disposer2?.();      }      componentDidMount() { -        this._disposer2 = reaction( -            () => this._opacity, -            opacity => {}, -            { fireImmediately: true } -        );          this._disposer = reaction(              () => SelectionManager.Views().slice(), -            selected => { -                AnchorMenu.Instance.fadeOut(true); -            } +            selected => AnchorMenu.Instance.fadeOut(true)          );      } @@ -129,17 +76,12 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {      gptSummarize = async (e: React.PointerEvent) => {          // move this logic to gptpopup, need to implement generate again          GPTPopup.Instance.setVisible(true); -        this.setHighlightRange(undefined);          GPTPopup.Instance.setMode(GPTPopupMode.SUMMARY);          GPTPopup.Instance.setLoading(true);          try {              const res = await gptAPICall(this.selectedText, GPTCallType.SUMMARY); -            if (res) { -                GPTPopup.Instance.setText(res); -            } else { -                GPTPopup.Instance.setText('Something went wrong.'); -            } +            GPTPopup.Instance.setText(res || 'Something went wrong.');          } catch (err) {              console.error(err);          } @@ -151,7 +93,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {              this,              e,              (e: PointerEvent) => { -                this.StartDrag(e, this._commentCont.current!); +                this.StartDrag(e, this._commentRef.current!);                  return true;              },              returnFalse, @@ -168,7 +110,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {              this,              e,              (e: PointerEvent) => { -                this.StartCropDrag(e, this._commentCont.current!); +                this.StartCropDrag(e, this._cropRef.current!);                  return true;              },              returnFalse, @@ -214,37 +156,21 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {       * all selected text available to summarize but its only supported for pdf and web ATM.       * @returns Whether the GPT icon for summarization should appear       */ -    canSummarize = (): boolean => { -        const docs = SelectionManager.Docs(); -        if (docs.length > 0) { -            return docs.some(doc => doc.type === DocumentType.PDF || doc.type === DocumentType.WEB); -        } -        return false; -    }; - -    /** -     * Returns whether the selected text can be edited. -     * @returns Whether the GPT icon for summarization should appear -     */ -    canEdit = (): boolean => { -        const docs = SelectionManager.Docs(); -        if (docs.length > 0) { -            return docs.some(doc => doc.type === 'rtf'); -        } -        return false; -    }; +    canSummarize = () => SelectionManager.Docs().some(doc => [DocumentType.PDF, DocumentType.WEB].includes(doc.type as any));      render() {          const buttons =              this.Status === 'marquee' ? (                  <>                      {this.highlighter} -                    <IconButton -                        tooltip="Drag to Place Annotation" // -                        onPointerDown={this.pointerDown} -                        icon={<FontAwesomeIcon icon="comment-alt" />} -                        color={StrCast(Doc.UserDoc().userColor)} -                    /> +                    <div ref={this._commentRef}> +                        <IconButton +                            tooltip="Drag to Place Annotation" // +                            onPointerDown={this.pointerDown} +                            icon={<FontAwesomeIcon icon="comment-alt" />} +                            color={SettingsManager.userColor} +                        /> +                    </div>                      {/* GPT Summarize icon only shows up when text is highlighted, not on marquee selection*/}                      {AnchorMenu.Instance.StartCropDrag === unimplementedFunction && this.canSummarize() && (                          <IconButton @@ -270,12 +196,14 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {                          color={StrCast(Doc.UserDoc().userColor)}                      />                      {AnchorMenu.Instance.StartCropDrag === unimplementedFunction ? null : ( -                        <IconButton -                            tooltip="Click/Drag to create cropped image" // -                            onPointerDown={this.cropDown} -                            icon={<FontAwesomeIcon icon="image" />} -                            color={StrCast(Doc.UserDoc().userColor)} -                        /> +                        <div ref={this._cropRef}> +                            <IconButton +                                tooltip="Click/Drag to create cropped image" // +                                onPointerDown={this.cropDown} +                                icon={<FontAwesomeIcon icon="image" />} +                                color={StrCast(Doc.UserDoc().userColor)} +                            /> +                        </div>                      )}                  </>              ) : ( | 
