diff options
Diffstat (limited to 'src/client/views/MainView.tsx')
-rw-r--r-- | src/client/views/MainView.tsx | 310 |
1 files changed, 251 insertions, 59 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 33cd43678..891d08214 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -12,10 +12,10 @@ import { Doc, DocListCast, Field, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { listSpec } from '../../fields/Schema'; -import { BoolCast, Cast, FieldValue, StrCast } from '../../fields/Types'; +import { BoolCast, Cast, FieldValue, StrCast, NumCast } from '../../fields/Types'; import { TraceMobx } from '../../fields/util'; import { CurrentUserUtils } from '../util/CurrentUserUtils'; -import { emptyFunction, emptyPath, returnFalse, returnOne, returnZero, returnTrue, Utils, returnEmptyFilter } from '../../Utils'; +import { emptyFunction, emptyPath, returnFalse, returnOne, returnZero, returnTrue, Utils, returnEmptyFilter, setupMoveUpEvents } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; @@ -44,7 +44,7 @@ import { RadialMenu } from './nodes/RadialMenu'; import { OverlayView } from './OverlayView'; import PDFMenu from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; -import { ScriptField } from '../../fields/ScriptField'; +import { ScriptField, ComputedField } from '../../fields/ScriptField'; import { TimelineMenu } from './animationtimeline/TimelineMenu'; import { SnappingManager } from '../util/SnappingManager'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; @@ -57,6 +57,12 @@ import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane"; import HypothesisAuthenticationManager from '../apis/HypothesisAuthenticationManager'; import CollectionMenu from './collections/CollectionMenu'; +import { Tooltip, AccordionActions } from '@material-ui/core'; +import { PropertiesView } from './collections/collectionFreeForm/PropertiesView'; +import { SelectionManager } from '../util/SelectionManager'; +import { PrefetchProxy } from '../../fields/Proxy'; +import { DragManager } from '../util/DragManager'; +import { discovery_v1, dialogflow_v2beta1 } from 'googleapis'; @observer export class MainView extends React.Component { @@ -69,8 +75,8 @@ export class MainView extends React.Component { @observable private _panelWidth: number = 0; @observable private _panelHeight: number = 0; - @observable private _flyoutTranslate: boolean = true; - @observable public flyoutWidth: number = 250; + @observable private _flyoutTranslate: boolean = false; + @observable public flyoutWidth: number = 0; private get darkScheme() { return BoolCast(Cast(this.userDoc?.activeWorkspace, Doc, null)?.darkScheme); } @computed private get userDoc() { return Doc.UserDoc(); } @@ -78,7 +84,26 @@ export class MainView extends React.Component { @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } @computed public get sidebarButtonsDoc() { return Cast(this.userDoc["tabs-buttons"], Doc) as Doc; } + @observable public sidebarContent: any = this.userDoc?.["tabs-panelContainer"]; + @observable public panelContent: string = "none"; + @observable public showProperties: boolean = false; public isPointerDown = false; + @computed get selectedDocumentView() { + if (SelectionManager.SelectedDocuments().length) { + return SelectionManager.SelectedDocuments()[0]; + } else { return undefined; } + } + + @observable _propertiesWidth: number = 0; + propertiesWidth = () => Math.max(0, Math.min(this._panelWidth - 50, this._propertiesWidth)); + + @computed get propertiesIcon() { + if (this.propertiesWidth() < 10) { + return "chevron-left"; + } else { + return "chevron-right"; + } + } componentDidMount() { DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's @@ -147,7 +172,8 @@ export class MainView extends React.Component { fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes, fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined, fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faChevronLeft, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript, - fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper); + fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper, + fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive); this.initEventListeners(); this.initAuthenticationRouters(); } @@ -209,7 +235,7 @@ export class MainView extends React.Component { const freeformOptions: DocumentOptions = { x: 0, y: 400, - _width: this._panelWidth * .7, + _width: this._panelWidth * .7 - this._propertiesWidth, _height: this._panelHeight, title: "Collection " + workspaceCount, }; @@ -275,10 +301,13 @@ export class MainView extends React.Component { @action onResize = (r: any) => { - this._panelWidth = r.offset.width; + this._panelWidth = r.offset.width - this._propertiesWidth; this._panelHeight = r.offset.height; } - getPWidth = () => this._panelWidth; + + @action + getPWidth = () => this._panelWidth - this._propertiesWidth; + getPHeight = () => this._panelHeight; getContentsHeight = () => this._panelHeight - this._buttonBarHeight; @@ -306,7 +335,8 @@ export class MainView extends React.Component { } } @computed get mainDocView() { - return <DocumentView Document={this.mainContainer!} + return <DocumentView + Document={this.mainContainer!} DataDoc={undefined} LibraryPath={emptyPath} addDocument={undefined} @@ -322,7 +352,6 @@ export class MainView extends React.Component { NativeWidth={returnZero} PanelWidth={this.getPWidth} PanelHeight={this.getPHeight} - renderDepth={0} focus={emptyFunction} parentActive={returnTrue} whenActiveChanged={emptyFunction} @@ -330,6 +359,7 @@ export class MainView extends React.Component { docFilters={returnEmptyFilter} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} + renderDepth={0} />; } @computed get dockingContent() { @@ -346,8 +376,11 @@ export class MainView extends React.Component { } _canClick = false; + + @action onPointerDown = (e: React.PointerEvent) => { if (this._flyoutTranslate) { + this.panelContent = "none"; this._canClick = true; this._flyoutSizeOnDown = e.clientX; document.removeEventListener("pointermove", this.onPointerMove); @@ -388,45 +421,18 @@ export class MainView extends React.Component { doc.dockingConfig ? this.openWorkspace(doc) : CollectionDockingView.AddRightSplit(doc, libraryPath); } - sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1); + sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0), 1); + //sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1); mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight); @computed get flyout() { - const sidebarContent = this.userDoc?.["tabs-panelContainer"]; - if (!(sidebarContent instanceof Doc)) { + if (!(this.sidebarContent instanceof Doc)) { return (null); } - return <div className="mainView-flyoutContainer" > - <div className="mainView-tabButtons" style={{ height: `${this._buttonBarHeight - 10/*margin-top*/}px`, backgroundColor: StrCast(this.sidebarButtonsDoc.backgroundColor) }}> - <DocumentView - Document={this.sidebarButtonsDoc} - DataDoc={undefined} - LibraryPath={emptyPath} - addDocument={undefined} - rootSelected={returnTrue} - addDocTab={this.addDocTabFunc} - pinToPres={emptyFunction} - removeDocument={undefined} - onClick={undefined} - ScreenToLocalTransform={this.sidebarScreenToLocal} - ContentScaling={returnOne} - NativeHeight={returnZero} - NativeWidth={returnZero} - PanelWidth={this.flyoutWidthFunc} - PanelHeight={this.getPHeight} - renderDepth={0} - focus={emptyFunction} - backgroundColor={this.defaultBackgroundColors} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} - bringToFront={emptyFunction} - docFilters={returnEmptyFilter} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> - </div> - <div className="mainView-contentArea" style={{ position: "relative", height: `calc(100% - ${this._buttonBarHeight}px)`, width: "100%", overflow: "visible" }}> + return <div className="mainView-libraryFlyout"> + <div className="mainView-contentArea" style={{ position: "relative", height: `100%`, width: "100%", overflow: "visible" }}> <DocumentView - Document={sidebarContent} + Document={this.sidebarContent} DataDoc={undefined} LibraryPath={emptyPath} addDocument={undefined} @@ -449,50 +455,227 @@ export class MainView extends React.Component { bringToFront={emptyFunction} docFilters={returnEmptyFilter} ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> - <div className="buttonContainer" > - <button className="mainView-settings" key="settings" onClick={() => SettingsManager.Instance.open()}> - <FontAwesomeIcon icon="cog" size="lg" /> - </button> + ContainingCollectionDoc={undefined} + relative={true} + /> + </div> + {this.docButtons}</div>; + } + + // @computed get menuPanel() { + + // return <div className="mainView-menuPanel"> + // <DocumentView + // Document={Doc.UserDoc().menuStack as Doc} + // DataDoc={undefined} + // LibraryPath={emptyPath} + // addDocument={undefined} + // addDocTab={this.addDocTabFunc} + // pinToPres={emptyFunction} + // NativeHeight={returnZero} + // NativeWidth={returnZero} + // rootSelected={returnTrue} + // removeDocument={returnFalse} + // onClick={undefined} + // ScreenToLocalTransform={this.mainContainerXf} + // ContentScaling={returnOne} + // PanelWidth={() => 80} + // PanelHeight={this.getContentsHeight} + // renderDepth={0} + // focus={emptyFunction} + // backgroundColor={this.defaultBackgroundColors} + // parentActive={returnTrue} + // whenActiveChanged={emptyFunction} + // bringToFront={emptyFunction} + // docFilters={returnEmptyFilter} + // ContainingCollectionView={undefined} + // ContainingCollectionDoc={undefined} + // relative={true} + // scriptContext={this} + // /> + // </div>; + // } + + @computed get menuPanel() { + return <div className="mainView-menuPanel"> + <div className="mainView-menuPanel-button" style={{ backgroundColor: this.panelContent === "workspace" ? "lightgrey" : "" }}> + <div className="mainView-menuPanel-button-wrap" + style={{ backgroundColor: this.panelContent === "workspace" ? "lightgrey" : "" }} + onPointerDown={e => this.selectPanel("workspace")}> + <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="desktop" + color={this.panelContent === "workspace" ? "black" : "white"} size="lg" /> + <div className="mainView-menuPanel-button-label" + style={{ color: this.panelContent === "workspace" ? "black" : "white" }}> Workspace </div> + </div> + </div> + + <div className="mainView-menuPanel-button" style={{ backgroundColor: this.panelContent === "catalog" ? "lightgrey" : "" }}> + <div className="mainView-menuPanel-button-wrap" + style={{ backgroundColor: this.panelContent === "catalog" ? "lightgrey" : "" }} + onPointerDown={e => this.selectPanel("catalog")}> + <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="file" + color={this.panelContent === "catalog" ? "black" : "white"} size="lg" /> + <div className="mainView-menuPanel-button-label" + style={{ color: this.panelContent === "catalog" ? "black" : "white" }}> Catalog </div> + </div> + </div> + + <div className="mainView-menuPanel-button" style={{ backgroundColor: this.panelContent === "deleted" ? "lightgrey" : "" }}> + <div className="mainView-menuPanel-button-wrap" + style={{ backgroundColor: this.panelContent === "deleted" ? "lightgrey" : "" }} + onPointerDown={e => this.selectPanel("deleted")}> + <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="archive" + color={this.panelContent === "deleted" ? "black" : "white"} size="lg" /> + <div className="mainView-menuPanel-button-label" + style={{ color: this.panelContent === "deleted" ? "black" : "white" }}> Recently Used </div> + </div> + </div> + + <div className="mainView-menuPanel-button"> + <div className="mainView-menuPanel-button-wrap" + onPointerDown={e => this.selectPanel("upload")}> + <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="upload" color="white" size="lg" /> + <div className="mainView-menuPanel-button-label"> Import </div> + </div> + </div> + + <div className="mainView-menuPanel-button"> + <div className="mainView-menuPanel-button-wrap" + //onPointerDown={e => this.selectPanel("sharing")} + onClick={() => GroupManager.Instance.open()}> + <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="users" color="white" size="lg" /> + <div className="mainView-menuPanel-button-label"> Sharing </div> + </div> + </div> + + <div className="mainView-menuPanel-button" style={{ marginBottom: "110px", backgroundColor: this.panelContent === "tools" ? "lightgrey" : "", }}> + <div className="mainView-menuPanel-button-wrap" + onPointerDown={e => this.selectPanel("tools")} + style={{ + backgroundColor: this.panelContent === "tools" ? "lightgrey" : "", + }}> + <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="wrench" + color={this.panelContent === "tools" ? "black" : "white"} size="lg" /> + <div className="mainView-menuPanel-button-label" + style={{ color: this.panelContent === "tools" ? "black" : "white" }}> Tools </div> + </div> + </div> + + <div className="mainView-menuPanel-button"> + <div className="mainView-menuPanel-button-wrap" + // style={{backgroundColor: this.panelContent= "help" ? "lightgrey" : "black"}} + onPointerDown={e => this.selectPanel("help")} > + <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="question-circle" color="white" size="lg" /> + <div className="mainView-menuPanel-button-label"> Help </div> + </div> + </div> + + <div className="mainView-menuPanel-button"> + <div className="mainView-menuPanel-button-wrap" + // onPointerDown={e => this.selectPanel("settings")} + onClick={() => SettingsManager.Instance.open()}> + <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="cog" color="white" size="lg" /> + <div className="mainView-menuPanel-button-label"> Settings </div> </div> </div> - {this.docButtons} + </div>; + } + + @action + selectPanel = (str: string) => { + if (this.panelContent === str && this.flyoutWidth !== 0) { + this.panelContent = "none"; + this.flyoutWidth = 0; + } else { + this.panelContent = str; + MainView.expandFlyout(); + if (str === "tools") { + CurrentUserUtils.toolsBtn; + this.sidebarContent.proto = CurrentUserUtils.toolsStack; + } else if (str === "workspace") { + this.sidebarContent.proto = CurrentUserUtils.workspaceStack; + } else if (str === "catalog") { + this.sidebarContent.proto = CurrentUserUtils.catalogStack; + } else if (str === "deleted") { + this.sidebarContent.proto = CurrentUserUtils.closedStack; + } else if (str === "search") { + this.sidebarContent.proto = CurrentUserUtils.searchStack; + } + } + return true; + } + + @action + onDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => { + this._propertiesWidth = this._panelWidth - Math.max(Transform.Identity().transformPoint(e.clientX, 0)[0], 0); + return false; + }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 200) : 0), false); + } + + @computed get propertiesView() { + TraceMobx(); + return <div className="mainView-propertiesView" style={{ + width: `200px`, + overflow: this.propertiesWidth() < 15 ? "hidden" : undefined + }}> + <PropertiesView + width={200} + height={this._panelHeight} + renderDepth={1} + ScreenToLocalTransform={Transform.Identity} + onDown={this.onDown} + /> </div>; } @computed get mainContent() { - const sidebar = this.userDoc?.["tabs-panelContainer"]; - const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0); + //const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0); + const n = (CollectionMenu.Instance?.Pinned ? 1 : 0); const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`; - return !this.userDoc || !(sidebar instanceof Doc) ? (null) : ( + + const rightFlyout = this.selectedDocumentView ? this._propertiesWidth - 1 : this.propertiesWidth() > 10 ? 151.5 : 0; + return !this.userDoc || !(this.sidebarContent instanceof Doc) ? (null) : ( <div className="mainView-mainContent" style={{ color: this.darkScheme ? "rgb(205,205,205)" : "black", //change to times 2 for both pinned height, width: (FormatShapePane.Instance?.Pinned) ? `calc(100% - 200px)` : "100%" }} > + {this.menuPanel} <div style={{ display: "contents", flexDirection: "row", position: "relative" }}> <div className="mainView-flyoutContainer" onPointerLeave={this.pointerLeaveDragger} style={{ width: this.flyoutWidth }}> - <div className="mainView-libraryHandle" onPointerDown={this.onPointerDown} - style={{ backgroundColor: this.defaultBackgroundColors(sidebar) }}> + {this.flyoutWidth !== 0 ? <div className="mainView-libraryHandle" + onPointerDown={this.onPointerDown} + style={{ backgroundColor: this.defaultBackgroundColors(this.sidebarContent) }}> <span title="library View Dragger" style={{ width: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "3vw", //height: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "100vh", position: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "absolute" : "fixed", top: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "" : "0" }} /> - </div> + <div className="mainview-libraryHandle-icon"> + <FontAwesomeIcon icon="chevron-left" color="black" size="sm" /> </div> + </div> : null} <div className="mainView-libraryFlyout" style={{ //transformOrigin: this._flyoutTranslate ? "" : "left center", transition: this._flyoutTranslate ? "" : "width .5s", //transform: `scale(${this._flyoutTranslate ? 1 : 0.8})`, - boxShadow: this._flyoutTranslate ? "" : "rgb(156, 147, 150) 0.2vw 0.2vw 0.8vw" + boxShadow: this._flyoutTranslate ? "" : "rgb(156, 147, 150) 0.2vw 0.2vw 0.2vw" }}> {this.flyout} {this.expandButton} </div> </div> {this.dockingContent} + {this.showProperties ? (null) : + <div className="mainView-propertiesDragger" title="Properties View Dragger" onPointerDown={this.onDown} + style={{ right: rightFlyout, top: "45%" }}> + <div className="mainView-propertiesDragger-icon"> + <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div> + </div> + } + {this.propertiesWidth() < 10 ? (null) : this.propertiesView} </div> </div>); } @@ -504,7 +687,7 @@ export class MainView extends React.Component { }); @computed get expandButton() { - return !this._flyoutTranslate ? (<div className="mainView-expandFlyoutButton" title="Re-attach sidebar" onPointerDown={MainView.expandFlyout}><FontAwesomeIcon icon="chevron-right" color="grey" size="lg" /></div>) : (null); + return !this._flyoutTranslate ? (<div className="mainView-expandFlyoutButton" title="Re-attach sidebar" onPointerDown={MainView.expandFlyout}></div>) : (null); } addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); @@ -598,8 +781,16 @@ export class MainView extends React.Component { </svg>; } + @computed get search() { + return <div className="mainView-searchPanel"> + <div style={{ float: "left", marginLeft: "10px" }}>{Doc.CurrentUserEmail}</div> + <div>SEARCH GOES HERE</div> + </div>; + } + render() { return (<div className={"mainView-container" + (this.darkScheme ? "-dark" : "")} ref={this._mainViewRef}> + {this.inkResources} <DictationOverlay /> <SharingManager /> @@ -608,9 +799,10 @@ export class MainView extends React.Component { <GoogleAuthenticationManager /> <HypothesisAuthenticationManager /> <DocumentDecorations /> + {/* {this.search} */} <CollectionMenu /> <FormatShapePane /> - <RichTextMenu key="rich" /> + <div style={{ display: "none" }}><RichTextMenu key="rich" /></div> {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null} {DocumentLinksButton.EditLink ? <LinkMenu location={DocumentLinksButton.EditLinkLoc} docView={DocumentLinksButton.EditLink} addDocTab={DocumentLinksButton.EditLink.props.addDocTab} changeFlyout={emptyFunction} /> : (null)} {LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} backgroundColor={this.defaultBackgroundColors} |