aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/MainView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/MainView.tsx')
-rw-r--r--src/client/views/MainView.tsx135
1 files changed, 95 insertions, 40 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index cbaa763f5..707cf3a34 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -4,20 +4,20 @@ import * as far from '@fortawesome/free-regular-svg-icons';
import * as fa from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import 'browndash-components/dist/styles/global.min.css';
-import { action, computed, configure, observable, reaction, runInAction } from 'mobx';
+import { action, computed, configure, observable, runInAction } from 'mobx';
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 { emptyFunction, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils';
import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
import { DocServer } from '../DocServer';
import { Docs } from '../documents/Documents';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
import { CaptureManager } from '../util/CaptureManager';
import { DocumentManager } from '../util/DocumentManager';
+import { DragManager } from '../util/DragManager';
import { GroupManager } from '../util/GroupManager';
import { HistoryUtil } from '../util/History';
import { Hypothesis } from '../util/HypothesisUtils';
@@ -43,7 +43,6 @@ import { DictationOverlay } from './DictationOverlay';
import { DocumentDecorations } from './DocumentDecorations';
import { GestureOverlay } from './GestureOverlay';
import { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } from './global/globalCssVariables.scss';
-import { Colors } from './global/globalEnums';
import { KeyManager } from './GlobalKeyHandler';
import { InkTranscription } from './InkTranscription';
import { LightboxView } from './LightboxView';
@@ -55,12 +54,17 @@ import { DocumentView, DocumentViewInternal, OpenWhere, OpenWhereMod } from './n
import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
import { RichTextMenu } from './nodes/formattedText/RichTextMenu';
+import GenerativeFill from './nodes/generativeFill/GenerativeFill';
+import { ImageBox } from './nodes/ImageBox';
import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
import { LinkDocPreview } from './nodes/LinkDocPreview';
+import { MapAnchorMenu } from './nodes/MapBox/MapAnchorMenu';
+import { MapBox } from './nodes/MapBox/MapBox';
import { RadialMenu } from './nodes/RadialMenu';
import { TaskCompletionBox } from './nodes/TaskCompletedBox';
import { OverlayView } from './OverlayView';
import { AnchorMenu } from './pdf/AnchorMenu';
+import { GPTPopup } from './pdf/GPTPopup/GPTPopup';
import { PreviewCursor } from './PreviewCursor';
import { PropertiesView } from './PropertiesView';
import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider';
@@ -72,7 +76,7 @@ export class MainView extends React.Component {
public static Instance: MainView;
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)
@@ -140,6 +144,12 @@ export class MainView extends React.Component {
mainDocViewHeight = () => this._dashUIHeight - this.headerBarDocHeight();
componentDidMount() {
+ const scriptTag = document.createElement('script');
+ scriptTag.setAttribute('type', 'text/javascript');
+ scriptTag.setAttribute('src', 'https://www.bing.com/api/maps/mapcontrol?callback=makeMap');
+ scriptTag.async = true;
+ scriptTag.defer = true;
+ document.body.appendChild(scriptTag);
document.getElementById('root')?.addEventListener('scroll', e => (ele => (ele.scrollLeft = ele.scrollTop = 0))(document.getElementById('root')!));
const ele = document.getElementById('loader');
const prog = document.getElementById('dash-progress');
@@ -156,8 +166,8 @@ export class MainView extends React.Component {
DocServer.setLivePlaygroundFields([
'dataTransition',
'viewTransition',
- 'treeViewOpen',
- 'treeViewExpandedView',
+ 'treeView_Open',
+ 'treeView_ExpandedView',
'carousel_index',
'itemIndex', // for changing slides in presentations
'layout_sidebarWidthPercent',
@@ -182,14 +192,6 @@ export class MainView extends React.Component {
'currentFrame',
]); // can play with these fields on someone else's
}
- DocServer.GetRefField('rtfProto').then(
- proto =>
- proto instanceof Doc &&
- reaction(
- () => StrCast(proto.BROADCAST_MESSAGE),
- msg => msg && alert(msg)
- )
- );
const tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
@@ -347,6 +349,7 @@ export class MainView extends React.Component {
fa.faMousePointer,
fa.faMusic,
fa.faObjectGroup,
+ fa.faArrowsLeftRight,
fa.faPause,
fa.faPen,
fa.faPenNib,
@@ -450,6 +453,7 @@ export class MainView extends React.Component {
fa.faSortUp,
fa.faSortDown,
fa.faTable,
+ fa.faTableColumns,
fa.faTh,
fa.faThList,
fa.faProjectDiagram,
@@ -527,10 +531,9 @@ export class MainView extends React.Component {
});
initEventListeners = () => {
- window.addEventListener('beforeunload', () => DocServer.UPDATE_SERVER_CACHE());
+ 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);
@@ -573,11 +576,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);
@@ -704,7 +703,7 @@ export class MainView extends React.Component {
switch (whereFields[0]) {
case OpenWhere.lightbox: return LightboxView.AddDocTab(doc, location);
case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods);
- case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods);
+ case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods, undefined, "dontSelectOnActivate"); // bcz: hack! mark the toggle so that it won't be selected on activation- this is needed so that the backlinks menu can toggle views of targets on and off without selecting them
case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, undefined, undefined, keyValue);
}
};
@@ -748,7 +747,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}
@@ -805,20 +804,24 @@ 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={{ right: this.propertiesWidth() - 1, background: 'linen' }}>
- <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={this.colorScheme === ColorScheme.Dark ? Colors.WHITE : Colors.BLACK} size="sm" />
+ <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userVariantColor, 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() }}>
- {this.propertiesWidth() < 10 ? null : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
+ <div className="properties-container" style={{ width: this.propertiesWidth(), color: SettingsManager.userColor }}>
+ {
+ <div style={{ display: this.propertiesWidth() < 10 ? 'none' : undefined }}>
+ <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />
+ </div>
+ }
</div>
</div>
</div>
@@ -858,11 +861,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;
@@ -880,7 +883,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}
@@ -910,19 +913,22 @@ export class MainView extends React.Component {
childFiltersByRanges={returnEmptyFilter}
searchFilterDocs={returnEmptyDoclist}
/>
- {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ? <div style={{ border: '.5rem solid green', padding: '5px' }}>{StrCast(this.userDoc?.presentationMode)}</div> : <></>}
+ {['watching', 'recording'].includes(StrCast(this.userDoc?.presentationMode)) ? <div style={{ border: '.5rem solid green', padding: '5px' }}>{StrCast(this.userDoc?.presentationMode)}</div> : <></>}
</div>
);
}
@computed get snapLines() {
- return !SelectionManager.Views().some(dv => dv.rootDoc.freeform_snapLines) ? null : (
+ SnappingManager.GetIsDragging();
+ const dragged = DragManager.docsBeingDragged.lastElement();
+ const dragPar = dragged ? DocumentManager.Instance.getDocumentView(dragged)?.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView : undefined;
+ return !dragPar?.rootDoc.freeform_snapLines ? null : (
<div className="mainView-snapLines">
<svg style={{ width: '100%', height: '100%' }}>
{SnappingManager.horizSnapLines().map((l, i) => (
- <line key={i} x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={'1 1'} />
+ <line key={i} x1="0" y1={l} x2="2000" y2={l} stroke={lightOrDark(dragPar.rootDoc.backgroundColor ?? 'gray')} opacity={0.3} strokeWidth={1} strokeDasharray={'2 2'} />
))}
{SnappingManager.vertSnapLines().map((l, i) => (
- <line key={i} y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={'1 1'} />
+ <line key={i} y1={this.topOfMainDocContent.toString()} x1={l} y2="2000" x2={l} stroke={lightOrDark(dragPar.rootDoc.backgroundColor ?? 'gray')} opacity={0.3} strokeWidth={1} strokeDasharray={'2 2'} />
))}
</svg>
</div>
@@ -957,14 +963,50 @@ export class MainView extends React.Component {
@computed get linkDocPreview() {
return LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : null;
}
+ @observable mapBoxHackBool = false;
+ @computed get mapBoxHack() {
+ return this.mapBoxHackBool ? null : (
+ <MapBox
+ ref={action((r: any) => r && (this.mapBoxHackBool = true))}
+ fieldKey="data"
+ select={returnFalse}
+ isSelected={returnFalse}
+ Document={this.headerBarDoc}
+ DataDoc={undefined}
+ addDocTab={returnFalse}
+ pinToPres={emptyFunction}
+ docViewPath={returnEmptyDoclist}
+ styleProvider={DefaultStyleProvider}
+ rootSelected={returnTrue}
+ addDocument={returnFalse}
+ removeDocument={returnFalse}
+ fitContentsToBox={returnTrue}
+ isDocumentActive={returnTrue} // headerBar is always documentActive (ie, the docView gets pointer events)
+ isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive
+ ScreenToLocalTransform={Transform.Identity}
+ childHideResizeHandles={returnTrue}
+ childDragAction="move"
+ dontRegisterView={true}
+ PanelWidth={this.headerBarDocWidth}
+ PanelHeight={this.headerBarDocHeight}
+ renderDepth={0}
+ focus={emptyFunction}
+ whenChildContentsActiveChanged={emptyFunction}
+ bringToFront={emptyFunction}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ />
+ );
+ }
render() {
return (
<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 => {
@@ -1012,14 +1054,18 @@ export class MainView extends React.Component {
<ContextMenu />
<RadialMenu />
<AnchorMenu />
+ <MapAnchorMenu />
<DashFieldViewMenu />
<MarqueeOptionsMenu />
- <OverlayView />
<TimelineMenu />
<RichTextMenu />
<InkTranscription />
{this.snapLines}
<LightboxView key="lightbox" PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} />
+ <OverlayView />
+ {this.mapBoxHack}
+ <GPTPopup key="gptpopup" />
+ <GenerativeFill imageEditorOpen={ImageBox.imageEditorOpen} imageEditorSource={ImageBox.imageEditorSource} imageRootDoc={ImageBox.imageRootDoc} addDoc={ImageBox.addDoc} />
{/* <NewLightboxView key="newLightbox" PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} /> */}
</div>
);
@@ -1029,3 +1075,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');