aboutsummaryrefslogtreecommitdiff
path: root/src/client/documents/Documents.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/documents/Documents.ts')
-rw-r--r--src/client/documents/Documents.ts93
1 files changed, 50 insertions, 43 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 457811e26..8d97ce5af 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -21,6 +21,7 @@ import { Networking } from '../Network';
import { DocumentManager } from '../util/DocumentManager';
import { DragManager, dropActionType } from '../util/DragManager';
import { DirectoryImportBox } from '../util/Import & Export/DirectoryImportBox';
+import { FollowLinkScript } from '../util/LinkFollower';
import { LinkManager } from '../util/LinkManager';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { undoBatch, UndoManager } from '../util/UndoManager';
@@ -166,6 +167,7 @@ export class DocumentOptions {
_chromeHidden?: boolean; // whether the editing chrome for a document is hidden
_searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view)
_forceActive?: boolean; // flag to handle pointer events when not selected (or otherwise active)
+ enableDragWhenActive?: boolean; // allow dragging even if document contentts are active (e.g., tree, groups)
_stayInCollection?: boolean; // whether the document should remain in its collection when someone tries to drag and drop it elsewhere
_raiseWhenDragged?: boolean; // whether a document is brought to front when dragged.
_hideContextMenu?: boolean; // whether the context menu can be shown
@@ -221,6 +223,8 @@ export class DocumentOptions {
recording?: boolean; // whether WebCam is recording or not
autoPlayAnchors?: boolean; // whether to play audio/video when an anchor is clicked in a stackedTimeline.
dontPlayLinkOnSelect?: boolean; // whether an audio/video should start playing when a link is followed to it.
+ linkSource?: Doc; // the source document for a collection of backlinks
+ updateContentsScript?: ScriptField; // reactive script invoked when viewing a document that can update contents of a collection (or do anything)
toolTip?: string; // tooltip to display on hover
toolType?: string; // type of pen tool
expertMode?: boolean; // something available only in expert (not novice) mode
@@ -228,7 +232,8 @@ export class DocumentOptions {
contextMenuScripts?: List<ScriptField>;
contextMenuLabels?: List<string>;
contextMenuIcons?: List<string>;
- allowClickBeforeDoubleClick?: boolean; // whether a click function can fire before the timeout for a double click has expired
+ defaultDoubleClick?: 'ignore' | 'default'; // ignore double clicks, or deafult (undefined) means open document full screen
+ waitForDoubleClickToClick?: 'always' | 'never' | 'default'; // whether a click function wait for double click to expire. 'default' undefined = wait only if there's a click handler, "never" = never wait, "always" = alway wait
dontUndo?: boolean; // whether button clicks should be undoable (this is set to true for Undo/Redo/and sidebar buttons that open the siebar panel)
description?: string; // added for links
layout?: string | Doc; // default layout string for a document
@@ -245,6 +250,7 @@ export class DocumentOptions {
childContextMenuIcons?: List<string>;
followLinkZoom?: boolean; // whether to zoom to the target of a link
hideLinkButton?: boolean; // whether the blue link counter button should be hidden
+ disableDocBrushing?: boolean; // whether to suppress border highlighting
hideDecorationTitle?: boolean;
hideOpenButton?: boolean;
hideResizeHandles?: boolean;
@@ -258,8 +264,8 @@ export class DocumentOptions {
caption?: RichTextField;
opacity?: number;
defaultBackgroundColor?: string;
- _isLinkButton?: boolean; // marks a document as a button that will follow its primary link when clicked
_linkAutoMove?: boolean; // whether link endpoint should move around the edges of a document to make shortest path to other link endpoint
+ hideLinkAnchors?: boolean; // suppresses link anchor dots from being displayed
isFolder?: boolean;
lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide)
activeFrame?: number; // the active frame of a document in a frame base collection
@@ -309,6 +315,7 @@ export class DocumentOptions {
linearViewExpandable?: boolean; // can linear view be expanded
linearViewToggleButton?: string; // button to open close linear view group
linearViewSubMenu?: boolean;
+ linearBtnWidth?: number;
flexGap?: number; // Linear view flex gap
flexDirection?: 'unset' | 'row' | 'column' | 'row-reverse' | 'column-reverse';
@@ -407,6 +414,7 @@ export namespace Docs {
nativeDimModifiable: true,
nativeHeightUnfrozen: true,
forceReflow: true,
+ defaultDoubleClick: 'ignore',
},
},
],
@@ -435,7 +443,7 @@ export namespace Docs {
DocumentType.WEB,
{
layout: { view: WebBox, dataField: defaultDataKey },
- options: { _height: 300, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true },
+ options: { _height: 300, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, waitForDoubleClickToClick: 'always' },
},
],
[
@@ -463,7 +471,7 @@ export namespace Docs {
DocumentType.AUDIO,
{
layout: { view: AudioBox, dataField: defaultDataKey },
- options: { _height: 100, forceReflow: true, nativeDimModifiable: true },
+ options: { _height: 100, fitWidth: true, forceReflow: true, nativeDimModifiable: true },
},
],
[
@@ -500,12 +508,13 @@ export namespace Docs {
layout: { view: LinkBox, dataField: defaultDataKey },
options: {
childDontRegisterViews: true,
- _isLinkButton: true,
+ onClick: FollowLinkScript(),
+ hideLinkAnchors: true,
_height: 150,
description: '',
showCaption: 'description',
backgroundColor: 'lightblue', // lightblue is default color for linking dot and link documents text comment area
- _removeDropProperties: new List(['isLinkButton']),
+ _removeDropProperties: new List(['onClick']),
},
},
],
@@ -577,14 +586,14 @@ export namespace Docs {
DocumentType.PRES,
{
layout: { view: PresBox, dataField: defaultDataKey },
- options: {},
+ options: { defaultDoubleClick: 'ignore', hideLinkAnchors: true },
},
],
[
DocumentType.FONTICON,
{
- layout: { view: FontIconBox, dataField: defaultDataKey },
- options: { allowClickBeforeDoubleClick: true, hideLinkButton: true, _width: 40, _height: 40, borderRounding: '100%' },
+ layout: { view: FontIconBox, dataField: 'icon' },
+ options: { defaultDoubleClick: 'ignore', waitForDoubleClickToClick: 'never', enableDragWhenActive: true, hideLinkButton: true, _width: 40, _height: 40 },
},
],
[
@@ -761,7 +770,6 @@ export namespace Docs {
...(template.options || {}),
layout: layout.view?.LayoutString(layout.dataField),
data: template.data,
- layout_keyValue: KeyValueBox.LayoutString(''),
};
Object.entries(options).map(pair => {
if (typeof pair[1] === 'string' && pair[1].startsWith('@')) {
@@ -927,13 +935,13 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey);
}
- export function LinkDocument(source: { doc: Doc; ctx?: Doc }, target: { doc: Doc; ctx?: Doc }, options: DocumentOptions = {}, id?: string) {
+ export function LinkDocument(source: Doc, target: Doc, options: DocumentOptions = {}, id?: string) {
const linkDoc = InstanceFromProto(
Prototypes.get(DocumentType.LINK),
undefined,
{
- anchor1: source.doc,
- anchor2: target.doc,
+ anchor1: source,
+ anchor2: target,
...options,
},
id
@@ -983,6 +991,7 @@ export namespace Docs {
I.author = Doc.CurrentUserEmail;
I.rotation = 0;
I.data = new InkField(points);
+ I.defaultDoubleClick = 'click';
I.creationDate = new DateField();
I['acl-Public'] = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
//I['acl-Override'] = SharingPermissions.Unset;
@@ -1020,9 +1029,10 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.MARKER), new List(documents), { lat, lng, infoWindowOpen, ...options }, id);
}
- export function KVPDocument(document: Doc, options: DocumentOptions = {}) {
- return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + '.kvp', ...options });
- }
+ // shouldn't ever need to create a KVP document-- instead set the LayoutTemplateString to be a KeyValueBox for the DocumentView (see addDocTab in TabDocView)
+ // export function KVPDocument(document: Doc, options: DocumentOptions = {}) {
+ // return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + '.kvp', ...options });
+ // }
export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xPadding: 20, _yPadding: 20, ...options, _viewType: CollectionViewType.Freeform }, id);
@@ -1285,16 +1295,14 @@ export namespace DocUtils {
broadcastEvent && runInAction(() => (DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1));
return DocUtils.ActiveRecordings.map(audio => {
const sourceDoc = getSourceDoc();
- const link = sourceDoc && DocUtils.MakeLink({ doc: sourceDoc }, { doc: audio.getAnchor(true) || audio.props.Document }, 'recording annotation:linked recording', 'recording timeline');
- link && (link.followLinkLocation = OpenWhere.addRight);
- return link;
+ return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { linkDisplay: false, linkRelationship: 'recording annotation:linked recording', description: 'recording timeline' });
});
}
- export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = '', description: string = '', id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) {
- if (!linkRelationship) linkRelationship = target.doc.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link';
- const sv = DocumentManager.Instance.getDocumentView(source.doc);
- if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target.doc) return;
+ export function MakeLink(source: Doc, target: Doc, linkSettings: { linkRelationship?: string; description?: string; linkDisplay?: boolean }, id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) {
+ if (!linkSettings.linkRelationship) linkSettings.linkRelationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link';
+ const sv = DocumentManager.Instance.getDocumentView(source);
+ if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target) return;
if (target.doc === Doc.UserDoc()) return undefined;
const makeLink = action((linkDoc: Doc, showPopup?: number[]) => {
@@ -1334,16 +1342,16 @@ export namespace DocUtils {
target,
{
title: ComputedField.MakeFunction('generateLinkTitle(self)') as any,
- 'anchor1-useLinkSmallAnchor': source.doc.useLinkSmallAnchor ? true : undefined,
- 'anchor2-useLinkSmallAnchor': target.doc.useLinkSmallAnchor ? true : undefined,
+ 'anchor1-useLinkSmallAnchor': source.useLinkSmallAnchor ? true : undefined,
+ 'anchor2-useLinkSmallAnchor': target.useLinkSmallAnchor ? true : undefined,
'acl-Public': SharingPermissions.Augment,
'_acl-Public': SharingPermissions.Augment,
- linkDisplay: true,
+ linkDisplay: linkSettings.linkDisplay,
_linkAutoMove: true,
- linkRelationship,
+ linkRelationship: linkSettings.linkRelationship,
_showCaption: 'description',
_showTitle: 'linkRelationship',
- description,
+ description: linkSettings.description,
},
id
),
@@ -1411,41 +1419,39 @@ export namespace DocUtils {
export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, options?: DocumentOptions): Doc | undefined {
let created: Doc | undefined;
- let layout: ((fieldKey: string) => string) | undefined;
const field = target[fieldKey];
- const resolved = options || {};
+ const resolved = options ?? {};
if (field instanceof ImageField) {
created = Docs.Create.ImageDocument(field.url.href, resolved);
- layout = ImageBox.LayoutString;
+ created.layout = ImageBox.LayoutString(fieldKey);
} else if (field instanceof Doc) {
created = field;
} else if (field instanceof VideoField) {
created = Docs.Create.VideoDocument(field.url.href, resolved);
- layout = VideoBox.LayoutString;
+ created.layout = VideoBox.LayoutString(fieldKey);
} else if (field instanceof PdfField) {
created = Docs.Create.PdfDocument(field.url.href, resolved);
- layout = PDFBox.LayoutString;
+ created.layout = PDFBox.LayoutString(fieldKey);
} else if (field instanceof AudioField) {
created = Docs.Create.AudioDocument(field.url.href, resolved);
- layout = AudioBox.LayoutString;
+ created.layout = AudioBox.LayoutString(fieldKey);
} else if (field instanceof RecordingField) {
created = Docs.Create.RecordingDocument(field.url.href, resolved);
- layout = RecordingBox.LayoutString;
+ created.layout = RecordingBox.LayoutString(fieldKey);
} else if (field instanceof InkField) {
created = Docs.Create.InkDocument(ActiveInkColor(), Doc.ActiveTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), field.inkData, ActiveIsInkMask(), resolved);
- layout = InkingStroke.LayoutString;
+ created.layout = InkingStroke.LayoutString(fieldKey);
} else if (field instanceof List && field[0] instanceof Doc) {
created = Docs.Create.StackingDocument(DocListCast(field), resolved);
- layout = CollectionView.LayoutString;
+ created.layout = CollectionView.LayoutString(fieldKey);
} else if (field instanceof MapField) {
created = Docs.Create.MapDocument(DocListCast(field), resolved);
- layout = MapBox.LayoutString;
+ created.layout = MapBox.LayoutString(fieldKey);
} else {
created = Docs.Create.TextDocument('', { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved });
- layout = FormattedTextBox.LayoutString;
+ created.layout = FormattedTextBox.LayoutString(fieldKey);
}
if (created) {
- created.layout = layout?.(fieldKey);
created.title = fieldKey;
proto && created.proto && (created.proto = Doc.GetProto(proto));
}
@@ -1541,7 +1547,7 @@ export namespace DocUtils {
const documentList: ContextMenuProps[] = DocListCast(DocListCast(Doc.MyTools?.data)[0]?.data)
.filter(btnDoc => !btnDoc.hidden)
.map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null))
- .filter(doc => doc && doc !== Doc.UserDoc().emptyTrail)
+ .filter(doc => doc && doc !== Doc.UserDoc().emptyTrail && doc !== Doc.UserDoc().emptyDataViz)
.map((dragDoc, i) => ({
description: ':' + StrCast(dragDoc.title).replace('Untitled ', ''),
event: undoBatch((args: { x: number; y: number }) => {
@@ -1685,14 +1691,15 @@ export namespace DocUtils {
x: Cast(doc.x, 'number', null),
y: Cast(doc.y, 'number', null),
backgroundColor: '#ACCEF7',
+ hideAllLinks: true,
_width: 15,
_height: 15,
_xPadding: 0,
- _isLinkButton: true,
+ onClick: FollowLinkScript(),
_timecodeToShow: Cast(doc._timecodeToShow, 'number', null),
});
Doc.AddDocToList(context, annotationField, pushpin);
- const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, 'pushpin', '');
+ const pushpinLink = DocUtils.MakeLink(pushpin, doc, { linkRelationship: 'pushpin' }, '');
doc._timecodeToShow = undefined;
return pushpin;
}