diff options
Diffstat (limited to 'src/client/views')
35 files changed, 260 insertions, 374 deletions
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index b53379435..c2cbca3e1 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -96,7 +96,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select <div className={`contextMenu-item-background`} style={{ - background: SettingsManager.Instance.userColor, + background: SettingsManager.userColor, }} /> </div> @@ -112,7 +112,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select style={{ marginLeft: window.innerHeight - this._overPosX - 50 > 0 ? '90%' : '20%', marginTop, - background: SettingsManager.Instance.userBackgroundColor, + background: SettingsManager.userBackgroundColor, }}> {this._items.map(prop => ( <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} /> @@ -146,7 +146,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select <div className={`contextMenu-item-background`} style={{ - background: SettingsManager.Instance.userColor, + background: SettingsManager.userColor, }} /> {submenu} diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 90425f264..3018dad79 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -57,7 +57,6 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P @observable private _editingTitle = false; @observable private _hidden = false; @observable public AddToSelection = false; // if Shift is pressed, then this should be set so that clicking on the selection background is ignored so overlapped documents can be added to the selection set. - @observable public Interacting = false; @observable public pushIcon: IconProp = 'arrow-alt-circle-up'; @observable public pullIcon: IconProp = 'arrow-alt-circle-down'; @observable public pullColor: string = 'white'; @@ -330,7 +329,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P */ @action onRadiusDown = (e: React.PointerEvent): void => { - this._isRounding = DocumentDecorations.Instance.Interacting = true; + this._isRounding = DocumentView.Interacting = true; this._resizeUndo = UndoManager.StartBatch('DocDecs set radius'); // Call util move event function setupMoveUpEvents( @@ -353,7 +352,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P return false; }, // moveEvent action(e => { - DocumentDecorations.Instance.Interacting = this._isRounding = false; + DocumentView.Interacting = this._isRounding = false; this._resizeUndo?.end(); }), // upEvent e => {}, // clickEvent, @@ -478,7 +477,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P @action onPointerDown = (e: React.PointerEvent): void => { setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction); - this.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them + DocumentView.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them this._resizeHdlId = e.currentTarget.className; const bounds = e.currentTarget.getBoundingClientRect(); this._offX = this._resizeHdlId.toLowerCase().includes('left') ? bounds.right - e.clientX : bounds.left - e.clientX; @@ -688,7 +687,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P @action onPointerUp = (e: PointerEvent): void => { this._resizeHdlId = ''; - this.Interacting = false; + DocumentView.Interacting = false; this._resizeUndo?.end(); SnappingManager.clearSnapLines(); @@ -895,7 +894,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P height: bounds.b - bounds.y + this._resizeBorderWidth + 'px', left: bounds.x - this._resizeBorderWidth / 2, top: bounds.y - this._resizeBorderWidth / 2, - pointerEvents: DocumentDecorations.Instance.AddToSelection || this.Interacting ? 'none' : 'all', + pointerEvents: DocumentDecorations.Instance.AddToSelection || DocumentView.Interacting ? 'none' : 'all', display: SelectionManager.Views().length <= 1 || hideDecorations ? 'none' : undefined, }} onPointerDown={this.onBackgroundDown} diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index d60617020..147921596 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -6,7 +6,6 @@ import { ObjectField } from '../../fields/ObjectField'; import './EditableView.scss'; import { DocumentIconContainer } from './nodes/DocumentIcon'; import { OverlayView } from './OverlayView'; -import { EditableText } from 'browndash-components'; export interface EditableProps { /** diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 11c2fc86c..b61ff35c7 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -1,23 +1,20 @@ import React = require('react'); import { action, computed, observable, ObservableMap } from 'mobx'; import { observer } from 'mobx-react'; +import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider'; +import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai'; +import { CiCircleRemove } from 'react-icons/ci'; import Select from 'react-select'; -import { Checkbox, Tooltip } from '@material-ui/core'; import { Doc, DocListCast, Field, StrListCast } from '../../fields/Doc'; import { RichTextField } from '../../fields/RichTextField'; -import { StrCast } from '../../fields/Types'; +import { DocumentOptions, FInfo } from '../documents/Documents'; import { DocumentManager } from '../util/DocumentManager'; import { UserOptions } from '../util/GroupManager'; +import { SearchUtil } from '../util/SearchUtil'; +import { undoable } from '../util/UndoManager'; import './FilterPanel.scss'; import { FieldView } from './nodes/FieldView'; -import { SearchBox } from './search/SearchBox'; -import { undoable } from '../util/UndoManager'; -import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai'; -import { CiCircleRemove } from 'react-icons/ci'; -import { Slider, Rail, Handles, Tracks, Ticks } from 'react-compound-slider'; -import { TooltipRail, Handle, Tick, Track } from './nodes/SliderBox-components'; -import { DocumentOptions, FInfo } from '../documents/Documents'; -import { string32 } from 'pdfjs-dist/types/src/shared/util'; +import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components'; interface filterProps { rootDoc: Doc; @@ -49,7 +46,7 @@ export class FilterPanel extends React.Component<filterProps> { const allDocs = new Set<Doc>(); const targetDoc = this.targetDoc; if (targetDoc) { - SearchBox.foreachRecursiveDoc([this.targetDoc], (depth, doc) => allDocs.add(doc)); + SearchUtil.foreachRecursiveDoc([this.targetDoc], (depth, doc) => allDocs.add(doc)); } console.log('this is all Docs' + Array.from(allDocs)); return Array.from(allDocs); @@ -62,7 +59,7 @@ export class FilterPanel extends React.Component<filterProps> { const noviceFields = [...noviceReqFields, ...noviceLayoutFields]; const keys = new Set<string>(noviceFields); - this.allDocs.forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key))); + this.allDocs.forEach(doc => SearchUtil.documentKeys(doc).filter(key => keys.add(key))); const sortedKeys = Array.from(keys.keys()) .filter(key => key[0]) .filter(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || noviceFields.includes(key) || !Doc.noviceMode) @@ -236,7 +233,7 @@ export class FilterPanel extends React.Component<filterProps> { facetValues = (facetHeader: string) => { const allCollectionDocs = new Set<Doc>(); - SearchBox.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); + SearchUtil.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); const set = new Set<string>([String.fromCharCode(127) + '--undefined--']); if (facetHeader === 'tags') allCollectionDocs.forEach(child => diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index afb76b9ac..8f081b321 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -16,7 +16,6 @@ import { CollectionStackedTimeline } from './collections/CollectionStackedTimeli import { TabDocView } from './collections/TabDocView'; import { GestureOverlay } from './GestureOverlay'; import './LightboxView.scss'; -import { MainView } from './MainView'; import { DocumentView, OpenWhere, OpenWhereMod } from './nodes/DocumentView'; import { DefaultStyleProvider, wavyBorderPath } from './StyleProvider'; @@ -61,7 +60,7 @@ export class LightboxView extends React.Component<LightboxViewProps> { this._childFilters && (this._childFilters.length = 0); this._future = this._history = []; Doc.ActiveTool = InkTool.None; - MainView.Instance._exploreMode = false; + DocumentView.ExploreMode = false; } else { const l = DocUtils.MakeLinkToActiveAudio(() => doc).lastElement(); l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen'); @@ -270,7 +269,7 @@ export class LightboxView extends React.Component<LightboxViewProps> { addDocTab={this.addDocTab} pinToPres={TabDocView.PinDoc} bringToFront={emptyFunction} - onBrowseClick={MainView.Instance.exploreMode} + onBrowseClick={DocumentView.exploreMode} focus={emptyFunction} /> </GestureOverlay> @@ -335,12 +334,12 @@ export class LightboxView extends React.Component<LightboxViewProps> { <div className="lightboxView-exploreBtn" title="toggle explore mode to navigate among documents only" - style={{ background: MainView.Instance._exploreMode ? 'white' : undefined }} + style={{ background: DocumentView.ExploreMode ? 'white' : undefined }} onClick={action(e => { e.stopPropagation(); - MainView.Instance._exploreMode = !MainView.Instance._exploreMode; + DocumentView.ExploreMode = !DocumentView.ExploreMode; })}> - <FontAwesomeIcon color={MainView.Instance._exploreMode ? 'black' : 'white'} icon={'globe-americas'} size="2x" /> + <FontAwesomeIcon color={DocumentView.ExploreMode ? 'black' : 'white'} icon={'globe-americas'} size="2x" /> </div> </div> ); diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 6dd1d53ee..a04309d0c 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -2,18 +2,18 @@ // (module as any).hot.accept(); // } +import * as dotenv from 'dotenv'; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import { AssignAllExtensions } from '../../extensions/General/Extensions'; import { FieldLoader } from '../../fields/FieldLoader'; import { CurrentUserUtils } from '../util/CurrentUserUtils'; +import { PingManager } from '../util/PingManager'; import { ReplayMovements } from '../util/ReplayMovements'; import { TrackMovements } from '../util/TrackMovements'; import { CollectionView } from './collections/CollectionView'; -import { MainView } from './MainView'; -import * as dotenv from 'dotenv'; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import -import { PingManager } from '../util/PingManager'; import './global/globalScripts'; +import { MainView } from './MainView'; dotenv.config(); AssignAllExtensions(); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 6a743a5e6..dde04dcc0 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -9,7 +9,6 @@ import { observer } from 'mobx-react'; import 'normalize.css'; import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; -import { ScriptField } from '../../fields/ScriptField'; import { DocCast, StrCast } from '../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; @@ -77,7 +76,6 @@ export class MainView extends React.Component { public static Live: boolean = false; private _docBtnRef = React.createRef<HTMLDivElement>(); - @observable public LastButton: Opt<Doc>; @observable private _windowWidth: number = 0; @observable private _windowHeight: number = 0; @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) @@ -529,7 +527,6 @@ export class MainView extends React.Component { window.addEventListener('beforeunload', DocServer.UPDATE_SERVER_CACHE); window.addEventListener('drop', e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page window.addEventListener('dragover', e => e.preventDefault(), false); - // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined)); document.addEventListener('pointerdown', this.globalPointerDown, true); document.addEventListener('pointermove', this.globalPointerMove, true); document.addEventListener('pointerup', this.globalPointerClick, true); @@ -572,11 +569,7 @@ export class MainView extends React.Component { Doc.AddDocToList(Doc.MyFilesystem, 'data', folder); }; - @observable _exploreMode = false; - @computed get exploreMode() { - return () => (this._exploreMode ? ScriptField.MakeScript('CollectionBrowseClick(documentView, clientX, clientY)', { documentView: 'any', clientX: 'number', clientY: 'number' })! : undefined); - } - waitForDoubleClick = () => (this._exploreMode ? 'never' : undefined); + waitForDoubleClick = () => (DocumentView.ExploreMode ? 'never' : undefined); headerBarScreenXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.headerBarDocHeight(), 1); mainScreenToLocalXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.topOfMainDocContent, 1); addHeaderDoc = (doc: Doc | Doc[], annotationKey?: string) => (doc instanceof Doc ? [doc] : doc).reduce((done, doc) => Doc.AddDocToList(this.headerBarDoc, 'data', doc), true); @@ -747,7 +740,7 @@ export class MainView extends React.Component { @computed get leftMenuPanel() { return ( - <div key="menu" className="mainView-leftMenuPanel" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), display: LightboxView.LightboxDoc ? 'none' : undefined }}> + <div key="menu" className="mainView-leftMenuPanel" style={{ background: SettingsManager.userBackgroundColor, display: LightboxView.LightboxDoc ? 'none' : undefined }}> <DocumentView Document={Doc.MyLeftSidebarMenu} DataDoc={undefined} @@ -804,16 +797,16 @@ export class MainView extends React.Component { {this.flyout} <div className="mainView-libraryHandle" - style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }} + style={{ background: SettingsManager.userBackgroundColor, left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }} onPointerDown={this.onFlyoutPointerDown}> - <FontAwesomeIcon icon="chevron-left" color={StrCast(Doc.UserDoc().userColor)} style={{ opacity: '50%' }} size="sm" /> + <FontAwesomeIcon icon="chevron-left" color={SettingsManager.userColor} style={{ opacity: '50%' }} size="sm" /> </div> <div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)` }}> {this.dockingContent} {this._hideUI ? null : ( - <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), right: this.propertiesWidth() - 1 }}> - <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={StrCast(Doc.UserDoc().userColor)} size="sm" /> + <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userBackgroundColor, right: this.propertiesWidth() - 1 }}> + <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" /> </div> )} <div className="properties-container" style={{ width: this.propertiesWidth() }}> @@ -857,11 +850,11 @@ export class MainView extends React.Component { //setTimeout(action(() => (this._leftMenuFlyoutWidth += 0.5))); this._sidebarContent.proto = DocCast(button.target); - this.LastButton = button; + DocumentView.LastPressedSidebarBtn = button; }); closeFlyout = action(() => { - this.LastButton = undefined; + DocumentView.LastPressedSidebarBtn = undefined; this._panelContent = 'none'; this._sidebarContent.proto = undefined; this._leftMenuFlyoutWidth = 0; @@ -879,7 +872,7 @@ export class MainView extends React.Component { @computed get docButtons() { return !Doc.MyDockedBtns ? null : ( - <div className="mainView-docButtons" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }} ref={this._docBtnRef}> + <div className="mainView-docButtons" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }} ref={this._docBtnRef}> <CollectionLinearView Document={Doc.MyDockedBtns} DataDoc={undefined} @@ -998,8 +991,8 @@ export class MainView extends React.Component { <div className={`mainView-container ${this.colorScheme}`} style={{ - color: StrCast(Doc.UserDoc().userColor), - background: StrCast(Doc.UserDoc().userBackgroundColor), + color: SettingsManager.userColor, + background: SettingsManager.userBackgroundColor, }} onScroll={() => (ele => (ele.scrollTop = ele.scrollLeft = 0))(document.getElementById('root')!)} ref={r => { @@ -1068,3 +1061,12 @@ export class MainView extends React.Component { ScriptingGlobals.add(function selectMainMenu(doc: Doc, title: string) { MainView.Instance.selectMenu(doc); }); +ScriptingGlobals.add(function createNewPresentation() { + return MainView.Instance.createNewPresentation(); +}, 'creates a new presentation when called'); +ScriptingGlobals.add(function openPresentation(pres: Doc) { + return MainView.Instance.openPresentation(pres); +}, 'creates a new presentation when called'); +ScriptingGlobals.add(function createNewFolder() { + return MainView.Instance.createNewFolder(); +}, 'creates a new folder in myFiles when called'); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 4fe6847c3..83bd1b860 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -188,7 +188,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { }); rows.push( - <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: SettingsManager.Instance.userBackgroundColor, textAlign: 'center' }}> + <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: SettingsManager.userBackgroundColor, textAlign: 'center' }}> <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} /> </div> ); @@ -1664,7 +1664,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-title" style={{ width: this.props.width }}> Properties <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}> - <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.Instance.userColor} /> + <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.userColor} /> </div> </div> </div> @@ -1706,8 +1706,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))} style={{ - color: SettingsManager.Instance.userColor, - backgroundColor: this.openPresTransitions ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor, + color: SettingsManager.userColor, + backgroundColor: this.openPresTransitions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor, }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Transitions <div className="propertiesView-presentationTrails-title-icon"> @@ -1723,8 +1723,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openPresVisibilityAndDuration = !this.openPresVisibilityAndDuration))} style={{ - color: SettingsManager.Instance.userColor, - backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor, + color: SettingsManager.userColor, + backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor, }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Visibilty <div className="propertiesView-presentationTrails-title-icon"> @@ -1740,8 +1740,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))} style={{ - color: SettingsManager.Instance.userColor, - backgroundColor: this.openPresProgressivize ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor, + color: SettingsManager.userColor, + backgroundColor: this.openPresProgressivize ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor, }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Progressivize <div className="propertiesView-presentationTrails-title-icon"> @@ -1757,8 +1757,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))} style={{ - color: SettingsManager.Instance.userColor, - backgroundColor: this.openSlideOptions ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor, + color: SettingsManager.userColor, + backgroundColor: this.openSlideOptions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor, }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'} <div className="propertiesView-presentationTrails-title-icon"> diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index c48a7241a..f3452c780 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -9,11 +9,11 @@ import { emptyFunction, returnAll, returnFalse, returnOne, returnTrue, returnZer import { Docs, DocUtils } from '../documents/Documents'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { LinkManager } from '../util/LinkManager'; +import { SearchUtil } from '../util/SearchUtil'; import { Transform } from '../util/Transform'; import { CollectionStackingView } from './collections/CollectionStackingView'; import { FieldViewProps } from './nodes/FieldView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import { SearchBox } from './search/SearchBox'; import './SidebarAnnos.scss'; import { StyleProp } from './StyleProvider'; import React = require('react'); @@ -43,7 +43,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> { @computed get allMetadata() { const keys = new Map<string, FieldResult<Field>>(); DocListCast(this.props.rootDoc[this.sidebarKey]).forEach(doc => - SearchBox.documentKeys(doc) + SearchUtil.documentKeys(doc) .filter(key => key[0] && key[0] !== '_' && key[0] === key[0].toUpperCase()) .map(key => keys.set(key, doc[key])) ); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 24a269927..12935400b 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -4,6 +4,7 @@ import { Tooltip } from '@material-ui/core'; import { IconButton, Shadows, Size } from 'browndash-components'; import { action, runInAction } from 'mobx'; import { extname } from 'path'; +import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs'; import { Doc, Opt, StrListCast } from '../../fields/Doc'; import { BoolCast, Cast, DocCast, ImageCast, NumCast, StrCast } from '../../fields/Types'; import { DashColor, lightOrDark, Utils } from '../../Utils'; @@ -14,15 +15,13 @@ import { LinkManager } from '../util/LinkManager'; import { SelectionManager } from '../util/SelectionManager'; import { ColorScheme, SettingsManager } from '../util/SettingsManager'; import { undoBatch, UndoManager } from '../util/UndoManager'; -import { TreeSort } from './collections/TreeView'; +import { TreeSort } from './collections/TreeSort'; import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; -import { MainView } from './MainView'; -import { DocumentViewProps } from './nodes/DocumentView'; +import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; import { SliderBox } from './nodes/SliderBox'; -import { BsArrowDown, BsArrowUp, BsArrowDownUp } from 'react-icons/bs'; import './StyleProvider.scss'; import React = require('react'); @@ -159,7 +158,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps '' ); case StyleProp.Color: - if (MainView.Instance.LastButton === doc) return SettingsManager.Instance.userBackgroundColor; + if (DocumentView.LastPressedSidebarBtn === doc) return SettingsManager.userBackgroundColor; if (Doc.IsSystem(doc!)) return StrCast(Doc.UserDoc().userColor) if (doc?.type === DocumentType.FONTICON) return Doc.UserDoc().userColor; const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color)); @@ -194,7 +193,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps ? 15 : 0; case StyleProp.BackgroundColor: { - if (MainView.Instance.LastButton === doc) return StrCast(Doc.UserDoc().userColor); // hack to indicate active menu panel item + if (DocumentView.LastPressedSidebarBtn === doc) return StrCast(Doc.UserDoc().userColor); // hack to indicate active menu panel item let docColor: Opt<string> = StrCast(doc?.[fieldKey + '_backgroundColor'], StrCast(doc?._backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : '')); // prettier-ignore switch (doc?.type) { @@ -217,7 +216,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps case DocumentType.COL: if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break; docColor = docColor || (Doc.IsSystem(doc) - ? SettingsManager.Instance.userBackgroundColor + ? SettingsManager.userBackgroundColor : doc.annotationOn ? '#00000010' // faint interior for collections on PDFs, images, etc : doc?._isGroup @@ -264,7 +263,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name) && !props?.LayoutTemplateString; if (StrCast(doc?.pointerEvents) && !props?.LayoutTemplateString?.includes(KeyValueBox.name)) return StrCast(doc!.pointerEvents); // honor pointerEvents field (set by lock button usually) if it's not a keyValue view of the Doc if (docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.() !== undefined) return docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.(); - if (MainView.Instance._exploreMode || doc?.layout_unrendered) return isInk ? 'visiblePainted' : 'all'; + if (DocumentView.ExploreMode || doc?.layout_unrendered) return isInk ? 'visiblePainted' : 'all'; if (props?.contentPointerEvents) return StrCast(props.contentPointerEvents); if (props?.pointerEvents?.() === 'none') return 'none'; if (opacity() === 0) return 'none'; diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx index a551e5332..3fd64d1fd 100644 --- a/src/client/views/UndoStack.tsx +++ b/src/client/views/UndoStack.tsx @@ -19,7 +19,7 @@ export class UndoStack extends React.Component<UndoStackProps> { @observable static HideInline: boolean; @observable static Expand: boolean; render() { - const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.Instance.userBackgroundColor; + const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userBackgroundColor; return this.props.inline && UndoStack.HideInline ? null : ( <div className="undoStack-outerContainer"> <Popup diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index e15d57306..519b7c905 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -3,6 +3,7 @@ import { observer } from 'mobx-react'; import * as ReactDOM from 'react-dom/client'; import * as GoldenLayout from '../../../client/goldenLayout'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; +import { AclAdmin, AclEdit } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; @@ -13,6 +14,7 @@ import { emptyFunction, incrementTitleCopy } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; import { InteractionUtils } from '../../util/InteractionUtils'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; @@ -28,8 +30,6 @@ import './CollectionDockingView.scss'; import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; import { TabDocView } from './TabDocView'; -import { DocumentManager } from '../../util/DocumentManager'; -import { AclAdmin, AclEdit } from '../../../fields/DocSymbols'; import React = require('react'); const _global = (window /* browser */ || global) /* node */ as any; diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index f65e8698f..5c9dd2058 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -181,7 +181,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> { <div className="collectionMenu-container" style={{ - background: SettingsManager.Instance.userBackgroundColor, + background: SettingsManager.userBackgroundColor, // borderColor: StrCast(Doc.UserDoc().userColor) }}> {this.contMenuButtons} diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index de58e1fe7..d2be70577 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -2,12 +2,12 @@ import React = require('react'); import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; -import { Doc, Opt, StrListCast } from '../../../fields/Doc'; +import { Doc, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; -import { Cast, NumCast, ScriptCast } from '../../../fields/Types'; +import { Cast, NumCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { emptyFunction, formatTime, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../Utils'; import { Docs } from '../../documents/Documents'; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index f379d09ff..f6acafa95 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -1,6 +1,6 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Tooltip } from '@material-ui/core'; +import { Popup, Type } from 'browndash-components'; import { clamp } from 'lodash'; import { action, computed, IReactionDisposer, observable, ObservableSet, reaction } from 'mobx'; import { observer } from 'mobx-react'; @@ -10,7 +10,7 @@ import { DocData, Height, Width } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { FieldId } from '../../../fields/RefField'; -import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; +import { Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; @@ -21,9 +21,8 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoable, UndoManager } from '../../util/UndoManager'; import { DashboardView } from '../DashboardView'; -import { Colors, Shadows } from '../global/globalEnums'; +import { Colors } from '../global/globalEnums'; import { LightboxView } from '../LightboxView'; -import { MainView } from '../MainView'; import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, OpenWhereMod } from '../nodes/DocumentView'; import { DashFieldView } from '../nodes/formattedText/DashFieldView'; import { KeyValueBox } from '../nodes/KeyValueBox'; @@ -34,7 +33,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV import { CollectionView } from './CollectionView'; import './TabDocView.scss'; import React = require('react'); -import { Popup, Toggle, Type } from 'browndash-components'; const _global = (window /* browser */ || global) /* node */ as any; interface TabDocViewProps { @@ -426,6 +424,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._type_collection !== CollectionViewType.Freeform; whenChildContentActiveChanges = (isActive: boolean) => (this._isAnyChildContentActive = isActive); isContentActive = () => this._isContentActive; + waitForDoubleClick = () => (DocumentView.ExploreMode ? 'never' : undefined); @computed get docView() { return !this._activated || !this._document ? null : ( <> @@ -441,8 +440,8 @@ export class TabDocView extends React.Component<TabDocViewProps> { hideTitle={this.props.keyValue} Document={this._document} DataDoc={!Doc.AreProtosEqual(this._document[DocData], this._document) ? this._document[DocData] : undefined} - onBrowseClick={MainView.Instance.exploreMode} - waitForDoubleClickToClick={MainView.Instance.waitForDoubleClick} + onBrowseClick={DocumentView.exploreMode} + waitForDoubleClickToClick={this.waitForDoubleClick} isContentActive={this.isContentActive} isDocumentActive={returnFalse} PanelWidth={this.PanelWidth} diff --git a/src/client/views/collections/TreeSort.ts b/src/client/views/collections/TreeSort.ts new file mode 100644 index 000000000..977acd030 --- /dev/null +++ b/src/client/views/collections/TreeSort.ts @@ -0,0 +1,6 @@ +export enum TreeSort { + AlphaUp = 'alphabetical from z', + AlphaDown = 'alphabetical from A', + Zindex = 'by Z index', + WhenAdded = 'when added', +} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 3402a8c8d..701150769 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -35,6 +35,7 @@ import { CollectionView } from './CollectionView'; import './TreeView.scss'; import React = require('react'); import { IconButton, Size } from 'browndash-components'; +import { TreeSort } from './TreeSort'; export interface TreeViewProps { treeView: CollectionTreeView; @@ -77,12 +78,6 @@ const treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace('px', '')); }; -export enum TreeSort { - AlphaUp = 'alphabetical from z', - AlphaDown = 'alphabetical from A', - Zindex = 'by Z index', - WhenAdded = 'when added', -} /** * Renders a treeView of a collection of documents * @@ -578,7 +573,7 @@ export class TreeView extends React.Component<TreeViewProps> { return ( <div> {!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? null : ( - <div className='treeView-sorting'> + <div className="treeView-sorting"> <IconButton color={sortings[sorting]?.color} size={Size.XSMALL} @@ -602,7 +597,7 @@ export class TreeView extends React.Component<TreeViewProps> { style={{ cursor: 'inherit' }} key={expandKey + 'more'} title={`Sorted by : ${this.doc.treeView_SortCriterion}. click to cycle`} - className='' //this.doc.treeView_HideTitle ? 'no-indent' : ''} + className="" //this.doc.treeView_HideTitle ? 'no-indent' : ''} onPointerDown={e => { downX = e.clientX; downY = e.clientY; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index f5cc1eb53..16d6f1270 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -371,7 +371,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection const nd = [Doc.NativeWidth(layoutDoc), Doc.NativeHeight(layoutDoc)]; layoutDoc._width = NumCast(layoutDoc._width, 300); layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? (nd[1] / nd[0]) * NumCast(layoutDoc._width) : 300); - (d._raiseWhenDragged === undefined ? DragManager.GetRaiseWhenDragged() : d._raiseWhenDragged) && (d.zIndex = zsorted.length + 1 + i); // bringToFront + !d._keepZWhenDragged && (d.zIndex = zsorted.length + 1 + i); // bringToFront } if (this.layoutDoc._autoArrange || de.metaKey) { @@ -1267,7 +1267,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection }; @computed get _pointerEvents() { const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine); - const pointerEvents = DocumentDecorations.Instance.Interacting + const pointerEvents = DocumentView.Interacting ? 'none' : this.props.childPointerEvents ?? (this.props.viewDefDivClick || (engine === computePassLayout.name && !this.props.isSelected(true)) || this.isContentActive() === false ? 'none' : this.props.pointerEvents?.()); return pointerEvents; diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx index 6895c0746..9a9a89732 100644 --- a/src/client/views/linking/LinkPopup.tsx +++ b/src/client/views/linking/LinkPopup.tsx @@ -3,15 +3,14 @@ import { observer } from 'mobx-react'; import { EditorView } from 'prosemirror-view'; import { Doc } from '../../../fields/Doc'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils'; -import { DocUtils } from '../../documents/Documents'; import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; +import { OpenWhere } from '../nodes/DocumentView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { SearchBox } from '../search/SearchBox'; import { DefaultStyleProvider } from '../StyleProvider'; import './LinkPopup.scss'; import React = require('react'); -import { OpenWhere } from '../nodes/DocumentView'; interface LinkPopupProps { linkFrom?: () => Doc | undefined; diff --git a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx index ff17e5c12..3a95e5f74 100644 --- a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx +++ b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx @@ -1,14 +1,13 @@ -import './ButtonMenu.scss'; +import { action } from 'mobx'; import * as React from 'react'; -import { IButtonMenu } from './utils'; -import { NewLightboxView } from '../NewLightboxView'; -import { SelectionManager } from '../../../util/SelectionManager'; -import { CollectionDockingView } from '../../collections/CollectionDockingView'; -import { OpenWhereMod } from '../../nodes/DocumentView'; import { Doc } from '../../../../fields/Doc'; import { InkTool } from '../../../../fields/InkField'; -import { MainView } from '../../MainView'; -import { action } from 'mobx'; +import { SelectionManager } from '../../../util/SelectionManager'; +import { CollectionDockingView } from '../../collections/CollectionDockingView'; +import { DocumentView, OpenWhereMod } from '../../nodes/DocumentView'; +import { NewLightboxView } from '../NewLightboxView'; +import './ButtonMenu.scss'; +import { IButtonMenu } from './utils'; export const ButtonMenu = (props: IButtonMenu) => { return ( @@ -40,10 +39,10 @@ export const ButtonMenu = (props: IButtonMenu) => { <div className="newLightboxView-exploreBtn" title="toggle explore mode to navigate among documents only" - style={{ background: MainView.Instance._exploreMode ? 'white' : undefined }} + style={{ background: DocumentView.ExploreMode ? 'white' : undefined }} onClick={action(e => { e.stopPropagation(); - MainView.Instance._exploreMode = !MainView.Instance._exploreMode; + DocumentView.ExploreMode = !DocumentView.ExploreMode; })}></div> </div> ); diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx index 3acbd1a32..ca90f6a0f 100644 --- a/src/client/views/newlightbox/NewLightboxView.tsx +++ b/src/client/views/newlightbox/NewLightboxView.tsx @@ -2,35 +2,32 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../Utils'; -import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc'; +import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { LinkManager } from '../../util/LinkManager'; import { SelectionManager } from '../../util/SelectionManager'; import { Transform } from '../../util/Transform'; -import { GestureOverlay } from '../GestureOverlay'; -import { MainView } from '../MainView'; -import { DefaultStyleProvider } from '../StyleProvider'; import { CollectionStackedTimeline } from '../collections/CollectionStackedTimeline'; import { TabDocView } from '../collections/TabDocView'; +import { GestureOverlay } from '../GestureOverlay'; +import { LightboxView } from '../LightboxView'; import { DocumentView, OpenWhere } from '../nodes/DocumentView'; +import { DefaultStyleProvider } from '../StyleProvider'; +import { IRecommendation } from './components'; import { ExploreView } from './ExploreView'; -import { IBounds, emptyBounds } from './ExploreView/utils'; +import { emptyBounds, IBounds } from './ExploreView/utils'; import { NewLightboxHeader } from './Header'; import './NewLightboxView.scss'; import { RecommendationList } from './RecommendationList'; -import { IRecommendation } from './components'; -import { fetchKeywords, fetchRecommendations } from './utils'; -import { List } from '../../../fields/List'; -import { LightboxView } from '../LightboxView'; enum LightboxStatus { - RECOMMENDATIONS = "recommendations", - ANNOTATIONS = "annotations", - NONE = "none" + RECOMMENDATIONS = 'recommendations', + ANNOTATIONS = 'annotations', + NONE = 'none', } interface LightboxViewProps { @@ -63,30 +60,30 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { @observable private static _docView: Opt<DocumentView>; // keywords - @observable private static _keywords: string[] = [] + @observable private static _keywords: string[] = []; @action public static SetKeywords(kw: string[]) { - this._keywords = kw + this._keywords = kw; } @computed public static get Keywords() { - return this._keywords + return this._keywords; } // query - @observable private static _query: string = '' + @observable private static _query: string = ''; @action public static SetQuery(query: string) { - this._query = query + this._query = query; } @computed public static get Query() { - return this._query + return this._query; } // keywords - @observable private static _recs: IRecommendation[] = [] + @observable private static _recs: IRecommendation[] = []; @action public static SetRecs(recs: IRecommendation[]) { - this._recs = recs + this._recs = recs; } @computed public static get Recs() { - return this._recs + return this._recs; } // bounds @@ -108,7 +105,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { } // newLightbox sidebar status - @observable private static _sidebarStatus: Opt<string> = ""; + @observable private static _sidebarStatus: Opt<string> = ''; @action public static SetSidebarStatus(sidebarStatus: Opt<string>) { this._sidebarStatus = sidebarStatus; } @@ -129,7 +126,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { this._docFilters && (this._docFilters.length = 0); this._future = this._history = []; Doc.ActiveTool = InkTool.None; - MainView.Instance._exploreMode = false; + DocumentView.ExploreMode = false; } else { const l = DocUtils.MakeLinkToActiveAudio(() => doc).lastElement(); l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen'); @@ -289,35 +286,38 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { @computed get documentView() { - if (!LightboxView.LightboxDoc) return null - else return (<GestureOverlay isActive={true}> - <DocumentView - ref={action((r: DocumentView | null) => (NewLightboxView._docView = r !== null ? r : undefined))} - Document={LightboxView.LightboxDoc} - DataDoc={undefined} - PanelWidth={this.newLightboxWidth} - PanelHeight={this.newLightboxHeight} - LayoutTemplate={NewLightboxView.LightboxDocTemplate} - isDocumentActive={returnTrue} // without this being true, sidebar annotations need to be activated before text can be selected. - isContentActive={returnTrue} - styleProvider={DefaultStyleProvider} - ScreenToLocalTransform={this.newLightboxScreenToLocal} - renderDepth={0} - rootSelected={returnTrue} - docViewPath={returnEmptyDoclist} - childFilters={this.docFilters} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - addDocument={undefined} - removeDocument={undefined} - whenChildContentsActiveChanged={emptyFunction} - addDocTab={this.addDocTab} - pinToPres={TabDocView.PinDoc} - bringToFront={emptyFunction} - onBrowseClick={MainView.Instance.exploreMode} - focus={emptyFunction} - /> - </GestureOverlay>) + if (!LightboxView.LightboxDoc) return null; + else + return ( + <GestureOverlay isActive={true}> + <DocumentView + ref={action((r: DocumentView | null) => (NewLightboxView._docView = r !== null ? r : undefined))} + Document={LightboxView.LightboxDoc} + DataDoc={undefined} + PanelWidth={this.newLightboxWidth} + PanelHeight={this.newLightboxHeight} + LayoutTemplate={NewLightboxView.LightboxDocTemplate} + isDocumentActive={returnTrue} // without this being true, sidebar annotations need to be activated before text can be selected. + isContentActive={returnTrue} + styleProvider={DefaultStyleProvider} + ScreenToLocalTransform={this.newLightboxScreenToLocal} + renderDepth={0} + rootSelected={returnTrue} + docViewPath={returnEmptyDoclist} + childFilters={this.docFilters} + childFiltersByRanges={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + addDocument={undefined} + removeDocument={undefined} + whenChildContentsActiveChanged={emptyFunction} + addDocTab={this.addDocTab} + pinToPres={TabDocView.PinDoc} + bringToFront={emptyFunction} + onBrowseClick={DocumentView.exploreMode} + focus={emptyFunction} + /> + </GestureOverlay> + ); } future = () => NewLightboxView._future; @@ -337,29 +337,28 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { NewLightboxView.SetNewLightboxDoc(undefined); } }}> - <div className={`app-document`} style={{gridTemplateColumns: `calc(100% - 400px) 400px`}}> - <div - className="newLightboxView-contents" - style={{ - top: 20, - left: 20, - width: this.newLightboxWidth(), - height: this.newLightboxHeight() - 40, - }}> + <div className={`app-document`} style={{ gridTemplateColumns: `calc(100% - 400px) 400px` }}> + <div + className="newLightboxView-contents" + style={{ + top: 20, + left: 20, + width: this.newLightboxWidth(), + height: this.newLightboxHeight() - 40, + }}> <NewLightboxHeader height={newLightboxHeaderHeight} width={this.newLightboxWidth()} /> - {!NewLightboxView._explore ? - <div className="newLightboxView-doc" style={{height: this.newLightboxHeight()}}> + {!NewLightboxView._explore ? ( + <div className="newLightboxView-doc" style={{ height: this.newLightboxHeight() }}> {this.documentView} </div> - : + ) : ( <div className={`explore`}> - <ExploreView recs={NewLightboxView.Recs} bounds={NewLightboxView.Bounds}/> + <ExploreView recs={NewLightboxView.Recs} bounds={NewLightboxView.Bounds} /> </div> - } - </div> - <RecommendationList keywords={NewLightboxView.Keywords}/> + )} + </div> + <RecommendationList keywords={NewLightboxView.Keywords} /> </div> - </div> ); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index be1eb3901..74eee49e0 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -28,6 +28,7 @@ import { FollowLinkScript } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; +import { SettingsManager } from '../../util/SettingsManager'; import { SharingManager } from '../../util/SharingManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; @@ -51,7 +52,6 @@ import { LinkAnchorBox } from './LinkAnchorBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; import React = require('react'); -import { SettingsManager } from '../../util/SettingsManager'; const { Howl } = require('howler'); interface Window { @@ -428,7 +428,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps if (!this.Document.ignoreClick && this.pointerEvents !== 'none' && this.props.renderDepth >= 0 && Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) { let stopPropagate = true; let preventDefault = true; - (this.rootDoc._raiseWhenDragged === undefined ? DragManager.GetRaiseWhenDragged() : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc); + !this.rootDoc._keepZWhenDragged && this.props.bringToFront(this.rootDoc); if (this._doubleTap) { const defaultDblclick = this.props.defaultDoubleClick?.() || this.Document.defaultDoubleClick; if (this.onDoubleClickHandler?.script) { @@ -744,8 +744,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: 'arrow-up' }); zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: 'arrow-down' }); zorderItems.push({ - description: this.rootDoc._raiseWhenDragged !== false ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged', - event: undoBatch(action(() => (this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined))), + description: !this.rootDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged', + event: undoBatch(action(() => (this.rootDoc._keepZWhenDragged = !this.rootDoc._keepZWhenDragged))), icon: 'hand-point-up', }); !zorders && cm.addItem({ description: 'Z Order...', addDivider: true, noexpand: true, subitems: zorderItems, icon: 'layer-group' }); @@ -1114,7 +1114,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps </div> ); const targetDoc = showTitle?.startsWith('_') ? this.layoutDoc : this.rootDoc; - const background = StrCast(SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor, StrCast(Doc.SharingDoc().headingColor, SettingsManager.Instance.userVariantColor)); + const background = StrCast(SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor, StrCast(Doc.SharingDoc().headingColor, SettingsManager.userVariantColor)); const sidebarWidthPercent = +StrCast(this.layoutDoc.layout_sidebarWidthPercent).replace('%', ''); const titleView = !showTitle ? null : ( <div @@ -1276,7 +1276,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps @observer export class DocumentView extends React.Component<DocumentViewProps> { public static ROOT_DIV = 'documentView-effectsWrapper'; + @observable public static Interacting = false; @observable public static LongPress = false; + @observable public static ExploreMode = false; + @observable public static LastPressedSidebarBtn: Opt<Doc>; // bcz: this is a hack to handle highlighting buttons in the leftpanel menu .. need to find a cleaner approach + @computed public static get exploreMode() { + return () => (DocumentView.ExploreMode ? ScriptField.MakeScript('CollectionBrowseClick(documentView, clientX, clientY)', { documentView: 'any', clientX: 'number', clientY: 'number' })! : undefined); + } @observable public docView: DocumentViewInternal | undefined | null; @observable public textHtmlOverlay: Opt<string>; @observable private _isHovering = false; diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 94650cc88..fc66d40db 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -67,19 +67,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() { } }; - static GetShowLabels() { - return BoolCast(Doc.UserDoc()._showLabel); - } - static SetShowLabels(show: boolean) { - Doc.UserDoc()._showLabel = show; - } - static GetRecognizeGestures() { - return BoolCast(Doc.UserDoc()._recognizeGestures); - } - static SetRecognizeGestures(show: boolean) { - Doc.UserDoc()._recognizeGestures = show; - } - // Determining UI Specs @computed get label() { return StrCast(this.rootDoc.icon_label, StrCast(this.rootDoc.title)); @@ -139,7 +126,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() { const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); // Script for checking the outcome of the toggle const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3))); - const label = !FontIconBox.GetShowLabels() ? null : <div className="fontIconBox-label">{this.label}</div>; + const label = !Doc.GetShowIconLabels() ? null : <div className="fontIconBox-label">{this.label}</div>; return ( <NumberDropdown @@ -174,7 +161,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() { Doc.UnBrushAllDocs(); })}> {this.Icon(color)} - {!this.label || !FontIconBox.GetShowLabels() ? null : ( + {!this.label || !Doc.GetShowIconLabels() ? null : ( <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {' '} {this.label}{' '} diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index d69009415..42c8ea6a4 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -4,7 +4,7 @@ import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import wiki from 'wikijs'; import { Doc, DocCastAsync, Opt } from '../../../fields/Doc'; -import { DirectLinks, Height, Width } from '../../../fields/DocSymbols'; +import { Height, Width } from '../../../fields/DocSymbols'; import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils'; import { DocServer } from '../../DocServer'; @@ -13,9 +13,9 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; +import { SearchUtil } from '../../util/SearchUtil'; import { SettingsManager } from '../../util/SettingsManager'; import { Transform } from '../../util/Transform'; -import { SearchBox } from '../search/SearchBox'; import { DocumentView, DocumentViewSharedProps, OpenWhere } from './DocumentView'; import './LinkDocPreview.scss'; import React = require('react'); @@ -174,7 +174,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { LinkFollower.FollowLink(this._linkDoc, this._linkSrc, false); } else if (this.props.hrefs?.length) { const webDoc = - Array.from(SearchBox.staticSearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ?? + Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ?? Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true }); this.props.docProps?.addDocTab(webDoc, OpenWhere.lightbox); } diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index fcbd0128d..0b02626e9 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -1,14 +1,14 @@ -import { action, observable, runInAction } from 'mobx'; +import { observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import ReactLoading from 'react-loading'; import { Doc } from '../../../fields/Doc'; +import { Id } from '../../../fields/FieldSymbols'; import { StrCast } from '../../../fields/Types'; import { Networking } from '../../Network'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { FieldView, FieldViewProps } from './FieldView'; import './LoadingBox.scss'; -import { Id } from '../../../fields/FieldSymbols'; /** * LoadingBox Class represents a placeholder doc for documents that are currently @@ -44,7 +44,7 @@ export class LoadingBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this.rootDoc.loadingError = 'Upload interrupted, please try again'; } else { const updateFunc = async () => { - const result = await Networking.QueryYoutubeProgress(StrCast(this.rootDoc[Id])); // We use the guid of the overwriteDoc to track file uploads. + const result = await Networking.QueryYoutubeProgress(StrCast(this.rootDoc[Id])); // We use the guid of the overwriteDoc to track file uploads. runInAction(() => (this.progress = result.progress)); this._timer = setTimeout(updateFunc, 1000); }; diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 83a29f071..fa19caae1 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -314,7 +314,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl </> </CollectionFreeFormView> </div> - <div style={{ background: SettingsManager.Instance.userColor, position: 'relative', height: this.formattedPanelHeight() }}> + <div style={{ background: SettingsManager.userColor, position: 'relative', height: this.formattedPanelHeight() }}> {!(this.dataDoc[this.fieldKey + '_dictation'] instanceof Doc) ? null : ( <FormattedTextBox {...this.props} @@ -336,8 +336,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl </div> </div> {!this.props.isSelected() ? null : ( - <div className="screenshotBox-uiButtons" style={{ background: SettingsManager.Instance.userColor }}> - <div className="screenshotBox-recorder" style={{ color: SettingsManager.Instance.userBackgroundColor, background: SettingsManager.Instance.userVariantColor }} key="snap" onPointerDown={this.toggleRecording}> + <div className="screenshotBox-uiButtons" style={{ background: SettingsManager.userColor }}> + <div className="screenshotBox-recorder" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userVariantColor }} key="snap" onPointerDown={this.toggleRecording}> <FontAwesomeIcon icon="file" size="lg" /> </div> </div> diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 2177adeff..48716b867 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -26,11 +26,10 @@ import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionS import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; -import { DocumentDecorations } from '../DocumentDecorations'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { StyleProp } from '../StyleProvider'; -import { OpenWhere } from './DocumentView'; +import { DocumentView, OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { RecordingBox } from './RecordingBox'; import { PinProps, PresBox } from './trails'; @@ -624,7 +623,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp () => !this._playing && this.Seek(NumCast(this.layoutDoc._layout_currentTimecode)) ); this._disposers.youtubeReactionDisposer = reaction( - () => Doc.ActiveTool === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting, + () => Doc.ActiveTool === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentView.Interacting, interactive => (iframe.style.pointerEvents = interactive ? 'all' : 'none'), { fireImmediately: true } ); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 200d06a0b..bd969b527 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -11,9 +11,10 @@ import { keymap } from 'prosemirror-keymap'; import { Fragment, Mark, Node, Slice } from 'prosemirror-model'; import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from 'prosemirror-state'; import { EditorView } from 'prosemirror-view'; +import { BsMarkdownFill } from 'react-icons/bs'; import { DateField } from '../../../../fields/DateField'; -import { Doc, DocListCast, StrListCast, Field, Opt } from '../../../../fields/Doc'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, Height, Width, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; +import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, ForceServerWrite, Height, UpdatingFromServer, Width } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; @@ -25,11 +26,10 @@ import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } fro import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils'; -import { gptAPICall, GPTCallType, gptImageCall } from '../../../apis/gpt/GPT'; +import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { DocServer } from '../../../DocServer'; import { Docs, DocUtils } from '../../../documents/Documents'; -import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; -import { Networking } from '../../../Network'; +import { CollectionViewType } from '../../../documents/DocumentTypes'; import { DictationManager } from '../../../util/DictationManager'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; @@ -49,6 +49,7 @@ import { DocumentButtonBar } from '../../DocumentButtonBar'; import { Colors } from '../../global/globalEnums'; import { LightboxView } from '../../LightboxView'; import { AnchorMenu } from '../../pdf/AnchorMenu'; +import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup'; import { SidebarAnnos } from '../../SidebarAnnos'; import { StyleProp } from '../../StyleProvider'; import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; @@ -70,8 +71,6 @@ import { schema } from './schema_rts'; import { SummaryView } from './SummaryView'; import applyDevTools = require('prosemirror-dev-tools'); import React = require('react'); -import { GPTPopup, GPTPopupMode } from '../../pdf/GPTPopup/GPTPopup'; -import { BsMarkdownFill } from 'react-icons/bs'; const translateGoogleApi = require('translate-google-api'); export const GoogleRef = 'googleDocId'; type PullHandler = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => void; @@ -575,7 +574,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps draggedDoc._freeform_fitContentsToBox = true; Doc.SetContainer(draggedDoc, this.rootDoc); const view = this._editorView!; - view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node)); + try { + const pos = view.posAtCoords({ left: de.x, top: de.y })?.pos; + pos && view.dispatch(view.state.tr.insert(pos, node)); + added = pos ? true : false; // pos will be null if you don't drop onto an actual text location + } catch (e) { + console.log('Drop failed', e); + added = false; + } } } } // otherwise, fall through to outer collection to handle drop @@ -1119,7 +1125,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps componentDidMount() { !this.props.dontSelectOnLoad && this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. this._cachedLinks = LinkManager.Links(this.Document); - this._disposers.breakupDictation = reaction(() => DocumentManager.Instance.RecordingEvent, this.breakupDictation); + this._disposers.breakupDictation = reaction(() => Doc.RecordingEvent, this.breakupDictation); this._disposers.layout_autoHeight = reaction( () => this.layout_autoHeight, layout_autoHeight => layout_autoHeight && this.tryUpdateScrollHeight() diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx index 1400d0f6d..1ec6d6e3f 100644 --- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx +++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx @@ -1,26 +1,25 @@ -import './GenerativeFill.scss'; -import React = require('react'); -import { useEffect, useRef, useState } from 'react'; -import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler'; -import { BrushHandler } from './generativeFillUtils/BrushHandler'; -import { IconButton } from 'browndash-components'; import { Checkbox, FormControlLabel, Slider, TextField } from '@mui/material'; -import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces'; -import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants'; -import { PointerHandler } from './generativeFillUtils/PointerHandler'; -import { IoMdUndo, IoMdRedo } from 'react-icons/io'; -import { MainView } from '../../MainView'; +import { IconButton } from 'browndash-components'; +import { useEffect, useRef, useState } from 'react'; +import { CgClose } from 'react-icons/cg'; +import { IoMdRedo, IoMdUndo } from 'react-icons/io'; import { Doc, DocListCast } from '../../../../fields/Doc'; -import { Networking } from '../../../Network'; -import { Utils } from '../../../../Utils'; -import { DocUtils, Docs } from '../../../documents/Documents'; +import { List } from '../../../../fields/List'; import { NumCast } from '../../../../fields/Types'; +import { Utils } from '../../../../Utils'; +import { Docs, DocUtils } from '../../../documents/Documents'; +import { Networking } from '../../../Network'; import { CollectionDockingView } from '../../collections/CollectionDockingView'; import { OpenWhereMod } from '../DocumentView'; -import Buttons from './GenerativeFillButtons'; -import { List } from '../../../../fields/List'; -import { CgClose } from 'react-icons/cg'; import { ImageBox } from '../ImageBox'; +import './GenerativeFill.scss'; +import Buttons from './GenerativeFillButtons'; +import { BrushHandler } from './generativeFillUtils/BrushHandler'; +import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants'; +import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces'; +import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler'; +import { PointerHandler } from './generativeFillUtils/PointerHandler'; +import React = require('react'); enum BrushStyle { ADD, diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 6ff22e929..f750392f5 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { action, computed, IReactionDisposer, observable, ObservableSet, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../../fields/Doc'; +import { Doc, DocListCast, FieldResult, Opt, StrListCast } from '../../../../fields/Doc'; import { Animation } from '../../../../fields/DocSymbols'; import { Copy, Id } from '../../../../fields/FieldSymbols'; import { InkField } from '../../../../fields/InkField'; @@ -15,7 +15,7 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Ty import { AudioField } from '../../../../fields/URLField'; import { emptyFunction, emptyPath, returnFalse, returnOne, setupMoveUpEvents, StopEvent } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; -import { Docs, DocUtils } from '../../../documents/Documents'; +import { Docs } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { DocumentManager } from '../../../util/DocumentManager'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index b0924888a..6a8b06377 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -1,23 +1,20 @@ import React = require('react'); import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Tooltip } from '@material-ui/core'; +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'; import { returnFalse, setupMoveUpEvents, unimplementedFunction, Utils } from '../../../Utils'; +import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT'; +import { DocumentType } from '../../documents/DocumentTypes'; import { SelectionManager } from '../../util/SelectionManager'; import { AntimodeMenu, AntimodeMenuProps } from '../AntimodeMenu'; import { LinkPopup } from '../linking/LinkPopup'; -import { ButtonDropdown } from '../nodes/formattedText/RichTextMenu'; -import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT'; -import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup'; -import { LightboxView } from '../LightboxView'; -import { EditorView } from 'prosemirror-view'; import './AnchorMenu.scss'; -import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; -import { StrCast } from '../../../fields/Types'; -import { DocumentType } from '../../documents/DocumentTypes'; +import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup'; @observer export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx index 6103b245c..540c1b5e1 100644 --- a/src/client/views/search/IconBar.tsx +++ b/src/client/views/search/IconBar.tsx @@ -1,17 +1,15 @@ import { action, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { DocumentType } from "../../documents/DocumentTypes"; -// import "./SearchBox.scss"; -import "./IconBar.scss"; +import { DocumentType } from '../../documents/DocumentTypes'; +import './IconBar.scss'; import { IconButton } from './IconButton'; -import "./IconButton.scss"; +import './IconButton.scss'; export interface IconBarProps { setIcons: (icons: string[]) => void; } - @observer export class IconBar extends React.Component<IconBarProps> { public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.RTF, DocumentType.VID, DocumentType.WEB, DocumentType.MAP]; @@ -32,7 +30,9 @@ export class IconBar extends React.Component<IconBarProps> { } @action.bound - getIcons(): string[] { return this._icons; } + getIcons(): string[] { + return this._icons; + } constructor(props: any) { super(props); @@ -40,29 +40,33 @@ export class IconBar extends React.Component<IconBarProps> { } @action.bound - getList(): string[] { return this.getIcons(); } + getList(): string[] { + return this.getIcons(); + } @action.bound - updateList(newList: string[]) { this.updateIcon(newList); } + updateList(newList: string[]) { + this.updateIcon(newList); + } @action.bound resetSelf = () => { this._resetClicked = true; this.updateList([]); - } + }; @action.bound selectAll = () => { this._selectAllClicked = true; this.updateList(this._allIcons); - } + }; render() { return ( <div className="icon-bar"> - {this._allIcons.map((type: string) => + {this._allIcons.map((type: string) => ( <IconButton key={type.toString()} type={type} /> - )} + ))} </div> ); } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 1ceea697a..6b6b0f2ff 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -19,6 +19,7 @@ import { fetchRecommendations } from '../newlightbox/utils'; import { IRecommendation, Recommendation } from '../newlightbox/components'; import { Colors } from '../global/globalEnums'; import { SettingsManager } from '../../util/SettingsManager'; +import { SearchUtil } from '../../util/SearchUtil'; const DAMPENING_FACTOR = 0.9; const MAX_ITERATIONS = 25; @@ -132,34 +133,6 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { * @param {Doc[]} docs - docs to be searched through recursively * @param {number, Doc => void} func - function to be called on each doc * - * This method iterates through an array of docs and all docs within those docs, calling - * the function func on each doc. - */ - static foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) { - let newarray: Doc[] = []; - var depth = 0; - const visited: Doc[] = []; - while (docs.length > 0) { - newarray = []; - docs.filter(d => d && !visited.includes(d)).forEach(d => { - visited.push(d); - const fieldKey = Doc.LayoutFieldKey(d); - const annos = !Field.toString(Doc.LayoutField(d) as Field).includes('CollectionView'); - const data = d[annos ? fieldKey + '_annotations' : fieldKey]; - data && newarray.push(...DocListCast(data)); - const sidebar = d[fieldKey + '_sidebar']; - sidebar && newarray.push(...DocListCast(sidebar)); - func(depth, d); - }); - docs = newarray; - depth++; - } - } - - /** - * @param {Doc[]} docs - docs to be searched through recursively - * @param {number, Doc => void} func - function to be called on each doc - * * This method iterates asynchronously through an array of docs and all docs within those * docs, calling the function func on each doc. */ @@ -213,74 +186,10 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { @action searchCollection(query: string) { this._selectedResult = undefined; - this._results = SearchBox.staticSearchCollection(CollectionDockingView.Instance?.rootDoc, query); + this._results = SearchUtil.SearchCollection(CollectionDockingView.Instance?.rootDoc, query); this.computePageRanks(); } - @action - static staticSearchCollection(rootDoc: Opt<Doc>, query: string) { - const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.SEARCH, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; - const blockedKeys = [ - 'x', - 'y', - 'proto', - 'width', - 'layout_autoHeight', - 'acl-Override', - 'acl-Guest', - 'embedContainer', - 'zIndex', - 'height', - 'text_scrollHeight', - 'text_height', - 'cloneFieldFilter', - 'isDataDoc', - 'text_annotations', - 'dragFactory_count', - 'text_noTemplate', - 'proto_embeddings', - 'isSystem', - 'layout_fieldKey', - 'isBaseProto', - 'xMargin', - 'yMargin', - 'links', - 'layout', - 'layout_keyValue', - 'layout_fitWidth', - 'type_collection', - 'title_custom', - 'freeform_panX', - 'freeform_panY', - 'freeform_scale', - ]; - query = query.toLowerCase(); - - const results = new Map<Doc, string[]>(); - if (rootDoc) { - const docs = DocListCast(rootDoc[Doc.LayoutFieldKey(rootDoc)]); - const docIDs: String[] = []; - SearchBox.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => { - const dtype = StrCast(doc.type) as DocumentType; - if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth >= 0) { - const hlights = new Set<string>(); - SearchBox.documentKeys(doc).forEach( - key => - Field.toString(doc[key] as Field) - .toLowerCase() - .includes(query) && hlights.add(key) - ); - blockedKeys.forEach(key => hlights.delete(key)); - - if (Array.from(hlights.keys()).length > 0) { - results.set(doc, Array.from(hlights.keys())); - } - } - docIDs.push(doc[Id]); - }); - } - return results; - } /** * This method initializes the page rank of every document to the reciprocal @@ -374,17 +283,6 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { } /** - * @param {Doc} doc - doc for which keys are returned - * - * This method returns a list of a document doc's keys. - */ - static documentKeys(doc: Doc) { - const keys: { [key: string]: boolean } = {}; - Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false))); - return Array.from(Object.keys(keys)); - } - - /** * This method submits a search with the _searchString as its query and updates * the results array accordingly. */ @@ -518,7 +416,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { className={className}> <div className="searchBox-result-title">{title as string}</div> <div className="searchBox-result-type">{formattedType}</div> - <div className="searchBox-result-keys" style={{ color: SettingsManager.Instance.userVariantColor }}> + <div className="searchBox-result-keys" style={{ color: SettingsManager.userVariantColor }}> {result[1].join(', ')} </div> </div> @@ -530,7 +428,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { const recommendationsJSX: JSX.Element[] = this._recommendations.map(props => <Recommendation {...props} />); return ( - <div className="searchBox-container" style={{ pointerEvents: 'all', color: SettingsManager.Instance.userColor, background: SettingsManager.Instance.userBackgroundColor }}> + <div className="searchBox-container" style={{ pointerEvents: 'all', color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}> <div className="searchBox-bar"> {isLinkSearch ? null : ( <select name="type" id="searchBox-type" className="searchBox-type" onChange={this.onSelectChange}> diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index c194ede32..a2f9de9ab 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -1,13 +1,14 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Button, IconButton, Size, Type, isDark } from 'browndash-components'; +import { Button, IconButton, isDark, Size, Type } from 'browndash-components'; import { action, computed, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { FaBug, FaCamera, FaStamp } from 'react-icons/fa'; +import { FaBug, FaCamera } from 'react-icons/fa'; import { Doc, DocListCast } from '../../../fields/Doc'; import { AclAdmin, DashVersion } from '../../../fields/DocSymbols'; import { StrCast } from '../../../fields/Types'; import { GetEffectiveAcl } from '../../../fields/util'; +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; import { DocumentManager } from '../../util/DocumentManager'; import { PingManager } from '../../util/PingManager'; import { ReportManager } from '../../util/reportManager/ReportManager'; @@ -15,13 +16,12 @@ import { ServerStats } from '../../util/ServerStats'; import { SettingsManager } from '../../util/SettingsManager'; import { SharingManager } from '../../util/SharingManager'; import { UndoManager } from '../../util/UndoManager'; +import { CollectionDockingView } from '../collections/CollectionDockingView'; import { ContextMenu } from '../ContextMenu'; import { DashboardView } from '../DashboardView'; -import { MainView } from '../MainView'; -import { CollectionDockingView } from '../collections/CollectionDockingView'; import { Colors } from '../global/globalEnums'; +import { DocumentView } from '../nodes/DocumentView'; import './TopBar.scss'; -import { CurrentUserUtils } from '../../util/CurrentUserUtils'; /** * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user @@ -43,7 +43,7 @@ export class TopBar extends React.Component { return StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE); } @computed get backgroundColor() { - return PingManager.Instance.IsBeating ? SettingsManager.Instance.userBackgroundColor : Colors.MEDIUM_GRAY; + return PingManager.Instance.IsBeating ? SettingsManager.userBackgroundColor : Colors.MEDIUM_GRAY; } @observable happyHeart: boolean = PingManager.Instance.IsBeating; @@ -76,9 +76,7 @@ export class TopBar extends React.Component { <span style={{ color: isDark(this.backgroundColor) ? Colors.LIGHT_BLUE : Colors.MEDIUM_BLUE, fontWeight: 500 }}>dash</span> </div> )} - {Doc.ActiveDashboard && ( - <Button text="Explore" tooltip="Browsing mode for directly navigating to documents" size={Size.SMALL} color={this.color} onClick={action(() => (MainView.Instance._exploreMode = !MainView.Instance._exploreMode))} /> - )} + {Doc.ActiveDashboard && <Button text="Explore" tooltip="Browsing mode for directly navigating to documents" size={Size.SMALL} color={this.color} onClick={action(() => (DocumentView.ExploreMode = !DocumentView.ExploreMode))} />} </div> ); } diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx index 02e44a793..524492226 100644 --- a/src/client/views/webcam/DashWebRTCVideo.tsx +++ b/src/client/views/webcam/DashWebRTCVideo.tsx @@ -6,8 +6,8 @@ import { observer } from 'mobx-react'; import { Doc } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import '../../views/nodes/WebBox.scss'; -import { DocumentDecorations } from '../DocumentDecorations'; import { CollectionFreeFormDocumentViewProps } from '../nodes/CollectionFreeFormDocumentView'; +import { DocumentView } from '../nodes/DocumentView'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import './DashWebRTCVideo.scss'; import { hangup, initialize, refreshVideos } from './WebCamLogic'; @@ -71,8 +71,8 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV </div> ); - const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting; - const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? '-interactive' : ''); + const frozen = !this.props.isSelected() || DocumentView.Interacting; + const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentView.Interacting ? '-interactive' : ''); return ( <> |
