aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts2
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/util/CurrentUserUtils.ts20
-rw-r--r--src/client/views/DocComponent.tsx18
-rw-r--r--src/client/views/DocumentDecorations.scss6
-rw-r--r--src/client/views/DocumentDecorations.tsx27
-rw-r--r--src/client/views/MainView.tsx6
-rw-r--r--src/client/views/OverlayView.tsx2
-rw-r--r--src/client/views/Palette.tsx2
-rw-r--r--src/client/views/PropertiesView.tsx2
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx7
-rw-r--r--src/client/views/collections/CollectionTreeView.scss9
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx252
-rw-r--r--src/client/views/collections/CollectionView.tsx12
-rw-r--r--src/client/views/collections/TabDocView.tsx3
-rw-r--r--src/client/views/collections/TreeView.scss7
-rw-r--r--src/client/views/collections/TreeView.tsx49
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx10
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx4
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx4
-rw-r--r--src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx2
-rw-r--r--src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx2
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx2
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTable.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx10
-rw-r--r--src/client/views/nodes/FieldView.tsx2
-rw-r--r--src/client/views/nodes/FilterBox.tsx2
-rw-r--r--src/client/views/nodes/LinkBox.tsx2
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx2
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx2
-rw-r--r--src/client/views/nodes/VideoBox.scss10
-rw-r--r--src/client/views/nodes/VideoBox.tsx11
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx18
-rw-r--r--src/mobile/AudioUpload.tsx2
-rw-r--r--src/mobile/MobileInterface.tsx2
36 files changed, 298 insertions, 221 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index bfb29fe8d..ca1432de2 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -448,7 +448,7 @@ export function returnEmptyDoclist() { return [] as any[]; }
export let emptyPath = [];
-export function emptyFunction() { }
+export function emptyFunction() { return undefined; }
export function unimplementedFunction() { throw new Error("This function is not implemented, but should be."); }
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index da5c8efa9..219f51a3a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -94,6 +94,7 @@ type DROPt = DAInfo | dropActionType;
export class DocumentOptions {
system?: BOOLt = new BoolInfo("is this a system created/owned doc");
_dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else");
+ allowOverlayDrop?: BOOLt = new BoolInfo("can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?");
childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection ");
targetDropAction?: DROPt = new DAInfo("what should happen to the source document when ??? ");
color?: string; // foreground color data doc
@@ -289,6 +290,7 @@ export class DocumentOptions {
treeViewExpandedViewLock?: boolean; // whether the expanded view can be changed
treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked
treeViewTruncateTitleWidth?: number;
+ treeViewHasOverlay?: boolean; // whether the treeview has an overlay for freeform annotations
treeViewType?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy
sidebarColor?: string; // background color of text sidebar
sidebarViewType?: string; // collection type of text sidebar
@@ -821,7 +823,7 @@ export namespace Docs {
}
export function TreeDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
- return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Tree }, id, undefined, protoId);
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xMargin: 5, _yMargin: 5, ...options, _viewType: CollectionViewType.Tree }, id, undefined, protoId);
}
export function StackingDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 9d06ad8a3..c9bef5924 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -339,7 +339,7 @@ export class CurrentUserUtils {
const clickTemplates = CurrentUserUtils.setupClickEditorTemplates(doc);
if (doc.templateDocs === undefined) {
doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([noteTemplates, userTemplateBtns, clickTemplates], {
- title: "template layouts", _xPadding: 0, system: true,
+ title: "template layouts", _xMargin: 0, system: true,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name })
}));
}
@@ -421,7 +421,11 @@ export class CurrentUserUtils {
((doc.emptyPane as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptySlide === undefined) {
- const textDoc = Docs.Create.TreeDocument([], { title: "Slide", _viewType: CollectionViewType.Tree, _fontSize: "20px", _autoHeight: true, treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "transparent", system: true, cloneFieldFilter: new List<string>(["system"]) });
+ const textDoc = Docs.Create.TreeDocument([], {
+ title: "Slide", _viewType: CollectionViewType.Tree, treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true,
+ allowOverlayDrop: true, treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true,
+ backgroundColor: "transparent", system: true, cloneFieldFilter: new List<string>(["system"])
+ });
Doc.GetProto(textDoc).title = ComputedField.MakeFunction('self.text?.Text');
FormattedTextBox.SelectOnLoad = textDoc[Id];
doc.emptySlide = textDoc;
@@ -811,7 +815,7 @@ export class CurrentUserUtils {
const newDashboardButton: Doc = Docs.Create.FontIconDocument({ onClick: newDashboard, _forceActive: true, toolTip: "Create new dashboard", _stayInCollection: true, _hideContextMenu: true, title: "new dashboard", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true });
doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], {
title: "My Dashboards", _showTitle: "title", _height: 400, childHideLinkButton: true, freezeChildren: "remove|add",
- treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
+ treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias",
treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newDashboardButton,
_lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true,
explainer: "This is your collection of dashboards. A dashboard represents the tab configuration of your workspace. To manage documents as folders, go to the Files."
@@ -840,7 +844,7 @@ export class CurrentUserUtils {
const newTrailButton: Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "Create new trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true });
doc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], {
title: "My Trails", _showTitle: "title", _height: 100,
- treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias",
+ treeViewHideTitle: true, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias",
treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newTrailButton,
_lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true,
explainer: "All of the trails that you have created will appear here."
@@ -865,7 +869,7 @@ export class CurrentUserUtils {
});
doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileOrphans as Doc], {
title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100,
- treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
+ treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true,
_lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true,
@@ -884,7 +888,7 @@ export class CurrentUserUtils {
const clearDocsButton: Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true });
doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], {
title: "My Recently Closed", _showTitle: "title", buttonMenu: true, buttonMenuDoc: clearDocsButton, childHideLinkButton: true,
- treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
+ treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
_lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true,
explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list."
@@ -902,7 +906,7 @@ export class CurrentUserUtils {
if (doc.currentFilter === undefined) {
doc.currentFilter = Docs.Create.FilterDocument({
title: "Unnamed Filter", _height: 150,
- treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "none",
+ treeViewHideTitle: true, _xPadding: 5, _yPadding: 5, _gridGap: 5, _forceActive: true, childDropAction: "none",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
_lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, _autoHeight: true, _fitWidth: true
});
@@ -918,7 +922,7 @@ export class CurrentUserUtils {
doc.treeViewOpen = true;
doc.treeViewExpandedView = "fields";
doc.myUserDoc = new PrefetchProxy(Docs.Create.TreeDocument([doc], {
- treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, title: "My UserDoc", _showTitle: "title",
+ treeViewHideTitle: true, _gridGap: 5, _forceActive: true, title: "My UserDoc", _showTitle: "title",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
_lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
})) as any as Doc;
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 32c351bf5..b9772fd57 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -44,7 +44,7 @@ interface ViewBoxBaseProps {
fieldKey: string;
layerProvider?: (doc: Doc, assign?: boolean) => boolean;
isSelected: (outsideReaction?: boolean) => boolean;
- isContentActive: () => boolean;
+ isContentActive: () => boolean | undefined;
renderDepth: number;
rootSelected: (outsideReaction?: boolean) => boolean;
}
@@ -65,10 +65,12 @@ export function ViewBoxBaseComponent<P extends ViewBoxBaseProps, T>(schemaCtor:
lookupField = (field: string) => ScriptCast(this.layoutDoc.lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field, container: this.props.ContainingCollectionDoc }).result;
- isContentActive = (outsideReaction?: boolean) => (CurrentUserUtils.SelectedTool !== InkTool.None ||
- (this.props.isContentActive?.() || this.props.Document.forceActive ||
- this.props.isSelected(outsideReaction) ||
- this.props.rootSelected(outsideReaction)) ? true : false)
+ isContentActive = (outsideReaction?: boolean) => (
+ this.props.isContentActive?.() === false ? false :
+ (CurrentUserUtils.SelectedTool !== InkTool.None ||
+ (this.props.isContentActive?.() || this.props.Document.forceActive ||
+ this.props.isSelected(outsideReaction) ||
+ this.props.rootSelected(outsideReaction)) ? true : undefined))
protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
}
return Component;
@@ -82,7 +84,7 @@ export interface ViewBoxAnnotatableProps {
fieldKey: string;
filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
layerProvider?: (doc: Doc, assign?: boolean) => boolean;
- isContentActive: () => boolean;
+ isContentActive: () => boolean | undefined;
select: (isCtrlPressed: boolean) => void;
whenChildContentsActiveChanged: (isActive: boolean) => void;
isSelected: (outsideReaction?: boolean) => boolean;
@@ -165,13 +167,13 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
// otherwise, the document being moved must be able to be removed from its container before
// moving it into the target.
@action.bound
- moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean, annotationKey?: string): boolean => {
+ moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string): boolean => {
if (Doc.AreProtosEqual(this.props.Document, targetCollection)) {
return true;
}
const first = doc instanceof Doc ? doc : doc[0];
if (!first?._stayInCollection && addDocument !== returnFalse) {
- return UndoManager.RunInTempBatch(() => this.removeDocument(doc, annotationKey, true) && addDocument(doc));
+ return UndoManager.RunInTempBatch(() => this.removeDocument(doc, annotationKey, true) && addDocument(doc, annotationKey));
}
return false;
}
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index d8ad47ecb..82dca1287 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -240,8 +240,10 @@ $linkGap: 3px;
text-align: center;
display: flex;
margin-left: 5px;
- height: 22px;
+ height: 20px;
position: absolute;
+ border-radius: 8px;
+ background: rgba(159,159,159,0.1);
.documentDecorations-titleSpan,
.documentDecorations-titleSpan-Dark {
@@ -288,7 +290,7 @@ $linkGap: 3px;
text-align: center;
display: flex;
margin-left: 5px;
- height: 22px;
+ height: 20px;
position: absolute;
.documentDecorations-titleSpan {
width: 100%;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 522995479..1c0b1b995 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -454,17 +454,18 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
</Tooltip>);
const colorScheme = StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme);
- const titleArea = this._edtingTitle ?
- <input ref={this._keyinput} className={`documentDecorations-title${colorScheme}`}
- style={{ width: `calc(100% - ${seldoc?.props.hideResizeHandles ? 0 : 20}px` }}
- type="text" name="dynbox" autoComplete="on"
- value={this._accumulatedTitle}
- onBlur={e => this.titleBlur()}
- onChange={action(e => this._accumulatedTitle = e.target.value)}
- onKeyPress={this.titleEntered} /> :
- <div className="documentDecorations-title" style={{ width: `calc(100% - ${seldoc?.props.hideResizeHandles ? 0 : 20}px` }} key="title" onPointerDown={this.onTitleDown} >
- <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${this.selectionTitle}`}</span>
- </div>;
+ const titleArea = hideTitle ? <div className="documentDecorations-title" onPointerDown={this.onTitleDown} style={{ width: "100%" }} key="title" /> :
+ this._edtingTitle ?
+ <input ref={this._keyinput} className={`documentDecorations-title${colorScheme}`}
+ style={{ width: `calc(100% - ${hideResizers ? 0 : 20}px` }}
+ type="text" name="dynbox" autoComplete="on"
+ value={this._accumulatedTitle}
+ onBlur={e => this.titleBlur()}
+ onChange={action(e => this._accumulatedTitle = e.target.value)}
+ onKeyPress={this.titleEntered} /> :
+ <div className="documentDecorations-title" style={{ width: `calc(100% - ${hideResizers ? 0 : 20}px` }} key="title" onPointerDown={this.onTitleDown} >
+ <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${this.selectionTitle}`}</span>
+ </div>;
let inMainMenuPanel = false;
for (let node = seldoc.ContentDiv; node && !inMainMenuPanel; node = node?.parentNode as any) {
@@ -498,8 +499,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
}}>
{!canDelete ? <div /> : topBtn("close", "times", undefined, this.onCloseClick, "Close")}
- {hideTitle ? (null) : titleArea}{!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")}
-
+ {titleArea}
+ {!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")}
{hideResizers ? (null) :
<>
{SelectionManager.Views().length !== 1 || hideTitle ? (null) :
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 9a885fbf8..546b0e360 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -511,7 +511,7 @@ export class MainView extends React.Component {
bringToFront={emptyFunction}
select={emptyFunction}
isAnyChildContentActive={returnFalse}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
isSelected={returnFalse}
docViewPath={returnEmptyDoclist}
moveDocument={this.moveButtonDoc}
@@ -592,7 +592,7 @@ export class MainView extends React.Component {
pinToPres={returnFalse}
ScreenToLocalTransform={Transform.Identity}
bringToFront={returnFalse}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
whenChildContentsActiveChanged={returnFalse}
focus={returnFalse}
docViewPath={returnEmptyDoclist}
@@ -669,7 +669,7 @@ export class MainView extends React.Component {
pinToPres={returnFalse}
ScreenToLocalTransform={Transform.Identity}
bringToFront={returnFalse}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
whenChildContentsActiveChanged={returnFalse}
focus={returnFalse}
PanelWidth={() => 500}
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index af04b967a..7cf388872 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -191,7 +191,7 @@ export class OverlayView extends React.Component {
ScreenToLocalTransform={Transform.Identity}
renderDepth={1}
isDocumentActive={returnTrue}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
whenChildContentsActiveChanged={emptyFunction}
focus={DocUtils.DefaultFocus}
styleProvider={DefaultStyleProvider}
diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx
index 86ab881bb..529697f71 100644
--- a/src/client/views/Palette.tsx
+++ b/src/client/views/Palette.tsx
@@ -50,7 +50,7 @@ export default class Palette extends React.Component<PaletteProps> {
PanelHeight={() => window.screen.height}
renderDepth={0}
isDocumentActive={returnTrue}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
focus={emptyFunction}
docViewPath={returnEmptyDoclist}
styleProvider={returnEmptyString}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index ab9022a84..1083e0075 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -295,7 +295,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
freezeDimensions={true}
dontCenter={"y"}
isDocumentActive={returnFalse}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined}
NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined}
PanelWidth={panelWidth}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 648ff5087..bffaf86b1 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -226,7 +226,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
layerProvider={this.props.layerProvider}
docViewPath={this.props.docViewPath}
fitWidth={this.props.childFitWidth}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
isDocumentActive={this.isContentActive}
LayoutTemplate={this.props.childLayoutTemplate}
LayoutTemplateString={this.props.childLayoutString}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 5dffc65fc..fc1bcb8b9 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -22,7 +22,6 @@ import ReactLoading from 'react-loading';
export interface SubCollectionViewProps extends CollectionViewProps {
CollectionView: Opt<CollectionView>;
- SetSubView?: (subView: any) => void;
isAnyChildContentActive: () => boolean;
}
@@ -49,10 +48,6 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
this.createDashEventsTarget(ele);
}
- componentDidMount() {
- this.props.SetSubView?.(this);
- }
-
componentWillUnmount() {
this.gestureDisposer?.();
this._multiTouchDisposer?.();
@@ -220,7 +215,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
if (movedDocs.length) {
- const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || !this.props.isAnnotationOverlay ||
+ const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || (!this.props.isAnnotationOverlay || this.props.Document.allowOverlayDrop) ||
Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse);
} else {
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index d370d21ab..b664d9d82 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -71,6 +71,15 @@
display: none;
}
+.collectionTreeView-titleBar {
+ display: inline-block;
+ width: 100%;
+ height: max-content;
+ .contentFittingDocumentView {
+ display: block; // makes titleBar take up full width of the treeView (flex doesn't for some reason)
+ }
+}
+
.collectionTreeView-keyHeader:hover {
background: #797777;
cursor: pointer;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 3852987b9..6fb18d4c2 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,4 +1,3 @@
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
import { observer } from "mobx-react";
import { DataSym, Doc, DocListCast, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
@@ -8,13 +7,14 @@ import { Document, listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, emptyFunction } from '../../../Utils';
+import { emptyFunction, OmitKeys, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils';
import { DocUtils } from '../../documents/Documents';
import { CurrentUserUtils } from '../../util/CurrentUserUtils';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager, dropActionType } from "../../util/DragManager";
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
+import { Transform } from '../../util/Transform';
import { undoBatch, UndoManager } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
@@ -22,11 +22,11 @@ import { EditableView } from "../EditableView";
import { DocumentView } from '../nodes/DocumentView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { StyleProp } from '../StyleProvider';
+import { CollectionFreeFormView } from './collectionFreeForm';
import { CollectionSubView } from "./CollectionSubView";
import "./CollectionTreeView.scss";
import { TreeView } from "./TreeView";
import React = require("react");
-import { Transform } from '../../util/Transform';
const _global = (window /* browser */ || global /* node */) as any;
export type collectionTreeViewProps = {
@@ -41,10 +41,13 @@ export type collectionTreeViewProps = {
@observer
export class CollectionTreeView extends CollectionSubView<Document, Partial<collectionTreeViewProps>>(Document) {
- private treedropDisposer?: DragManager.DragDropDisposer;
+ private _treedropDisposer?: DragManager.DragDropDisposer;
private _mainEle?: HTMLDivElement;
+ private _titleRef?: HTMLDivElement | HTMLInputElement | null;
private _disposers: { [name: string]: IReactionDisposer } = {};
- MainEle = () => this._mainEle;
+ private _isDisposing = false; // notes that instance is in process of being disposed
+ private refList: Set<any> = new Set(); // list of tree view items to monitor for height changes
+ private observer: any; // observer for mnonitoring tree view items.
@computed get doc() { return this.props.Document; }
@computed get dataDoc() { return this.props.DataDoc || this.doc; }
@@ -54,6 +57,10 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
@computed get fileSysMode() { return this.doc.treeViewType === "fileSystem"; }
@computed get dashboardMode() { return this.doc === Doc.UserDoc().myDashboards; }
+ @observable _explainerHeight = 0; // height of the description of the tree view
+
+ MainEle = () => this._mainEle;
+
// these should stay in synch with counterparts in DocComponent.ts ViewBoxAnnotatableComponent
@observable _isAnyChildContentActive = false;
whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged(this._isAnyChildContentActive = isActive));
@@ -62,11 +69,10 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
this.props.isSelected(outsideReaction) || this._isAnyChildContentActive ||
this.props.rootSelected(outsideReaction)) ? true : false)
- isDisposing = false;
componentWillUnmount() {
- this.isDisposing = true;
+ this._isDisposing = true;
super.componentWillUnmount();
- this.treedropDisposer?.();
+ this._treedropDisposer?.();
Object.values(this._disposers).forEach(disposer => disposer?.());
}
@@ -76,13 +82,13 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
{ fireImmediately: true });
}
- refList: Set<any> = new Set();
- observer: any;
computeHeight = () => {
- if (this.isDisposing) return;
- const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), this.paddingTop() + this.paddingBot());
- this.layoutDoc._autoHeightMargins = bodyHeight;
- this.props.setHeight(this.documentTitleHeight() + bodyHeight);
+ if (!this._isDisposing) {
+ const titleHeight = !this._titleRef ? this.marginTop() : Number(getComputedStyle(this._titleRef).height.replace("px", ""));
+ const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), this.marginBot());
+ this.layoutDoc._autoHeightMargins = bodyHeight;
+ this.props.setHeight(bodyHeight + titleHeight);
+ }
}
unobserveHeight = (ref: any) => {
this.refList.delete(ref);
@@ -101,8 +107,8 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
}
}
protected createTreeDropTarget = (ele: HTMLDivElement) => {
- this.treedropDisposer?.();
- if (this._mainEle = ele) this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.doc, this.onInternalPreDrop.bind(this));
+ this._treedropDisposer?.();
+ if (this._mainEle = ele) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.doc, this.onInternalPreDrop.bind(this));
}
protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => {
@@ -165,60 +171,54 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
this.addDoc(TreeView.makeTextBullet(), childDocs.length ? childDocs[0] : undefined, true);
}
- editableTitle = (childDocs: Doc[]) => {
- return !this.dataDoc ? (null) :
- <EditableView
- contents={this.dataDoc.title}
- display={"block"}
- maxHeight={72}
- height={"auto"}
- GetValue={() => StrCast(this.dataDoc.title)}
- SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
- if (enter && this.props.Document.treeViewType === "outline") this.makeTextCollection(childDocs);
- this.dataDoc.title = value;
- return true;
- })} />;
+ get editableTitle() {
+ return <EditableView
+ contents={this.dataDoc.title}
+ display={"block"}
+ maxHeight={72}
+ height={"auto"}
+ GetValue={() => StrCast(this.dataDoc.title)}
+ SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
+ if (enter && this.props.Document.treeViewType === "outline") this.makeTextCollection(this.treeChildren);
+ this.dataDoc.title = value;
+ return true;
+ })} />;
}
- documentTitle = (childDocs: Doc[]) => {
- return <div style={{ display: "inline-block", width: "100%", height: this.documentTitleHeight() }} key={this.doc[Id]}
- onKeyDown={e => {
- e.stopPropagation();
- e.key === "Enter" && this.makeTextCollection(childDocs);
- }}>
- <DocumentView
- Document={this.doc}
- DataDoc={undefined}
- LayoutTemplateString={FormattedTextBox.LayoutString("text")}
- renderDepth={this.props.renderDepth + 1}
- isContentActive={this.isContentActive}
- isDocumentActive={this.isContentActive}
- rootSelected={returnTrue}
- docViewPath={this.props.docViewPath}
- styleProvider={this.props.styleProvider}
- layerProvider={this.props.layerProvider}
- PanelWidth={this.documentTitleWidth}
- PanelHeight={this.documentTitleHeight}
- NativeWidth={this.documentTitleWidth}
- NativeHeight={this.documentTitleHeight}
- focus={this.props.focus}
- treeViewDoc={this.props.Document}
- ScreenToLocalTransform={this.titleTransform}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- ContainingCollectionDoc={this.doc}
- ContainingCollectionView={this.props.CollectionView}
- addDocument={this.props.addDocument}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- bringToFront={returnFalse}
- />
- </div>;
+ get documentTitle() {
+ return <DocumentView
+ Document={this.doc}
+ DataDoc={undefined}
+ LayoutTemplateString={FormattedTextBox.LayoutString("text")}
+ renderDepth={this.props.renderDepth + 1}
+ isContentActive={this.isContentActive}
+ isDocumentActive={this.isContentActive}
+ rootSelected={returnTrue}
+ forceAutoHeight={true} // needed to make the title resize even if the rest of the tree view is not autoHeight
+ docViewPath={this.props.docViewPath}
+ styleProvider={this.props.styleProvider}
+ layerProvider={this.props.layerProvider}
+ PanelWidth={this.documentTitleWidth}
+ PanelHeight={this.documentTitleHeight}
+ NativeWidth={this.documentTitleWidth}
+ NativeHeight={this.documentTitleHeight}
+ focus={this.props.focus}
+ treeViewDoc={this.props.Document}
+ ScreenToLocalTransform={this.titleTransform}
+ docFilters={returnEmptyFilter}
+ docRangeFilters={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ ContainingCollectionDoc={this.doc}
+ ContainingCollectionView={this.props.CollectionView}
+ addDocument={this.props.addDocument}
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
+ addDocTab={this.props.addDocTab}
+ pinToPres={this.props.pinToPres}
+ bringToFront={returnFalse}
+ />;
}
childContextMenuItems = () => {
const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []);
@@ -263,21 +263,31 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
);
}
@computed get titleBar() {
- const hideTitle = this.props.treeViewHideTitle || this.doc.treeViewHideTitle;
- return hideTitle ? (null) : (this.outlineMode ? this.documentTitle : this.editableTitle)(this.treeChildren);
+ return this.dataDoc === null ? (null) :
+ <div className="collectionTreeView-titleBar" key={this.doc[Id]}
+ style={!this.outlineMode ? { paddingLeft: this.marginX(), paddingRight: this.marginX(), paddingTop: this.marginTop() } : {}}
+ ref={r => this._titleRef = r}
+ onKeyDown={e => {
+ if (this.outlineMode) {
+ e.stopPropagation();
+ e.key === "Enter" && this.makeTextCollection(this.treeChildren);
+ }
+ }}>
+ {this.outlineMode ? this.documentTitle : this.editableTitle}
+ </div>;
+ }
+
+ @computed get noviceExplainer() {
+ return !Doc.UserDoc().noviceMode || !this.rootDoc.explainer ? (null) :
+ <div className="documentExplanation"> {this.rootDoc.explainer} </div>;
}
return35 = () => 35;
@computed get buttonMenu() {
- const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
+ const menuDoc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
// To create a multibutton menu add a CollectionLinearView
- if (menuDoc) {
-
- const width: number = NumCast(menuDoc._width, 30);
- const height: number = NumCast(menuDoc._height, 30);
- console.log(menuDoc.title, width, height);
- return (<div className="buttonMenu-docBtn"
- style={{ width: width, height: height }}>
+ return !menuDoc ? null :
+ (<div className="buttonMenu-docBtn" style={{ width: NumCast(menuDoc._width, 30), height: NumCast(menuDoc._height, 30) }}>
<DocumentView
Document={menuDoc}
DataDoc={menuDoc}
@@ -306,11 +316,8 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
ContainingCollectionDoc={undefined}
/>
</div>);
- }
}
- @observable _explainerHeight: number = 0;
-
@computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); }
@computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); }
@@ -321,47 +328,82 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
const wscale = nw ? this.props.PanelWidth() / nw : 1;
return wscale < hscale ? wscale : hscale;
}
- paddingX = () => NumCast(this.doc._xPadding, 15);
- paddingTop = () => NumCast(this.doc._yPadding, 20);
- paddingBot = () => NumCast(this.doc._yPadding, 20);
+ marginX = () => NumCast(this.doc._xMargin);
+ marginTop = () => NumCast(this.doc._yMargin);
+ marginBot = () => NumCast(this.doc._yMargin);
documentTitleWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.panelWidth());
documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins);
titleTransform = () => this.props.ScreenToLocalTransform().translate(-NumCast(this.doc._xPadding, 10), -NumCast(this.doc._yPadding, 20));
truncateTitleWidth = () => this.treeViewtruncateTitleWidth;
onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
- panelWidth = () => (this.props.PanelWidth() - 2 * this.paddingX()) * (this.props.scaling?.() || 1);
- render() {
- TraceMobx();
+ panelWidth = () => (this.props.PanelWidth() - 2 * this.marginX()) * (this.props.scaling?.() || 1);
+
+ addAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.addDocument(doc, `${this.props.fieldKey}-annotations`) || false;
+ remAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false;
+ moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) =>
+ this.props.CollectionView?.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}-annotations`) || false
+
+ contentFunc = () => {
const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
const pointerEvents = () => !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined;
- const buttonMenu = this.rootDoc.buttonMenu;
- const noviceExplainer = this.rootDoc.explainer;
-
- return !(this.doc instanceof Doc) || !this.treeChildren ? (null) :
- <>
- {this.titleBar}
+ const titleBar = this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? (null) : this.titleBar;
+ return [
+ <div className="collectionTreeView-contents" key="tree" style={{
+ ...(!titleBar ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
+ overflow: "auto",
+ height: this.layoutDoc._autoHeight ? "max-content" : "100%"
+ }} >
+ {titleBar}
<div className="collectionTreeView-container"
- style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
+ style={{
+ transform: this.outlineMode ? `scale(${this.contentScaling})` : "",
+ paddingLeft: `${this.marginX()}px`,
+ height: "max-content",
+ width: this.outlineMode ? `calc(${100 / this.contentScaling}%)` : ""
+ }}
onContextMenu={this.onContextMenu}>
- {buttonMenu || noviceExplainer ? <div className="documentButtonMenu" ref={action((r: HTMLDivElement) => r && (this._explainerHeight = r.getBoundingClientRect().height))}>
- {buttonMenu ? this.buttonMenu : null}
- {Doc.UserDoc().noviceMode && noviceExplainer ?
- <div className="documentExplanation">
- {noviceExplainer}
- </div>
- : null
- }
- </div> : null}
+ {!this.buttonMenu && !this.noviceExplainer ? (null) :
+ <div className="documentButtonMenu" ref={action((r: HTMLDivElement) => r && (this._explainerHeight = r.getBoundingClientRect().height))}>
+ {this.buttonMenu}
+ {this.noviceExplainer}
+ </div>
+ }
<div className="collectionTreeView-dropTarget"
- style={{ background: background(), height: `calc(100% - ${this._explainerHeight}px)`, paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
+ style={{
+ background: background(),
+ height: `calc(100% - ${this._explainerHeight}px)`,
+ pointerEvents: pointerEvents()
+ }}
onWheel={e => e.stopPropagation()}
onDrop={this.onTreeDrop}
- ref={this.createTreeDropTarget}>
+ ref={r => !this.doc.treeViewHasOverlay && r && this.createTreeDropTarget(r)}>
<ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
{this.treeViewElements}
</ul>
</div >
</div>
- </>;
+ </div>
+ ];
+ }
+ render() {
+ TraceMobx();
+
+ return !(this.doc instanceof Doc) || !this.treeChildren ? (null) :
+ this.doc.treeViewHasOverlay ?
+ <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
+ isAnnotationOverlay={true}
+ isAnnotationOverlayScrollable={true}
+ childDocumentsActive={this.props.isDocumentActive}
+ fieldKey={this.props.fieldKey + "-annotations"}
+ dropAction={"move"}
+ select={emptyFunction}
+ addDocument={this.addAnnotationDocument}
+ removeDocument={this.remAnnotationDocument}
+ moveDocument={this.moveAnnotationDocument}
+ bringToFront={emptyFunction}
+ renderDepth={this.props.renderDepth + 1} >
+ {this.contentFunc}
+ </CollectionFreeFormView> :
+ this.contentFunc();
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 38e027fb3..8e84b59de 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -63,6 +63,7 @@ export enum CollectionViewType {
}
export interface CollectionViewProps extends FieldViewProps {
isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc)
+ isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently)
layoutEngine?: () => string;
setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void;
@@ -125,8 +126,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
}
screenToLocalTransform = () => this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth());
- private SubView = (type: CollectionViewType, props: SubCollectionViewProps) => {
+ private renderSubView = (type: CollectionViewType | undefined, props: SubCollectionViewProps) => {
TraceMobx();
+ if (type === undefined) return null;
switch (type) {
default:
case CollectionViewType.Freeform: return <CollectionFreeFormView key="collview" {...props} />;
@@ -246,17 +248,13 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.rootDoc.childLayoutTemplate, Doc, null);
@computed get childLayoutString() { return StrCast(this.rootDoc.childLayoutString); }
-
- @observable _subView: any = undefined;
-
isContentActive = (outsideReaction?: boolean) => {
- return this.props.isContentActive() ? true : false;
+ return this.props.isContentActive();
}
render() {
TraceMobx();
const props: SubCollectionViewProps = {
...this.props,
- SetSubView: action((subView: any) => this._subView = subView),
addDocument: this.addDocument,
moveDocument: this.moveDocument,
removeDocument: this.removeDocument,
@@ -273,7 +271,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
return (<div className={"collectionView"} onContextMenu={this.onContextMenu}
style={{ pointerEvents: this.props.layerProvider?.(this.rootDoc) === false ? "none" : undefined }}>
{this.showIsTagged()}
- {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)}
+ {this.renderSubView(this.collectionViewType, props)}
</div>);
}
}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index eb95bb913..5ba019698 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -476,7 +476,6 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
<div className="miniMap" style={{ width: miniSize, height: miniSize, background: this.props.background() }}>
<CollectionFreeFormView
Document={this.props.document}
- SetSubView={() => this}
CollectionView={undefined}
ContainingCollectionView={undefined}
ContainingCollectionDoc={undefined}
@@ -484,7 +483,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
childLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid having to set stuff like this.
noOverlay={true} // don't render overlay Docs since they won't scale
setHeight={returnFalse}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
isAnyChildContentActive={returnFalse}
select={emptyFunction}
dropAction={undefined}
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 1ebc5873e..2e33d3564 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -53,14 +53,11 @@
}
}
+.treeView-container-outline-active
.treeView-container-active {
z-index: 100;
position: relative;
-
- .formattedTextbox-sidebar {
- background-color: #ffff001f !important;
- height: 500px !important;
- }
+ pointer-events: all;
}
.treeView-openRight {
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 7f2128230..a266c301f 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -81,7 +81,7 @@ export class TreeView extends React.Component<TreeViewProps> {
static _openLevelScript: Opt<ScriptField | undefined>;
private _header: React.RefObject<HTMLDivElement> = React.createRef();
private _tref = React.createRef<HTMLDivElement>();
- private _docRef: Opt<DocumentView>;
+ @observable _docRef: Opt<DocumentView>;
private _selDisposer: Opt<IReactionDisposer>;
private _editTitleScript: (() => ScriptField) | undefined;
private _openScript: (() => ScriptField) | undefined;
@@ -116,7 +116,8 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get childLinks() { return this.childDocList("links"); }
@computed get childAliases() { return this.childDocList("aliases"); }
@computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); }
- @computed get selected() { return SelectionManager.Views().lastElement()?.props.Document === this.props.document; }
+ @computed get selected() { return SelectionManager.IsSelected(this._docRef); }
+ // SelectionManager.Views().lastElement()?.props.Document === this.props.document; }
childDocList(field: string) {
const layout = Cast(Doc.LayoutField(this.doc), Doc, null);
@@ -125,7 +126,12 @@ export class TreeView extends React.Component<TreeViewProps> {
DocListCastOrNull(this.doc[field]); // otherwise use the document's data field
}
@undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
- return this.doc !== target && this.props.removeDoc?.(doc) === true && addDoc(doc);
+ if (this.doc !== target && addDoc !== returnFalse) { // bcz: this should all be running in a Temp undo batch instead of hackily testing for returnFalse
+ if (this.props.removeDoc?.(doc) === true) {
+ return addDoc(doc);
+ }
+ }
+ return false;
}
@undoBatch @action remove = (doc: Doc | Doc[], key: string) => {
this.props.treeView.props.select(false);
@@ -141,8 +147,10 @@ export class TreeView extends React.Component<TreeViewProps> {
this._editTitle = false;
}
else if (docView.isSelected()) {
+ const doc = docView.Document;
+ SelectionManager.SelectSchemaViewDoc(doc);
this._editTitle = true;
- this._selDisposer = reaction(() => docView.isSelected(), sel => !sel && this.setEditTitle(undefined));
+ this._selDisposer = reaction(() => SelectionManager.SelectedSchemaDoc(), seldoc => seldoc !== doc && this.setEditTitle(undefined));
} else {
docView.select(false);
}
@@ -222,7 +230,7 @@ export class TreeView extends React.Component<TreeViewProps> {
public static makeTextBullet() {
const bullet = Docs.Create.TextDocument("-text-", {
layout: CollectionView.LayoutString("data"),
- title: "-title-", "sidebarColor": "transparent", "sidebarViewType": CollectionViewType.Freeform,
+ title: "-title-",
treeViewExpandedViewLock: true, treeViewExpandedView: "data",
_viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewType: "outline",
x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, backgroundColor: "transparent", _width: 1000, _height: 10
@@ -266,23 +274,25 @@ export class TreeView extends React.Component<TreeViewProps> {
e.stopPropagation();
}
const docDragData = de.complete.docDragData;
- if (docDragData) {
- e.stopPropagation();
+ if (docDragData && pt[0] < rect.left + rect.width) {
if (docDragData.draggedDocuments[0] === this.doc) return true;
- this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document);
+ if (this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document)) {
+ e.stopPropagation();
+ }
}
}
dropDocuments(droppedDocuments: Doc[], before: boolean, inside: number | boolean, dropAction: dropActionType, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean) {
const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before);
- const canAdd = !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes("add") || forceAdd;
+ const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes("add")) || forceAdd;
const localAdd = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) && ((doc.context = this.doc.context) || true) ? true : false;
const addDoc = !inside ? parentAddDoc :
(doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean);
const move = (!dropAction || dropAction === "proto" || dropAction === "move" || dropAction === "same") && moveDocument;
if (canAdd) {
- UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === "proto" ? addDoc(d) : false) : addDoc(d)) || added, false));
+ return UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === "proto" ? addDoc(d) : false) : addDoc(d)) || added, false));
}
+ return false;
}
refTransform = (ref: HTMLDivElement | undefined | null) => {
@@ -432,7 +442,7 @@ export class TreeView extends React.Component<TreeViewProps> {
</div>
</ul>;
}
- return <ul>{this.renderEmbeddedDocument(false)}</ul>; // "layout"
+ return <ul onPointerDown={e => { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, returnFalse)}</ul>; // "layout"
}
get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); }
@@ -581,6 +591,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}
titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth()));
+ return18 = () => 18;
/**
* Renders the EditableView title element for placement into the tree.
*/
@@ -636,10 +647,10 @@ export class TreeView extends React.Component<TreeViewProps> {
moveDocument={this.move}
removeDocument={this.props.removeDoc}
ScreenToLocalTransform={this.getTransform}
- NativeHeight={() => 18}
+ NativeHeight={this.return18}
NativeWidth={this.titleWidth}
PanelWidth={this.titleWidth}
- PanelHeight={() => 18}
+ PanelHeight={this.return18}
contextMenuItems={this.contextMenuItems}
renderDepth={1}
isContentActive={this.props.isContentActive}
@@ -679,6 +690,7 @@ export class TreeView extends React.Component<TreeViewProps> {
renderBulletHeader = (contents: JSX.Element, editing: boolean) => {
return <>
<div className={`treeView-header` + (editing ? "-editing" : "")} key="titleheader"
+ style={{ width: "max-content" }}
ref={this._header}
onClick={this.ignoreEvent}
onPointerDown={this.ignoreEvent}
@@ -691,7 +703,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}
- renderEmbeddedDocument = (asText: boolean) => {
+ renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => {
const layout = StrCast(Doc.LayoutField(this.layoutDoc));
const isExpandable = layout.includes(FormattedTextBox.name) || layout.includes(SliderBox.name);
const panelWidth = asText || isExpandable ? this.rtfWidth : this.expandPanelWidth;
@@ -704,8 +716,8 @@ export class TreeView extends React.Component<TreeViewProps> {
NativeWidth={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfWidth : undefined}
NativeHeight={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfHeight : undefined}
LayoutTemplateString={asText ? FormattedTextBox.LayoutString("text") : undefined}
- isContentActive={asText ? this.props.isContentActive : returnFalse}
- isDocumentActive={asText ? this.props.isContentActive : returnFalse}
+ isContentActive={isActive}
+ isDocumentActive={isActive}
styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
hideTitle={asText}
fitContentsToDoc={returnTrue}
@@ -749,7 +761,7 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get renderDocumentAsHeader() {
return <>
{this.renderBullet}
- {this.renderEmbeddedDocument(true)}
+ {this.renderEmbeddedDocument(true, this.props.isContentActive)}
</>;
}
@@ -776,13 +788,12 @@ export class TreeView extends React.Component<TreeViewProps> {
return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? "<" + this.doc.title + ">" : // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
<div className={`treeView-container${this.props.isContentActive() ? "-active" : ""}`}
ref={this.createTreeDropTarget}
-
onDrop={this.onTreeDrop}
//onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
onKeyDown={this.onKeyDown}>
<li className="collection-child">
{hideTitle && this.doc.type !== DocumentType.RTF ?
- this.renderEmbeddedDocument(false) :
+ this.renderEmbeddedDocument(false, returnFalse) :
this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader : this.renderTitleAsHeader, this._editTitle)}
</li>
</div>;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 37caf508f..190d0e76a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -165,7 +165,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document._panX);
panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document._panY);
zoomScaling = () => (this.freeformData()?.scale ?? NumCast(this.Document[this.scaleFieldKey], 1));
- contentTransform = () => `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`;
+ contentTransform = () => !this.cachedCenteringShiftX && !this.cachedCenteringShiftY && this.zoomScaling() === 1 ? "" : `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`;
getTransform = () => this.cachedGetTransform.copy();
getLocalTransform = () => this.cachedGetLocalTransform.copy();
getContainerTransform = () => this.cachedGetContainerTransform.copy();
@@ -802,7 +802,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
else if (this.props.isContentActive(true) && !this.Document._isGroup) {
e.stopPropagation();
e.preventDefault();
- this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
+ !this.props.isAnnotationOverlayScrollable && this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
}
}
@@ -1015,7 +1015,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
docFilters={this.childDocFilters}
docRangeFilters={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
isDocumentActive={this.props.childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
focus={this.focusDocument}
addDocTab={this.addDocTab}
@@ -1034,7 +1034,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
bringToFront={this.bringToFront}
showTitle={this.props.childShowTitle}
dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView}
- pointerEvents={this.backgroundActive || this.props.childPointerEvents ? "all" :
+ pointerEvents={this.props.isContentActive() === false ? "none" : this.backgroundActive || this.props.childPointerEvents ? "all" :
(this.props.viewDefDivClick || (engine === "pass" && !this.props.isSelected(true))) ? "none" : this.props.pointerEvents}
jitterRotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
//fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
@@ -1474,6 +1474,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
{this.layoutDoc._backgroundGridShow ? this.backgroundGrid : (null)}
<CollectionFreeFormViewPannableContents
isAnnotationOverlay={this.isAnnotationOverlay}
+ isAnnotationOverlayScrollable={this.props.isAnnotationOverlayScrollable}
transform={this.contentTransform}
zoomScaling={this.zoomScaling}
presPaths={BoolCast(this.Document.presPathView)}
@@ -1582,6 +1583,7 @@ interface CollectionFreeFormViewPannableContentsProps {
progressivize?: boolean;
presPinView?: boolean;
isAnnotationOverlay: boolean | undefined;
+ isAnnotationOverlayScrollable: boolean | undefined;
}
@observer
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 65c345547..ec1cbadd5 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -6,7 +6,7 @@ import { documentSchema } from '../../../../fields/documentSchemas';
import { List } from '../../../../fields/List';
import { makeInterface } from '../../../../fields/Schema';
import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { returnFalse, emptyPath, returnEmptyDoclist } from '../../../../Utils';
+import { returnFalse, emptyPath, returnEmptyDoclist, emptyFunction } from '../../../../Utils';
import { DragManager, dropActionType } from '../../../util/DragManager';
import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
@@ -228,7 +228,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
LayoutTemplateString={this.props.childLayoutString}
freezeDimensions={this.props.childFreezeDimensions}
renderDepth={this.props.renderDepth + 1}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
PanelWidth={width}
PanelHeight={height}
rootSelected={this.rootSelected}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 30836854a..a2d51e2e7 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -6,7 +6,7 @@ import { documentSchema } from '../../../../fields/documentSchemas';
import { List } from '../../../../fields/List';
import { makeInterface } from '../../../../fields/Schema';
import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { returnFalse, emptyPath, returnEmptyDoclist } from '../../../../Utils';
+import { returnFalse, emptyPath, returnEmptyDoclist, emptyFunction } from '../../../../Utils';
import { DragManager, dropActionType } from '../../../util/DragManager';
import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
@@ -237,7 +237,7 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
ScreenToLocalTransform={dxf}
focus={this.props.focus}
docFilters={this.childDocFilters}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
docRangeFilters={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
ContainingCollectionDoc={this.props.CollectionView?.props.Document}
diff --git a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
index 9fe18d118..273e609ca 100644
--- a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
@@ -11,7 +11,7 @@ import { StyleProp } from "../../StyleProvider";
interface ResizerProps {
width: number;
styleProvider?: StyleProviderFunc;
- isContentActive?: () => boolean;
+ isContentActive?: () => boolean | undefined;
columnUnitLength(): number | undefined;
toLeft?: Doc;
toRight?: Doc;
diff --git a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
index 5478bf709..006ef4df6 100644
--- a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
@@ -11,7 +11,7 @@ import { StyleProviderFunc } from "../../nodes/DocumentView";
interface ResizerProps {
height: number;
styleProvider?: StyleProviderFunc;
- isContentActive?: () => boolean;
+ isContentActive?: () => boolean | undefined;
columnUnitLength(): number | undefined;
toTop?: Doc;
toBottom?: Doc;
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
index 1306b79cb..dc35b5749 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
@@ -225,7 +225,7 @@ export interface KeysDropdownProps {
fieldKey: string;
ContainingCollectionDoc: Doc | undefined;
ContainingCollectionView: Opt<CollectionView>;
- active?: (outsideReaction?: boolean) => boolean;
+ active?: (outsideReaction?: boolean) => boolean | undefined;
openHeader: (column: any, screenx: number, screeny: number) => void;
col: SchemaHeaderField;
icon: IconProp;
diff --git a/src/client/views/collections/collectionSchema/SchemaTable.tsx b/src/client/views/collections/collectionSchema/SchemaTable.tsx
index bc5a9559f..2219345f6 100644
--- a/src/client/views/collections/collectionSchema/SchemaTable.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTable.tsx
@@ -68,7 +68,7 @@ export interface SchemaTableProps {
addDocument?: (document: Doc | Doc[]) => boolean;
moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
ScreenToLocalTransform: () => Transform;
- active: (outsideReaction: boolean | undefined) => boolean;
+ active: (outsideReaction: boolean | undefined) => boolean | undefined;
onDrop: (e: React.DragEvent<Element>, options: DocumentOptions, completed?: (() => void) | undefined) => void;
addDocTab: (document: Doc, where: string) => boolean;
pinToPres: (document: Doc) => void;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6c058ff97..c8a32a911 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -138,6 +138,7 @@ export interface DocumentViewSharedProps {
hideLinkButton?: boolean;
hideCaptions?: boolean;
ignoreAutoHeight?: boolean;
+ forceAutoHeight?: boolean;
disableDocBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over.
pointerEvents?: string;
scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document
@@ -224,7 +225,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
componentWillUnmount() { this.cleanupHandlers(true); }
componentDidMount() { this.setupHandlers(); }
- componentDidUpdate() { this.setupHandlers(); }
+ //componentDidUpdate() { this.setupHandlers(); }
setupHandlers() {
this.cleanupHandlers(false);
if (this._mainCont.current) {
@@ -825,13 +826,14 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
setContentView = action((view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view);
isContentActive = (outsideReaction?: boolean) => {
- return CurrentUserUtils.SelectedTool !== InkTool.None ||
+ return this.props.isContentActive() === false ? false : (
+ CurrentUserUtils.SelectedTool !== InkTool.None ||
SnappingManager.GetIsDragging() ||
this.props.rootSelected() ||
this.props.Document.forceActive ||
this.props.isSelected(outsideReaction) ||
this._componentView?.isAnyChildContentActive?.() ||
- this.props.isContentActive() ? true : false;
+ this.props.isContentActive()) ? true : undefined;
}
@computed get contents() {
TraceMobx();
@@ -1256,7 +1258,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
position: this.props.Document.isInkMask ? "absolute" : undefined,
transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`,
width: isButton ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`,
- height: isButton ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` :
+ height: isButton || this.props.forceAutoHeight ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` :
`${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`),
}}>
<DocumentViewInternal {...this.props}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index ee81e106a..943b9f153 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -18,7 +18,7 @@ export interface FieldViewProps extends DocumentViewSharedProps {
scrollOverflow?: boolean; // bcz: would like to think this can be avoided -- need to look at further
select: (isCtrlPressed: boolean) => void;
- isContentActive: (outsideReaction?: boolean) => boolean;
+ isContentActive: (outsideReaction?: boolean) => boolean | undefined;
isDocumentActive?: () => boolean;
isSelected: (outsideReaction?: boolean) => boolean;
scaling?: () => number;
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 2041c7399..fb8e89da9 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -225,7 +225,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
treeViewExpandedView: "layout", _treeViewOpen: true, _forceActive: true, ignoreClick: true
});
Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
- newFacet._textBoxPadding = 4;
+ newFacet._textBoxPaddingX = newFacet._textBoxPaddingY = 4;
const scriptText = `setDocFilter(this?.target, "${facetHeader}", text, "match")`;
newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" });
} else if (facetHeader !== "tags" && nonNumbers / facetValues.strings.length < .1) {
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index b82d16677..879a63248 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -15,7 +15,7 @@ const LinkDocument = makeInterface(documentSchema);
@observer
export class LinkBox extends ViewBoxBaseComponent<FieldViewProps, LinkDocument>(LinkDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); }
- isContentActiveFunc = () => this.isContentActive() ? true : false;
+ isContentActiveFunc = () => this.isContentActive();
render() {
if (this.dataDoc.treeViewOpen === undefined) setTimeout(() => this.dataDoc.treeViewOpen = true);
return <div className={`linkBox-container${this.isContentActive() ? "-interactive" : ""}`}
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 424083dac..2e29c0656 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -166,7 +166,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
docViewPath={returnEmptyDoclist}
ScreenToLocalTransform={Transform.Identity}
isDocumentActive={returnFalse}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
addDocument={returnFalse}
removeDocument={returnFalse}
addDocTab={returnFalse}
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 7ad96bf05..0c631e5f9 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -313,7 +313,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
PanelHeight={this.formattedPanelHeight}
isAnnotationOverlay={true}
select={emptyFunction}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
scaling={returnOne}
xPadding={25}
yPadding={10}
diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss
index 4871599b8..f0d7bd2f3 100644
--- a/src/client/views/nodes/VideoBox.scss
+++ b/src/client/views/nodes/VideoBox.scss
@@ -48,10 +48,18 @@
width: 100%;
z-index: -1; // 0; // logically this should be 0 (or unset) which would give us transparent brush strokes over videos. However, this makes Chrome crawl to a halt
position: absolute;
+ video {
+ width: auto;
+ height: 100%;
+ display: flex;
+ margin: auto;
+ }
}
.videoBox-content, .videoBox-content-interactive, .videoBox-content-fullScreen {
- height: Auto;
+ width: 100%;
+ height: 100%;
+ left: 0px;
}
.videoBox-content-YouTube, .videoBox-content-YouTube-fullScreen {
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 440ccf638..615d595c0 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -307,12 +307,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
@computed get content() {
const field = Cast(this.dataDoc[this.fieldKey], VideoField);
const interactive = CurrentUserUtils.SelectedTool !== InkTool.None || !this.props.isSelected() ? "" : "-interactive";
- const style = "videoBox-content" + (this._fullScreen ? "-fullScreen" : "") + interactive;
+ const classname = "videoBox-content" + (this._fullScreen ? "-fullScreen" : "") + interactive;
return !field ? <div key="loading">Loading</div> :
- <div className="container" key="container" style={{ mixBlendMode: "multiply", pointerEvents: this.props.isContentActive() ? "all" : "none" }}>
- <div className={`${style}`} style={{ width: "100%", height: "100%", left: "0px" }}>
+ <div className="videoBox-contentContainer" key="container" style={{ mixBlendMode: "multiply" }}>
+ <div className={classname}>
<video key="video" autoPlay={this._screenCapture} ref={this.setVideoRef}
- style={{ height: "100%", width: "auto", display: "flex", margin: "auto" }}
onCanPlay={this.videoLoad}
controls={VideoBox._nativeControls}
onPlay={() => this.Play()}
@@ -457,11 +456,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
@computed get youtubeContent() {
this._youtubeIframeId = VideoBox._youtubeIframeCounter++;
this._youtubeContentCreated = this._forceCreateYouTubeIFrame ? true : true;
- const style = "videoBox-content-YouTube" + (this._fullScreen ? "-fullScreen" : "");
+ const classname = "videoBox-content-YouTube" + (this._fullScreen ? "-fullScreen" : "");
const start = untracked(() => Math.round((this.layoutDoc._currentTimecode || 0)));
return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId}-player`}
onPointerLeave={this.updateTimecode}
- onLoad={this.youtubeIframeLoaded} className={`${style}`} width={Doc.NativeWidth(this.layoutDoc) || 640} height={Doc.NativeHeight(this.layoutDoc) || 390}
+ onLoad={this.youtubeIframeLoaded} className={classname} width={Doc.NativeWidth(this.layoutDoc) || 640} height={Doc.NativeHeight(this.layoutDoc) || 390}
src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=0&mute=1&start=${start}&modestbranding=1&controls=${VideoBox._nativeControls ? 1 : 0}`} />;
}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index aa53f751d..1170528df 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -123,7 +123,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
@computed get sidebarWidthPercent() { return this._showSidebar ? "20%" : StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); }
@computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); }
- @computed get autoHeight() { return this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight; }
+ @computed get autoHeight() { return (this.props.forceAutoHeight || this.layoutDoc._autoHeight) && !this.props.ignoreAutoHeight; }
@computed get textHeight() { return NumCast(this.rootDoc[this.fieldKey + "-height"]); }
@computed get scrollHeight() { return NumCast(this.rootDoc[this.fieldKey + "-scrollHeight"]); }
@computed get sidebarHeight() { return !this.sidebarWidth() ? 0 : NumCast(this.rootDoc[this.SidebarKey + "-height"]); }
@@ -1565,7 +1565,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
setHeight={this.setSidebarHeight}
fitContentsToDoc={this.fitToBox}
noSidebar={true}
- fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : this.SidebarKey} />;
+ fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : `${this.fieldKey}-annotations`} />;
};
return <div className={"formattedTextBox-sidebar" + (CurrentUserUtils.SelectedTool !== InkTool.None ? "-inking" : "")}
style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
@@ -1581,10 +1581,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const interactive = (CurrentUserUtils.SelectedTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false);
if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(FormattedTextBoxComment.Hide);
const minimal = this.props.ignoreAutoHeight;
- const margins = NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0);
- const selPad = Math.min(margins, 10);
- const padding = Math.max(margins + ((selected && !this.layoutDoc._singleLine) || minimal ? -selPad : 0), 0);
- const selPaddingClass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : "";
+ const paddingX = NumCast(this.layoutDoc._xMargin, this.props.xPadding || 0);
+ const paddingY = NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0);
+ const selPad = ((selected && !this.layoutDoc._singleLine) || minimal ? Math.min(paddingY, Math.min(paddingX, 10)) : 0);
+ const selPaddingClass = selected && !this.layoutDoc._singleLine && paddingY >= 10 ? "-selected" : "";
const styleFromString = this.styleFromLayoutString(scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._headerHeight}px' >
return (styleFromString?.height === "0px" ? (null) :
<div className="formattedTextBox-cont"
@@ -1628,7 +1628,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
onScroll={this.onScroll} onDrop={this.ondrop} >
<div className={minimal ? "formattedTextBox-minimal" : `formattedTextBox-inner${rounded}${selPaddingClass}`} ref={this.createDropTarget}
style={{
- padding: StrCast(this.layoutDoc._textBoxPadding, `${padding}px`),
+ padding: StrCast(this.layoutDoc._textBoxPadding),
+ paddingLeft: StrCast(this.layoutDoc._textBoxPaddingX, `${paddingX - selPad}px`),
+ paddingRight: StrCast(this.layoutDoc._textBoxPaddingX, `${paddingX - selPad}px`),
+ paddingTop: StrCast(this.layoutDoc._textBoxPaddingY, `${paddingY - selPad}px`),
+ paddingBottom: StrCast(this.layoutDoc._textBoxPaddingY, `${paddingY - selPad}px`),
pointerEvents: !active && !SnappingManager.GetIsDragging() ? (this.layoutDoc.isLinkButton ? "none" : undefined) : undefined
}}
/>
diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx
index 71ddda866..88221732e 100644
--- a/src/mobile/AudioUpload.tsx
+++ b/src/mobile/AudioUpload.tsx
@@ -94,7 +94,7 @@ export class AudioUpload extends React.Component {
PanelHeight={() => 400}
renderDepth={0}
isDocumentActive={returnTrue}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
focus={emptyFunction}
layerProvider={undefined}
styleProvider={() => "rgba(0,0,0,0)"}
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 652804126..d732a6e2f 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -211,7 +211,7 @@ export class MobileInterface extends React.Component {
PanelHeight={this.returnHeight}
renderDepth={0}
isDocumentActive={returnTrue}
- isContentActive={returnFalse}
+ isContentActive={emptyFunction}
focus={DocUtils.DefaultFocus}
styleProvider={this.whitebackground}
layerProvider={undefined}