diff options
author | bobzel <zzzman@gmail.com> | 2022-09-14 14:37:43 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2022-09-14 14:37:43 -0400 |
commit | 081873137bfa860a183e10402073a36605d4d189 (patch) | |
tree | 3b2b5b20d153f93bb6eef1f0a6c371084f4c8b28 | |
parent | 9e24fb58f5cb7fca663c30e32b59dc70b80fa739 (diff) | |
parent | 1dd8e0bf7901700ef0eded57169cd4078a61cdd0 (diff) |
Merge branch 'master' into sharing-jenny
22 files changed, 306 insertions, 292 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 63080f8cf..14e6fe5bb 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -169,6 +169,7 @@ export class DocumentOptions { _raiseWhenDragged?: boolean; // whether a document is brought to front when dragged. _hideContextMenu?: boolean; // whether the context menu can be shown _viewType?: string; // sub type of a collection + viewType?: string; // sub type of a collection _gridGap?: number; // gap between items in masonry view _viewScale?: number; // how much a freeform view has been scaled (zoomed) _overflow?: string; // set overflow behavior @@ -1142,7 +1143,7 @@ export namespace Docs { } export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: 'remove|add', ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: 'remove|add', ...options, viewType: CollectionViewType.Docking, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); } export function DirectoryImportDocument(options: DocumentOptions = {}) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 3f3816a8a..c6a3959ee 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -269,7 +269,7 @@ export class CurrentUserUtils { {key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }}, // {key: "DataViz", creator: opts => Docs.Create.DataVizDocument(opts), opts: { _width: 300, _height: 300 }}, {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true,}}, - {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 500, _viewType: CollectionViewType.Stacking, targetDropAction: "alias" as any, treeViewHideTitle: true, _chromeHidden: true, boxShadow: "0 0" }}, + {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _viewType: CollectionViewType.Stacking, targetDropAction: "alias" as any, treeViewHideTitle: true, _chromeHidden: true, boxShadow: "0 0" }}, {key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _backgroundGridShow: true, }}, {key: "Slide", creator: opts => Docs.Create.TreeDocument([], opts), opts: { _width: 300, _height: 200, _viewType: CollectionViewType.Tree, treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true, @@ -326,13 +326,13 @@ export class CurrentUserUtils { const badgeValue = "((len) => len && len !== '0' ? len: undefined)(docList(self.target.data).filter(doc => !docList(self.target.viewed).includes(doc)).length.toString())"; const getActiveDashTrails = "Doc.ActiveDashboard?.myTrails"; return [ - { title: "Dashboards", target: this.setupDashboards(doc, "myDashboards"), icon: "desktop", }, + { title: "Dashboards", target: this.setupDashboards(doc, "myDashboards"), icon: "desktop", funcs: {hidden: "IsNoviceMode()"} }, { title: "Search", target: this.setupSearcher(doc, "mySearcher"), icon: "search", }, { title: "Files", target: this.setupFilesystem(doc, "myFilesystem"), icon: "folder-open", }, { title: "Tools", target: this.setupToolsBtnPanel(doc, "myTools"), icon: "wrench", funcs: {hidden: "IsNoviceMode()"} }, { title: "Imports", target: this.setupImportSidebar(doc, "myImports"), icon: "upload", }, { title: "Recently Closed", target: this.setupRecentlyClosed(doc, "myRecentlyClosed"), icon: "archive", }, - { title: "Shared Docs", target: Doc.MySharedDocs, icon: "users", funcs:{badgeValue:badgeValue}}, + { title: "Shared Docs", target: Doc.MySharedDocs, icon: "users", funcs: {badgeValue:badgeValue}}, { title: "Trails", target: Doc.UserDoc(), icon: "pres-trail", funcs: {target: getActiveDashTrails}}, { title: "User Doc View", target: this.setupUserDocView(doc, "myUserDocView"), icon: "address-card",funcs: {hidden: "IsNoviceMode()"} }, ].map(tuple => ({...tuple, scripts:{onClick: 'selectMainMenu(self)'}})); @@ -749,7 +749,7 @@ export class CurrentUserUtils { childContextMenuLabels: new List<string>(["Add to Dashboards",]), childContextMenuIcons: new List<string>(["user-plus",]), "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, - childDropAction: "alias", system: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 50, _gridGap: 15, + childDropAction: "alias", system: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, // NOTE: treeViewHideTitle & _showTitle is for a TreeView's editable title, _showTitle is for DocumentViews title bar _showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, explainer: "This is where documents or dashboards that other users have shared with you will appear. To share a document or dashboard right click and select 'Share'" diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 7a555d5f8..a3d6f5227 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -91,7 +91,7 @@ export namespace SelectionManager { } export function Views(): Array<DocumentView> { - return Array.from(manager.SelectedViews.keys()).filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking); + return Array.from(manager.SelectedViews.keys()); //.filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking); } export function SelectedSchemaDoc(): Doc | undefined { return manager.SelectedSchemaDocument; diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 6415601f1..12fc3133d 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -50,7 +50,7 @@ export class DashboardView extends React.Component { this.selectedDashboardGroup = group; }; - clickDashboard = async (e: React.MouseEvent, dashboard: Doc) => { + clickDashboard = (e: React.MouseEvent, dashboard: Doc) => { if (e.detail === 2) { Doc.AddDocToList(Doc.MySharedDocs, 'viewed', dashboard); Doc.ActiveDashboard = dashboard; @@ -156,7 +156,7 @@ export class DashboardView extends React.Component { </div> <div className="all-dashboards"> {this.getDashboards().map(dashboard => { - const href = ImageCast((dashboard.thumb as Doc)?.data)?.url.href; + const href = ImageCast(dashboard.thumb)?.url.href; return ( <div className="dashboard-container" diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 832d0a35c..0fc33bdea 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -189,7 +189,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P onCloseClick = (forceDeleteOrIconify: boolean | undefined) => { const views = SelectionManager.Views() .slice() - .filter(v => v); + .filter(v => v && v.props.renderDepth > 0); if (forceDeleteOrIconify === false && this._iconifyBatch) return; this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false; if (!this._iconifyBatch) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index c1cc80163..26718d695 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -9,7 +9,6 @@ import 'normalize.css'; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; -import { List } from '../../fields/List'; import { ScriptField } from '../../fields/ScriptField'; import { DocCast, StrCast } from '../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils'; @@ -34,7 +33,6 @@ import { CollectionDockingView } from './collections/CollectionDockingView'; import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; import { CollectionLinearView } from './collections/collectionLinear'; import { CollectionMenu } from './collections/CollectionMenu'; -import { CollectionView } from './collections/CollectionView'; import './collections/TreeView.scss'; import { ComponentDecorations } from './ComponentDecorations'; import { ContextMenu } from './ContextMenu'; @@ -115,8 +113,7 @@ export class MainView extends React.Component { } @observable mainDoc: Opt<Doc>; @computed private get mainContainer() { - if (Doc.ActiveDashboard) return Doc.ActiveDashboard; - if (window.location.pathname.startsWith('/doc/')) { + if (window.location.pathname.startsWith('/doc/') && Doc.CurrentUserEmail === 'guest') { DocServer.GetRefField(window.location.pathname.substring('/doc/'.length)).then(main => runInAction(() => (this.mainDoc = main as Doc))); return this.mainDoc; } @@ -166,6 +163,7 @@ export class MainView extends React.Component { 'sidebarWidthPercent', 'currentTimecode', 'timelineHeightPercent', + 'presStatus', 'panX', 'panY', 'overlayX', @@ -536,7 +534,6 @@ export class MainView extends React.Component { @action createNewPresentation = () => { const pres = Doc.MakeCopy(Doc.UserDoc().emptyTrail as Doc, true); - Docs.Create.PresDocument({ title: 'Untitled Trail', _viewType: CollectionViewType.Stacking, _fitWidth: true, treeViewHideTitle: true, _width: 400, _height: 500, targetDropAction: 'alias', _chromeHidden: true, boxShadow: '0 0' }); CollectionDockingView.AddSplit(pres, 'left'); Doc.MyTrails && Doc.AddDocToList(Doc.MyTrails, 'data', pres); // Doc.MyTrails should be created in createDashboard Doc.ActivePresentation = pres; diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 2354e84ff..6d7f2c037 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -12,6 +12,7 @@ import { DragManager } from '../util/DragManager'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { Transform } from '../util/Transform'; import { CollectionFreeFormLinksView } from './collections/collectionFreeForm/CollectionFreeFormLinksView'; +import { LightboxView } from './LightboxView'; import { DocumentView } from './nodes/DocumentView'; import './OverlayView.scss'; import { ScriptingRepl } from './ScriptingRepl'; @@ -90,7 +91,7 @@ export class OverlayWindow extends React.Component<OverlayWindowProps> { }; render() { - return ( + return LightboxView.LightboxDoc ? null : ( <div className="overlayWindow-outerDiv" style={{ transform: `translate(${this.x}px, ${this.y}px)`, width: this.width, height: this.height }}> <div className="overlayWindow-titleBar" onPointerDown={this.onPointerDown}> {this.props.overlayOptions.title || 'Untitled'} @@ -169,72 +170,74 @@ export class OverlayView extends React.Component { ); @computed get overlayDocs() { - return DocListCast(Doc.MyOverlayDocs?.data).map(d => { - let offsetx = 0, - offsety = 0; - const dref = React.createRef<HTMLDivElement>(); - const onPointerMove = action((e: PointerEvent, down: number[]) => { - if (e.buttons === 1) { - d.overlayX = e.clientX + offsetx; - d.overlayY = e.clientY + offsety; - } - if (e.metaKey) { - const dragData = new DragManager.DocumentDragData([d]); - dragData.offset = [-offsetx, -offsety]; - dragData.dropAction = 'move'; - dragData.removeDocument = (doc: Doc | Doc[]) => { - const docs = doc instanceof Doc ? [doc] : doc; - docs.forEach(d => Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, d)); - return true; - }; - dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { - return dragData.removeDocument!(doc) ? addDocument(doc) : false; - }; - DragManager.StartDocumentDrag([dref.current!], dragData, down[0], down[1]); - return true; - } - return false; - }); + return LightboxView.LightboxDoc + ? null + : DocListCast(Doc.MyOverlayDocs?.data).map(d => { + let offsetx = 0, + offsety = 0; + const dref = React.createRef<HTMLDivElement>(); + const onPointerMove = action((e: PointerEvent, down: number[]) => { + if (e.buttons === 1) { + d.overlayX = e.clientX + offsetx; + d.overlayY = e.clientY + offsety; + } + if (e.metaKey) { + const dragData = new DragManager.DocumentDragData([d]); + dragData.offset = [-offsetx, -offsety]; + dragData.dropAction = 'move'; + dragData.removeDocument = (doc: Doc | Doc[]) => { + const docs = doc instanceof Doc ? [doc] : doc; + docs.forEach(d => Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, d)); + return true; + }; + dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { + return dragData.removeDocument!(doc) ? addDocument(doc) : false; + }; + DragManager.StartDocumentDrag([dref.current!], dragData, down[0], down[1]); + return true; + } + return false; + }); - const onPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, onPointerMove, emptyFunction, emptyFunction); - offsetx = NumCast(d.overlayX) - e.clientX; - offsety = NumCast(d.overlayY) - e.clientY; - }; - return ( - <div - className="overlayView-doc" - ref={dref} - key={d[Id]} - onPointerDown={onPointerDown} - style={{ top: d.type === 'presentation' ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.overlayX}px, ${d.overlayY}px)` }}> - <DocumentView - Document={d} - rootSelected={returnTrue} - bringToFront={emptyFunction} - addDocument={undefined} - removeDocument={this.removeOverlayDoc} - PanelWidth={d[WidthSym]} - PanelHeight={d[HeightSym]} - ScreenToLocalTransform={this.docScreenToLocalXf(d)} - renderDepth={1} - isDocumentActive={returnTrue} - isContentActive={returnTrue} - whenChildContentsActiveChanged={emptyFunction} - focus={DocUtils.DefaultFocus} - styleProvider={DefaultStyleProvider} - docViewPath={returnEmptyDoclist} - addDocTab={returnFalse} - pinToPres={emptyFunction} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - /> - </div> - ); - }); + const onPointerDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, onPointerMove, emptyFunction, emptyFunction); + offsetx = NumCast(d.overlayX) - e.clientX; + offsety = NumCast(d.overlayY) - e.clientY; + }; + return ( + <div + className="overlayView-doc" + ref={dref} + key={d[Id]} + onPointerDown={onPointerDown} + style={{ top: d.type === 'presentation' ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.overlayX}px, ${d.overlayY}px)` }}> + <DocumentView + Document={d} + rootSelected={returnTrue} + bringToFront={emptyFunction} + addDocument={undefined} + removeDocument={this.removeOverlayDoc} + PanelWidth={d[WidthSym]} + PanelHeight={d[HeightSym]} + ScreenToLocalTransform={this.docScreenToLocalXf(d)} + renderDepth={1} + isDocumentActive={returnTrue} + isContentActive={returnTrue} + whenChildContentsActiveChanged={emptyFunction} + focus={DocUtils.DefaultFocus} + styleProvider={DefaultStyleProvider} + docViewPath={returnEmptyDoclist} + addDocTab={returnFalse} + pinToPres={emptyFunction} + docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + /> + </div> + ); + }); } public static ShowSpinner() { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 10b54edad..31c839af7 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -6,7 +6,7 @@ import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; -import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { inheritParentAcls } from '../../../fields/util'; import { emptyFunction, incrementTitleCopy } from '../../../Utils'; @@ -56,7 +56,7 @@ export class CollectionDockingView extends CollectionSubView() { constructor(props: SubCollectionViewProps) { super(props); - runInAction(() => (CollectionDockingView.Instance = this)); + if (this.props.renderDepth < 0) runInAction(() => (CollectionDockingView.Instance = this)); //Why is this here? (window as any).React = React; (window as any).ReactDOM = ReactDOM; @@ -73,7 +73,7 @@ export class CollectionDockingView extends CollectionSubView() { public StartOtherDrag = (e: { pageX: number; pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => { this._flush = this._flush ?? UndoManager.StartBatch('golden layout drag'); const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) : { type: 'row', content: dragDocs.map(doc => CollectionDockingView.makeDocumentConfig(doc)) }; - const dragSource = this._goldenLayout.createDragSource(document.createElement('div'), config); + const dragSource = CollectionDockingView.Instance?._goldenLayout.createDragSource(document.createElement('div'), config); this.tabDragStart(dragSource, finishDrag); dragSource._dragListener.onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 }); }; @@ -395,10 +395,10 @@ export class CollectionDockingView extends CollectionSubView() { const _height = Number(getComputedStyle(content).height.replace('px', '')); return CollectionFreeFormView.UpdateIcon(this.layoutDoc[Id] + '-icon' + new Date().getTime(), content, _width, _height, _width, _height, 0, 1, true, this.layoutDoc[Id] + '-icon', (iconFile, _nativeWidth, _nativeHeight) => { const img = Docs.Create.ImageDocument(new ImageField(iconFile), { title: this.rootDoc.title + '-icon', _width, _height, _nativeWidth, _nativeHeight }); - const proto = Cast(img.proto, Doc, null)!; - proto['data-nativeWidth'] = _width; - proto['data-nativeHeight'] = _height; - this.dataDoc.thumb = img; + const proto = this.dataDoc; // Cast(img.proto, Doc, null)!; + proto['thumb-nativeWidth'] = _width; + proto['thumb-nativeHeight'] = _height; + this.dataDoc.thumb = new ImageField(iconFile); }); } } @@ -532,7 +532,23 @@ export class CollectionDockingView extends CollectionSubView() { }; render() { - return <div className="collectiondockingview-container" onPointerDown={this.onPointerDown} ref={this._containerRef} />; + const href = ImageCast(this.rootDoc.thumb)?.url.href; + return this.props.renderDepth > -1 ? ( + <div> + {href ? ( + <img + style={{ background: 'white', top: 0, position: 'absolute' }} + src={href} // + '?d=' + (new Date()).getTime()} + width={this.props.PanelWidth()} + height={this.props.PanelHeight()} + /> + ) : ( + <p>nested dashboards has no thumbnail</p> + )} + </div> + ) : ( + <div className="collectiondockingview-container" onPointerDown={this.onPointerDown} ref={this._containerRef} /> + ); } } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 4227955ef..7fc1a800b 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -212,7 +212,7 @@ export function CollectionSubView<X>(moreProps?: X) { let added = false; const dropAction = docDragData.dropAction || docDragData.userDropAction; const targetDocments = DocListCast(this.dataDoc[this.props.fieldKey]); - const someMoved = !docDragData.userDropAction && docDragData.draggedDocuments.some(drag => targetDocments.includes(drag)); + const someMoved = !dropAction && docDragData.draggedDocuments.some(drag => targetDocments.includes(drag)); if (someMoved) docDragData.droppedDocuments = docDragData.droppedDocuments.map((drop, i) => (targetDocments.includes(docDragData.draggedDocuments[i]) ? docDragData.draggedDocuments[i] : drop)); if ((!dropAction || dropAction === 'same' || dropAction === 'move' || someMoved) && docDragData.moveDocument) { const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 1ee77d4ce..0a06b6e00 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -116,6 +116,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab switch (type) { default: case CollectionViewType.Freeform: return <CollectionFreeFormView key="collview" {...props} />; + case CollectionViewType.Docking: return <CollectionDockingView key="collview" {...props} />; case CollectionViewType.Schema: return <CollectionSchemaView key="collview" {...props} />; case CollectionViewType.Docking: return <CollectionDockingView key="collview" {...props} />; case CollectionViewType.Tree: return <CollectionTreeView key="collview" {...props} />; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 46386fa71..b9262763f 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -400,7 +400,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap); @computed get docView() { - return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? null : ( + return !this._activated || !this._document ? null : ( <> <DocumentView key={this._document[Id]} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 039407e77..6927d429d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -116,8 +116,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @observable ChildDrag: DocumentView | undefined; // child document view being dragged. needed to update drop areas of groups when a group item is dragged. @computed get views() { - const viewsMask = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask !== -1).map(ele => ele.ele); - const renderableEles = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask === -1).map(ele => ele.ele); + const viewsMask = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask !== -1 && ele.inkMask !== undefined).map(ele => ele.ele); + const renderableEles = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && (ele.inkMask === -1 || ele.inkMask === undefined)).map(ele => ele.ele); if (viewsMask.length) renderableEles.push(<div className={`collectionfreeformview-mask${this._layoutElements.some(ele => (ele.inkMask ?? 0) > 0) ? '' : '-empty'}`}>{viewsMask}</div>); return renderableEles; } @@ -1425,15 +1425,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @computed get doInternalLayoutComputation() { TraceMobx(); const newPool = new Map<string, PoolData>(); + // prettier-ignore switch (this.layoutEngine) { - case 'pass': - return { newPool, computedElementData: this.doEngineLayout(newPool, computerPassLayout) }; - case 'timeline': - return { newPool, computedElementData: this.doEngineLayout(newPool, computeTimelineLayout) }; - case 'pivot': - return { newPool, computedElementData: this.doEngineLayout(newPool, computePivotLayout) }; - case 'starburst': - return { newPool, computedElementData: this.doEngineLayout(newPool, computerStarburstLayout) }; + case 'pass': return { newPool, computedElementData: this.doEngineLayout(newPool, computerPassLayout) }; + case 'timeline': return { newPool, computedElementData: this.doEngineLayout(newPool, computeTimelineLayout) }; + case 'pivot': return { newPool, computedElementData: this.doEngineLayout(newPool, computePivotLayout) }; + case 'starburst': return { newPool, computedElementData: this.doEngineLayout(newPool, computerStarburstLayout) }; } return { newPool, computedElementData: this.doFreeformLayout(newPool) }; } diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 8437736ae..497b4993c 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -348,8 +348,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp Doc.GetProto(newDoc).recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.fieldKey}-recordingStart"]`); Doc.GetProto(newDoc).mediaState = ComputedField.MakeFunction('self.recordingSource.mediaState'); if (DocListCast(Doc.MyOverlayDocs?.data).includes(this.rootDoc)) { - newDoc.x = this.rootDoc.x; - newDoc.y = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height); + newDoc.overlayX = this.rootDoc.x; + newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height); Doc.AddDocToList(Doc.MyOverlayDocs, undefined, newDoc); } else { this.props.addDocument?.(newDoc); diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index a37de7f69..9ffbf8e37 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -5,7 +5,7 @@ import { observer } from 'mobx-react'; import { Doc, Opt } from '../../../fields/Doc'; import { StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, returnFalse, setupMoveUpEvents, StopEvent } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { Hypothesis } from '../../util/HypothesisUtils'; @@ -287,7 +287,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp </div> ) : null} {this.props.InMenu && this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again - <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton} onPointerDown={isActive ? undefined : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}> + <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton} onPointerDown={isActive ? StopEvent : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}> <FontAwesomeIcon className="documentdecorations-icon" icon="link" /> </div> ) : null} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e628c2e44..cab0e744f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1000,7 +1000,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps LightboxView.LightboxDoc !== this.rootDoc && this.thumb && !Doc.AreProtosEqual(DocumentLinksButton.StartLink, this.rootDoc) && - !Doc.isBrushedHighlightedDegree(this.props.Document) && + (!Doc.isBrushedHighlightedDegree(this.props.Document) || this.rootDoc._viewType === CollectionViewType.Docking) && !this._componentView?.isAnyChildContentActive?.() ? true : false; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 93ca22d5d..f50524e4e 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -249,7 +249,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { searchFilterDocs={returnEmptyDoclist} ContainingCollectionDoc={undefined} ContainingCollectionView={undefined} - renderDepth={-1} + renderDepth={0} suppressSetHeight={true} PanelWidth={this.width} PanelHeight={this.height} diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss index c2aee7a1b..5e1359441 100644 --- a/src/client/views/nodes/VideoBox.scss +++ b/src/client/views/nodes/VideoBox.scss @@ -83,6 +83,8 @@ .videoBox-ui-wrapper { width: 0; height: 0; + position: relative; + z-index: 100001; } .videoBox-ui { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 5cb805f80..dd8eb1f7a 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1006,7 +1006,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, autoHeight: this.autoHeight, marginsHeight: this.autoHeightMargins }), ({ sidebarHeight, textHeight, autoHeight, marginsHeight }) => { const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight)); - if (autoHeight && newHeight && newHeight !== this.rootDoc.height) { + if (autoHeight && newHeight && newHeight !== this.rootDoc.height && !this.props.dontRegisterView) { this.props.setHeight?.(newHeight); } }, @@ -1701,7 +1701,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace('px', '')) + Number(getComputedStyle(child).marginTop.replace('px', '')) + Number(getComputedStyle(child).marginBottom.replace('px', '')), margins); const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); - if (this.props.setHeight && scrollHeight && this.props.renderDepth && !this.props.dontRegisterView) { + if (this.props.setHeight && scrollHeight && !this.props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation const setScrollHeight = () => (this.rootDoc[this.fieldKey + '-scrollHeight'] = scrollHeight); if (this.rootDoc === this.layoutDoc || this.layoutDoc.resolvedDataDoc) { @@ -1862,7 +1862,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps className={`formattedTextBox-cont`} ref={this._ref} style={{ - overflow: this.autoHeight ? 'hidden' : undefined, + //overflow: this.autoHeight ? 'hidden' : undefined, //x this breaks viewing an autoHeight doc in its own tab, or in the lightbox height: this.props.height || (this.autoHeight && this.props.renderDepth && !this.props.suppressSetHeight ? 'max-content' : undefined), pointerEvents: interactive ? undefined : 'none', }} diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index a4db2d777..5bede448d 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -239,16 +239,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { // TODO: to handle child slides (entering into subtrail and exiting), also the next() and back() functions // No more frames in current doc and next slide is defined, therefore move to next slide nextSlide = (activeNext: Doc) => { - const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null); - console.info('nextSlide', activeNext.title, targetNext?.title); let nextSelected = this.itemIndex + 1; this.gotoDocument(nextSelected, this.activeItem); for (nextSelected = nextSelected + 1; nextSelected < this.childDocs.length; nextSelected++) { - if (!this.childDocs[nextSelected].groupWithUp) { - break; - } else { - console.log('Title: ' + this.childDocs[nextSelected].title); + if (this.childDocs[nextSelected].groupWithUp) { this.gotoDocument(nextSelected, this.activeItem, true); + } else { + break; } } }; @@ -2578,7 +2575,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { const mode = StrCast(this.rootDoc._viewType) as CollectionViewType; const presEnd: boolean = !this.layoutDoc.presLoop && this.itemIndex === this.childDocs.length - 1; const presStart: boolean = !this.layoutDoc.presLoop && this.itemIndex === 0; - return DocListCast(Doc.MyOverlayDocs?.data).includes(this.rootDoc) ? ( + return this.props.addDocTab === returnFalse ? ( // bcz: hack!! - addDocTab === returnFalse only when this is being rendered by the OverlayView which means the doc is a mini player <div className="miniPres" onClick={e => e.stopPropagation()} onPointerEnter={action(e => (this._forceKeyEvents = true))}> <div className="presPanelOverlay" diff --git a/src/client/views/nodes/trails/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss index 969f034a8..8a6c2a6dc 100644 --- a/src/client/views/nodes/trails/PresElementBox.scss +++ b/src/client/views/nodes/trails/PresElementBox.scss @@ -1,161 +1,159 @@ -$light-blue: #AEDDF8; -$dark-blue: #5B9FDD; +$light-blue: #aeddf8; +$dark-blue: #5b9fdd; $light-background: #ececec; $slide-background: #d5dce2; -$slide-active: #5B9FDD; +$slide-active: #5b9fdd; .presItem-container { - cursor: grab; - display: flex; - grid-template-columns: 20px auto; - font-family: Roboto; - letter-spacing: normal; - position: relative; - pointer-events: all; - width: 100%; - height: 100%; - font-weight: 400; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - align-items: center; - - // .presItem-number { - // margin-top: 3.5px; - // font-size: 12px; - // font-weight: 700; - // text-align: center; - // justify-self: center; - // align-self: flex-start; - // position: relative; - // display: inline-block; - // overflow: hidden; - // } + cursor: grab; + display: flex; + grid-template-columns: 20px auto; + font-family: Roboto; + letter-spacing: normal; + position: relative; + pointer-events: all; + width: 100%; + height: 100%; + font-weight: 400; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + align-items: center; + // .presItem-number { + // margin-top: 3.5px; + // font-size: 12px; + // font-weight: 700; + // text-align: center; + // justify-self: center; + // align-self: flex-start; + // position: relative; + // display: inline-block; + // overflow: hidden; + // } } .presItem-slide { - position: relative; - height: 100%; - width: 100%; - border-bottom: .5px solid grey; - display: flex; - justify-content: space-between; - align-items: center; - grid-template-rows: 16px 10px auto; - grid-template-columns: max-content max-content max-content max-content auto; + position: relative; + height: 100%; + width: 100%; + border-bottom: 0.5px solid grey; + display: flex; + justify-content: space-between; + align-items: center; + grid-template-rows: 16px 10px auto; + grid-template-columns: max-content max-content max-content max-content auto; - .presItem-name { - display: flex; - min-width: 20px; - z-index: 300; - top: 2px; - align-self: center; - font-size: 11px; - font-family: Roboto; - font-weight: 500; - position: relative; - padding-left: 10px; - padding-right: 10px; - letter-spacing: normal; - width: max-content; - text-overflow: ellipsis; - overflow: hidden; - white-space: pre; - } + .presItem-name { + display: flex; + min-width: 20px; + z-index: 300; + top: 2px; + align-self: center; + font-size: 11px; + font-family: Roboto; + font-weight: 500; + position: relative; + padding-left: 10px; + padding-right: 10px; + letter-spacing: normal; + width: max-content; + text-overflow: ellipsis; + overflow: hidden; + white-space: pre; + } - .presItem-docName { - min-width: 20px; - z-index: 300; - align-self: center; - font-size: 9px; - font-family: Roboto; - font-weight: 300; - position: relative; - padding-left: 10px; - padding-right: 10px; - letter-spacing: normal; - width: max-content; - text-overflow: ellipsis; - overflow: hidden; - white-space: pre; - grid-row: 2; - grid-column: 1/6; - } + .presItem-docName { + min-width: 20px; + z-index: 300; + align-self: center; + font-size: 9px; + font-family: Roboto; + font-weight: 300; + position: relative; + padding-left: 10px; + padding-right: 10px; + letter-spacing: normal; + width: max-content; + text-overflow: ellipsis; + overflow: hidden; + white-space: pre; + grid-row: 2; + grid-column: 1/6; + } - .presItem-time { - align-self: center; - position: relative; - padding-right: 10px; - top: 1px; - font-size: 10; - font-weight: 300; - font-family: Roboto; - z-index: 300; - letter-spacing: normal; - } + .presItem-time { + align-self: center; + position: relative; + padding-right: 10px; + top: 1px; + font-size: 10; + font-weight: 300; + font-family: Roboto; + z-index: 300; + letter-spacing: normal; + } - .presItem-embedded { - overflow: hidden; - grid-row: 3; - grid-column: 1/8; - position: relative; - display: flex; - width: auto; - justify-content: center; - margin: auto; - margin-bottom: 2px; - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; - } + .presItem-embedded { + overflow: hidden; + grid-row: 3; + grid-column: 1/8; + position: relative; + display: flex; + width: auto; + justify-content: center; + margin: auto; + margin-bottom: 2px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + } - .presItem-embeddedMask { - width: 100%; - height: 100%; - position: absolute; - border-radius: 3px; - top: 0; - left: 0; - z-index: 1; - overflow: hidden; - } + .presItem-embeddedMask { + width: 100%; + height: 100%; + position: absolute; + border-radius: 3px; + top: 0; + left: 0; + z-index: 1; + overflow: hidden; + } + .presItem-slideButtons { + display: flex; + grid-column: 7; + grid-row: 1/3; + width: max-content; + justify-self: right; + justify-content: flex-end; - .presItem-slideButtons { + .slideButton { + cursor: pointer; + position: relative; + border-radius: 100px; + z-index: 300; + width: 18px; + height: 18px; display: flex; - grid-column: 7; - grid-row: 1/3; - width: max-content; - justify-self: right; - justify-content: flex-end; - - .slideButton { - cursor: pointer; - position: relative; - border-radius: 100px; - z-index: 300; - width: 18px; - height: 18px; - display: flex; - font-size: 12px; - justify-self: center; - align-self: center; - background-color: rgba(0, 0, 0, 0.5); - color: white; - justify-content: center; - align-items: center; - transition: 0.2s; - margin-right: 3px; - } + font-size: 12px; + justify-self: center; + align-self: center; + background-color: rgba(0, 0, 0, 0.5); + color: white; + justify-content: center; + align-items: center; + transition: 0.2s; + margin-right: 3px; + } - .slideButton:hover { - background-color: rgba(0, 0, 0, 1); - transform: scale(1.2); - } - } + .slideButton:hover { + background-color: rgba(0, 0, 0, 1); + transform: scale(1.2); + } + } } // .presItem-slide:hover { @@ -194,7 +192,8 @@ $slide-active: #5B9FDD; // } .presItem-slide.active { - box-shadow: 0 0 0px 2.5px $dark-blue; + //box-shadow: 0 0 0px 2.5px $dark-blue; + border: $dark-blue solid 2.5px; } .presItem-slide.group { @@ -239,38 +238,38 @@ $slide-active: #5B9FDD; } .presItem-multiDrag { - font-family: Roboto; - font-weight: 600; - color: white; - text-align: center; - justify-content: center; - align-content: center; - width: 100px; - height: 30px; - position: absolute; - background-color: $dark-blue; - z-index: 4000; - border-radius: 10px; - box-shadow: black 0.4vw 0.4vw 0.8vw; - line-height: 30px; + font-family: Roboto; + font-weight: 600; + color: white; + text-align: center; + justify-content: center; + align-content: center; + width: 100px; + height: 30px; + position: absolute; + background-color: $dark-blue; + z-index: 4000; + border-radius: 10px; + box-shadow: black 0.4vw 0.4vw 0.8vw; + line-height: 30px; } .presItem-miniSlide { - font-weight: 700; - font-size: 12; - grid-column: 1/8; - align-self: center; - justify-self: center; - background-color: #d5dce2; - width: 26px; - text-align: center; - height: 26px; - line-height: 28px; - border-radius: 100%; + font-weight: 700; + font-size: 12; + grid-column: 1/8; + align-self: center; + justify-self: center; + background-color: #d5dce2; + width: 26px; + text-align: center; + height: 26px; + line-height: 28px; + border-radius: 100%; } .presItem-miniSlide.active { - box-shadow: 0 0 0px 1.5px $dark-blue; + box-shadow: 0 0 0px 1.5px $dark-blue; } .expandButton { @@ -306,4 +305,4 @@ $slide-active: #5B9FDD; top: 1; font-weight: 600; font-size: 12; -}
\ No newline at end of file +} diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index d88ff45fa..e3f93c637 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -405,7 +405,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { @action startRecording = (e: React.MouseEvent, activeItem: Doc) => { e.stopPropagation(); - console.log('start recording', 'activeItem', activeItem); if (PresElementBox.videoIsRecorded(activeItem)) { // if we already have an existing recording this.showRecording(activeItem, true); @@ -432,8 +431,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { activeItem.recording = recording; // make recording box appear in the bottom right corner of the screen - recording.x = window.innerWidth - recording[WidthSym]() - 20; - recording.y = window.innerHeight - recording[HeightSym]() - 20; + recording.overlayX = window.innerWidth - recording[WidthSym]() - 20; + recording.overlayY = window.innerHeight - recording[HeightSym]() - 20; Doc.AddDocToList(Doc.MyOverlayDocs, undefined, recording); } }; @@ -449,6 +448,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { @computed get mainItem() { const isSelected: boolean = this.selectedArray?.has(this.rootDoc) ? true : false; + const isCurrent: boolean = this.presBox._itemIndex === this.indexInPres; const toolbarWidth: number = this.toolbarWidth; const showMore: boolean = this.toolbarWidth >= 300; const miniView: boolean = this.toolbarWidth <= 110; @@ -487,10 +487,11 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { ) : ( <div ref={this._dragRef} - className={`presItem-slide ${isSelected ? 'active' : ''}`} + className={`presItem-slide ${isCurrent ? 'active' : ''}`} style={{ backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor), - boxShadow: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isSelected ? '0 0 0px 1.5px' + presBoxColor : undefined) : undefined, + //boxShadow: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? '0 0 0px 1.5px' + presBoxColor : undefined) : undefined, + border: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? presBoxColor + ' solid 2.5px' : undefined) : undefined, }}> <div className="presItem-name" diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index cbcfed06f..096b2561f 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -28,12 +28,12 @@ import { ReportManager } from '../../util/ReportManager'; @observer export class TopBar extends React.Component { navigateToHome = () => { - CollectionDockingView.Instance?.CaptureThumbnail()?.then(() => { + (CollectionDockingView.Instance?.CaptureThumbnail() ?? new Promise<void>(res => res())).then(() => { Doc.ActivePage = 'home'; DashboardView.closeActiveDashboard(); // bcz: if we do this, we need some other way to keep track, for user convenience, of the last dashboard in use }); }; - + render() { const activeDashboard = Doc.ActiveDashboard; return ( |