aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Utils.ts29
-rw-r--r--src/client/documents/Documents.ts62
-rw-r--r--src/client/util/DocumentManager.ts2
-rw-r--r--src/client/util/SelectionManager.ts6
-rw-r--r--src/client/util/SharingManager.tsx2
-rw-r--r--src/client/views/DocumentButtonBar.tsx5
-rw-r--r--src/client/views/DocumentDecorations.tsx42
-rw-r--r--src/client/views/GlobalKeyHandler.ts7
-rw-r--r--src/client/views/InkingControl.tsx18
-rw-r--r--src/client/views/MainView.scss2
-rw-r--r--src/client/views/MainView.tsx44
-rw-r--r--src/client/views/OverlayView.tsx23
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx16
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx2
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx2
-rw-r--r--src/client/views/collections/CollectionTreeView.scss31
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx117
-rw-r--r--src/client/views/nodes/AudioBox.tsx5
-rw-r--r--src/client/views/nodes/DocumentView.scss1
-rw-r--r--src/client/views/nodes/DocumentView.tsx49
-rw-r--r--src/client/views/nodes/FontIconBox.scss12
-rw-r--r--src/client/views/nodes/FontIconBox.tsx1
-rw-r--r--src/client/views/nodes/PresBox.tsx8
-rw-r--r--src/client/views/nodes/WebBox.tsx10
-rw-r--r--src/client/views/pdf/PDFViewer.tsx2
-rw-r--r--src/mobile/ImageUpload.tsx2
-rw-r--r--src/mobile/MobileInterface.tsx53
-rw-r--r--src/new_fields/Doc.ts18
-rw-r--r--src/server/authentication/models/current_user_utils.ts649
-rw-r--r--src/server/database.ts2
30 files changed, 700 insertions, 522 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index 58f272ba5..9acdc8731 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -470,6 +470,35 @@ export function clearStyleSheetRules(sheet: any) {
return false;
}
+export function simulateMouseClick(element: Element, x: number, y: number, sx: number, sy: number) {
+ ["pointerdown", "pointerup"].map(event => element.dispatchEvent(
+ new PointerEvent(event, {
+ view: window,
+ bubbles: true,
+ cancelable: true,
+ button: 2,
+ pointerType: "mouse",
+ clientX: x,
+ clientY: y,
+ screenX: sx,
+ screenY: sy,
+ })));
+
+ element.dispatchEvent(
+ new MouseEvent("contextmenu", {
+ view: window,
+ bubbles: true,
+ cancelable: true,
+ button: 2,
+ clientX: x,
+ clientY: y,
+ movementX: 0,
+ movementY: 0,
+ screenX: sx,
+ screenY: sy,
+ }));
+}
+
export function setupMoveUpEvents(
target: object,
e: React.PointerEvent,
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 6778bc45e..237951a2c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -8,7 +8,6 @@ import { PDFBox } from "../views/nodes/PDFBox";
import { ScriptingBox } from "../views/nodes/ScriptingBox";
import { VideoBox } from "../views/nodes/VideoBox";
import { WebBox } from "../views/nodes/WebBox";
-import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
import { OmitKeys, JSONUtils, Utils } from "../../Utils";
import { Field, Doc, Opt, DocListCastAsync, FieldResult, DocListCast } from "../../new_fields/Doc";
import { ImageField, VideoField, AudioField, PdfField, WebField, YoutubeField } from "../../new_fields/URLField";
@@ -79,11 +78,13 @@ export interface DocumentOptions {
x?: number;
y?: number;
z?: number;
+ author?: string;
dropAction?: dropActionType;
childDropAction?: dropActionType;
layoutKey?: string;
type?: string;
title?: string;
+ label?: string; // short form of title for use as an icon label
style?: string;
page?: number;
scale?: number;
@@ -103,6 +104,7 @@ export interface DocumentOptions {
ignoreClick?: boolean;
lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
+ isAnnotating?: boolean; // whether we web document is annotation mode where links can't be clicked to allow annotations to be created
opacity?: number;
defaultBackgroundColor?: string;
isBackground?: boolean;
@@ -178,7 +180,7 @@ export namespace Docs {
};
type TemplateMap = Map<DocumentType, PrototypeTemplate>;
type PrototypeMap = Map<DocumentType, Doc>;
- const data = "data";
+ const defaultDataKey = "data";
const TemplateMap: TemplateMap = new Map([
[DocumentType.RTF, {
@@ -186,97 +188,97 @@ export namespace Docs {
options: { _height: 150, _xMargin: 10, _yMargin: 10 }
}],
[DocumentType.QUERY, {
- layout: { view: QueryBox, dataField: data },
+ layout: { view: QueryBox, dataField: defaultDataKey },
options: { _width: 400 }
}],
[DocumentType.COLOR, {
- layout: { view: ColorBox, dataField: data },
+ layout: { view: ColorBox, dataField: defaultDataKey },
options: { _nativeWidth: 220, _nativeHeight: 300 }
}],
[DocumentType.IMG, {
- layout: { view: ImageBox, dataField: data },
+ layout: { view: ImageBox, dataField: defaultDataKey },
options: {}
}],
[DocumentType.WEB, {
- layout: { view: WebBox, dataField: data },
+ layout: { view: WebBox, dataField: defaultDataKey },
options: { _height: 300 }
}],
[DocumentType.COL, {
- layout: { view: CollectionView, dataField: data },
+ layout: { view: CollectionView, dataField: defaultDataKey },
options: { _panX: 0, _panY: 0, scale: 1 } // , _width: 500, _height: 500 }
}],
[DocumentType.KVP, {
- layout: { view: KeyValueBox, dataField: data },
+ layout: { view: KeyValueBox, dataField: defaultDataKey },
options: { _height: 150 }
}],
[DocumentType.DOCHOLDER, {
- layout: { view: DocHolderBox, dataField: data },
+ layout: { view: DocHolderBox, dataField: defaultDataKey },
options: { _height: 250 }
}],
[DocumentType.VID, {
- layout: { view: VideoBox, dataField: data },
+ layout: { view: VideoBox, dataField: defaultDataKey },
options: { currentTimecode: 0 },
}],
[DocumentType.AUDIO, {
- layout: { view: AudioBox, dataField: data },
+ layout: { view: AudioBox, dataField: defaultDataKey },
options: { _height: 35, backgroundColor: "lightGray" }
}],
[DocumentType.PDF, {
- layout: { view: PDFBox, dataField: data },
+ layout: { view: PDFBox, dataField: defaultDataKey },
options: { curPage: 1 }
}],
[DocumentType.IMPORT, {
- layout: { view: DirectoryImportBox, dataField: data },
+ layout: { view: DirectoryImportBox, dataField: defaultDataKey },
options: { _height: 150 }
}],
[DocumentType.LINK, {
- layout: { view: LinkBox, dataField: data },
+ layout: { view: LinkBox, dataField: defaultDataKey },
options: { _height: 150 }
}],
[DocumentType.LINKDB, {
data: new List<Doc>(),
- layout: { view: EmptyBox, dataField: data },
- options: { childDropAction: "alias", title: "LINK DB" }
+ layout: { view: EmptyBox, dataField: defaultDataKey },
+ options: { childDropAction: "alias", title: "Global Link Database" }
}],
[DocumentType.SCRIPTING, {
- layout: { view: ScriptingBox, dataField: data }
+ layout: { view: ScriptingBox, dataField: defaultDataKey }
}],
[DocumentType.YOUTUBE, {
- layout: { view: YoutubeBox, dataField: data }
+ layout: { view: YoutubeBox, dataField: defaultDataKey }
}],
[DocumentType.LABEL, {
- layout: { view: LabelBox, dataField: data },
+ layout: { view: LabelBox, dataField: defaultDataKey },
}],
[DocumentType.BUTTON, {
layout: { view: LabelBox, dataField: "onClick" },
}],
[DocumentType.SLIDER, {
- layout: { view: SliderBox, dataField: data },
+ layout: { view: SliderBox, dataField: defaultDataKey },
}],
[DocumentType.PRES, {
- layout: { view: PresBox, dataField: data },
+ layout: { view: PresBox, dataField: defaultDataKey },
options: {}
}],
[DocumentType.FONTICON, {
- layout: { view: FontIconBox, dataField: data },
+ layout: { view: FontIconBox, dataField: defaultDataKey },
options: { _width: 40, _height: 40, borderRounding: "100%" },
}],
[DocumentType.RECOMMENDATION, {
- layout: { view: RecommendationsBox, dataField: data },
+ layout: { view: RecommendationsBox, dataField: defaultDataKey },
options: { _width: 200, _height: 200 },
}],
[DocumentType.WEBCAM, {
- layout: { view: DashWebRTCVideo, dataField: data }
+ layout: { view: DashWebRTCVideo, dataField: defaultDataKey }
}],
[DocumentType.PRESELEMENT, {
- layout: { view: PresElementBox, dataField: data }
+ layout: { view: PresElementBox, dataField: defaultDataKey }
}],
[DocumentType.INK, {
- layout: { view: InkingStroke, dataField: data },
+ layout: { view: InkingStroke, dataField: defaultDataKey },
options: { backgroundColor: "transparent" }
}],
[DocumentType.SCREENSHOT, {
- layout: { view: ScreenshotBox, dataField: data },
+ layout: { view: ScreenshotBox, dataField: defaultDataKey },
}],
]);
@@ -590,7 +592,7 @@ export namespace Docs {
}
export function WebDocument(url: string, options: DocumentOptions = {}) {
- return InstanceFromProto(Prototypes.get(DocumentType.WEB), new WebField(new URL(url)), { _fitWidth: true, ...options });
+ return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(new URL(url)) : undefined, { _fitWidth: true, _chromeStatus: url ? "disabled" : "enabled", isAnnotating: true, lockedTransform: true, ...options });
}
export function HtmlDocument(html: string, options: DocumentOptions = {}) {
@@ -962,7 +964,7 @@ export namespace DocUtils {
export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = "", id?: string) {
const sv = DocumentManager.Instance.getDocumentView(source.doc);
if (sv && sv.props.ContainingCollectionDoc === target.doc) return;
- if (target.doc === CurrentUserUtils.UserDocument) return undefined;
+ if (target.doc === Doc.UserDoc()) return undefined;
const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship }, id);
Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('self.anchor1.title +" (" + (self.linkRelationship||"to") +") " + self.anchor2.title');
@@ -992,7 +994,7 @@ export namespace DocUtils {
});
ContextMenu.Instance.addItem({
description: "Add Template Doc ...",
- subitems: DocListCast(Cast(Doc.UserDoc().expandingButtons, Doc, null)?.data).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc).map((dragDoc, i) => ({
+ subitems: DocListCast(Cast(Doc.UserDoc().dockedBtns, Doc, null)?.data).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc).map((dragDoc, i) => ({
description: ":" + StrCast(dragDoc.title),
event: (args: { x: number, y: number }) => {
const newDoc = Doc.ApplyTemplate(dragDoc);
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index e66e67723..4683e77a8 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -241,4 +241,4 @@ export class DocumentManager {
}
}
}
-Scripting.addGlobal(function focus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, true)); }); \ No newline at end of file
+Scripting.addGlobal(function DocFocus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, true)); }); \ No newline at end of file
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 6c386d684..a49977c42 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -28,21 +28,21 @@ export namespace SelectionManager {
manager.SelectedDocuments.clear();
manager.SelectedDocuments.set(docView, true);
}
- Doc.UserDoc().SelectedDocs = new List(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
+ Doc.UserDoc().activeSelection = new List(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
}
@action
DeselectDoc(docView: DocumentView): void {
if (manager.SelectedDocuments.get(docView)) {
manager.SelectedDocuments.delete(docView);
docView.props.whenActiveChanged(false);
- Doc.UserDoc().SelectedDocs = new List(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
+ Doc.UserDoc().activeSelection = new List(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
}
}
@action
DeselectAll(): void {
Array.from(manager.SelectedDocuments.keys()).map(dv => dv.props.whenActiveChanged(false));
manager.SelectedDocuments.clear();
- Doc.UserDoc().SelectedDocs = new List<Doc>([]);
+ Doc.UserDoc().activeSelection = new List<Doc>([]);
}
}
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 7496ac73c..3ce6de80d 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -109,7 +109,7 @@ export default class SharingManager extends React.Component<{}> {
if (isCandidate) {
const userDocument = await DocServer.GetRefField(user.userDocumentId);
if (userDocument instanceof Doc) {
- const notificationDoc = await Cast(userDocument.optionalRightCollection, Doc);
+ const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc);
runInAction(() => {
if (notificationDoc instanceof Doc) {
this.users.push({ user, notificationDoc });
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 5b78008ab..93987b751 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -21,7 +21,6 @@ import { Template, Templates } from "./Templates";
import React = require("react");
import { DragManager } from '../util/DragManager';
import { MetadataEntryMenu } from './MetadataEntryMenu';
-import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
@@ -202,9 +201,9 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView |
@computed
get pinButton() {
const targetDoc = this.view0?.props.Document;
- const isPinned = targetDoc && CurrentUserUtils.IsDocPinned(targetDoc);
+ const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
return !targetDoc ? (null) : <div className="documentButtonBar-linker"
- title={CurrentUserUtils.IsDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}
+ title={Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}
style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
onClick={e => {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c49fe157c..c8766a6b3 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -7,8 +7,7 @@ import { Doc, DataSym } from "../../new_fields/Doc";
import { PositionDocument } from '../../new_fields/documentSchemas';
import { ScriptField } from '../../new_fields/ScriptField';
import { Cast, StrCast, NumCast } from "../../new_fields/Types";
-import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
-import { Utils, setupMoveUpEvents, emptyFunction, returnFalse } from "../../Utils";
+import { Utils, setupMoveUpEvents, emptyFunction, returnFalse, simulateMouseClick } from "../../Utils";
import { DocUtils } from "../documents/Documents";
import { DocumentType } from '../documents/DocumentTypes';
import { DragManager } from "../util/DragManager";
@@ -69,7 +68,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
get Bounds(): { x: number, y: number, b: number, r: number } {
return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
if (documentView.props.renderDepth === 0 ||
- Doc.AreProtosEqual(documentView.props.Document, CurrentUserUtils.UserDocument)) {
+ Doc.AreProtosEqual(documentView.props.Document, Doc.UserDoc())) {
return bounds;
}
const transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse();
@@ -142,40 +141,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
@action onSettingsDown = (e: React.PointerEvent): void => {
setupMoveUpEvents(this, e, () => false, (e) => { }, this.onSettingsClick);
}
-
- simulateMouseClick(element: Element, x: number, y: number, sx: number, sy: number) {
- ["pointerdown", "pointerup"].map(event => element.dispatchEvent(
- new PointerEvent(event, {
- view: window,
- bubbles: true,
- cancelable: true,
- button: 2,
- pointerType: "mouse",
- clientX: x,
- clientY: y,
- screenX: sx,
- screenY: sy,
- })));
-
- element.dispatchEvent(
- new MouseEvent("contextmenu", {
- view: window,
- bubbles: true,
- cancelable: true,
- button: 2,
- clientX: x,
- clientY: y,
- movementX: 0,
- movementY: 0,
- screenX: sx,
- screenY: sy,
- }));
- }
@action onSettingsClick = (e: PointerEvent): void => {
if (e.button === 0 && !e.altKey && !e.ctrlKey) {
let child = SelectionManager.SelectedDocuments()[0].ContentDiv!.children[0];
while (child.children.length && child.className !== "jsx-parser") child = child.children[0];
- this.simulateMouseClick(child.children[0], e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+ simulateMouseClick(child.children[0], e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
}
}
@@ -193,7 +163,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
dragData.isSelectionMove = true;
this.Interacting = true;
this._hidden = true;
- DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(documentView => documentView.ContentDiv!), dragData, e.x, e.y, {
+ DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(dv => dv.ContentDiv!), dragData, e.x, e.y, {
dragComplete: action(e => this._hidden = this.Interacting = false),
hideSource: true
});
@@ -207,14 +177,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
@action
onCloseClick = async (e: PointerEvent) => {
if (e.button === 0) {
- const recent = Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc) as Doc;
+ const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc;
const selected = SelectionManager.SelectedDocuments().slice();
SelectionManager.DeselectAll();
this._addedCloseCalls.forEach(handler => handler(selected));
selected.map(dv => {
recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true);
- dv.props.removeDocument && dv.props.removeDocument(dv.props.Document);
+ dv.props.removeDocument?.(dv.props.Document);
});
}
}
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index d01f3f1e5..185222541 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -7,7 +7,6 @@ import { action, runInAction } from "mobx";
import { Doc } from "../../new_fields/Doc";
import { DictationManager } from "../util/DictationManager";
import SharingManager from "../util/SharingManager";
-import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
import { Cast, PromiseValue, NumCast } from "../../new_fields/Types";
import { ScriptField } from "../../new_fields/ScriptField";
import { InkingControl } from "./InkingControl";
@@ -194,7 +193,7 @@ export default class KeyManager {
}
break;
case "t":
- PromiseValue(Cast(CurrentUserUtils.UserDocument.Create, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+ PromiseValue(Cast(Doc.UserDoc()["tabs-button-tools"], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
if (MainView.Instance.flyoutWidth === 240) {
MainView.Instance.flyoutWidth = 0;
} else {
@@ -202,7 +201,7 @@ export default class KeyManager {
}
break;
case "l":
- PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+ PromiseValue(Cast(Doc.UserDoc()["tabs-button-library"], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
if (MainView.Instance.flyoutWidth === 250) {
MainView.Instance.flyoutWidth = 0;
} else {
@@ -210,7 +209,7 @@ export default class KeyManager {
}
break;
case "f":
- PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+ PromiseValue(Cast(Doc.UserDoc()["tabs-button-search"], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
if (MainView.Instance.flyoutWidth === 400) {
MainView.Instance.flyoutWidth = 0;
} else {
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 645c7fa54..172c1864a 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -12,9 +12,9 @@ import { FormattedTextBox } from "./nodes/FormattedTextBox";
export class InkingControl {
@observable static Instance: InkingControl;
- @computed private get _selectedTool(): InkTool { return FieldValue(NumCast(CurrentUserUtils.UserDocument.inkTool)) ?? InkTool.None; }
- @computed private get _selectedColor(): string { return GestureOverlay.Instance.Color ?? FieldValue(StrCast(CurrentUserUtils.UserDocument.inkColor)) ?? "rgb(244, 67, 54)"; }
- @computed private get _selectedWidth(): string { return GestureOverlay.Instance.Width?.toString() ?? FieldValue(StrCast(CurrentUserUtils.UserDocument.inkWidth)) ?? "5"; }
+ @computed private get _selectedTool(): InkTool { return FieldValue(NumCast(Doc.UserDoc().inkTool)) ?? InkTool.None; }
+ @computed private get _selectedColor(): string { return GestureOverlay.Instance.Color ?? FieldValue(StrCast(Doc.UserDoc().inkColor)) ?? "rgb(244, 67, 54)"; }
+ @computed private get _selectedWidth(): string { return GestureOverlay.Instance.Width?.toString() ?? FieldValue(StrCast(Doc.UserDoc().inkWidth)) ?? "5"; }
@observable public _open: boolean = false;
constructor() {
@@ -23,7 +23,7 @@ export class InkingControl {
switchTool = action((tool: InkTool): void => {
// this._selectedTool = tool;
- CurrentUserUtils.UserDocument.inkTool = tool;
+ Doc.UserDoc().inkTool = tool;
});
decimalToHexString(number: number) {
if (number < 0) {
@@ -34,7 +34,7 @@ export class InkingControl {
@undoBatch
switchColor = action((color: ColorState): void => {
- CurrentUserUtils.UserDocument.inkColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff");
+ Doc.UserDoc().inkColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff");
if (InkingControl.Instance.selectedTool === InkTool.None) {
const selected = SelectionManager.SelectedDocuments();
@@ -44,9 +44,9 @@ export class InkingControl {
view.props.Document.isTemplateForField ? view.props.Document : Doc.GetProto(view.props.Document);
if (targetDoc) {
if (StrCast(Doc.Layout(view.props.Document).layout).indexOf("FormattedTextBox") !== -1 && FormattedTextBox.HadSelection) {
- Doc.Layout(view.props.Document).color = CurrentUserUtils.UserDocument.inkColor;
+ Doc.Layout(view.props.Document).color = Doc.UserDoc().inkColor;
} else {
- Doc.Layout(view.props.Document)._backgroundColor = CurrentUserUtils.UserDocument.inkColor; // '_backgroundColor' is template specific. 'backgroundColor' would apply to all templates, but has no UI at the moment
+ Doc.Layout(view.props.Document)._backgroundColor = Doc.UserDoc().inkColor; // '_backgroundColor' is template specific. 'backgroundColor' would apply to all templates, but has no UI at the moment
}
}
});
@@ -57,7 +57,7 @@ export class InkingControl {
@action
switchWidth = (width: string): void => {
// this._selectedWidth = width;
- CurrentUserUtils.UserDocument.inkWidth = width;
+ Doc.UserDoc().inkWidth = width;
}
@computed
@@ -73,7 +73,7 @@ export class InkingControl {
@action
updateSelectedColor(value: string) {
// this._selectedColor = value;
- CurrentUserUtils.UserDocument.inkColor = value;
+ Doc.UserDoc().inkColor = value;
}
@computed
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index e9f2248ad..81d427f64 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -5,6 +5,7 @@
.mainView-tabButtons {
position: relative;
width: 100%;
+ margin-top: 10px;
}
.mainContent-div {
@@ -72,6 +73,7 @@
flex-direction: column;
position: relative;
height: 100%;
+ background: dimgray;
.documentView-node-topmost {
background: lightgrey;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index aec1f960a..f8e246315 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,5 +1,5 @@
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faTerminal, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faThumbtack, faTree, faTv, faUndoAlt, faVideo } from '@fortawesome/free-solid-svg-icons';
+import { faTerminal, faWindowMaximize, faAddressCard, faQuestionCircle, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faThumbtack, faTree, faTv, faUndoAlt, faVideo } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, configure, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -41,11 +41,12 @@ import { RadialMenu } from './nodes/RadialMenu';
import { OverlayView } from './OverlayView';
import PDFMenu from './pdf/PDFMenu';
import { PreviewCursor } from './PreviewCursor';
+import { ScriptField } from '../../new_fields/ScriptField';
@observer
export class MainView extends React.Component {
public static Instance: MainView;
- private _buttonBarHeight = 35;
+ private _buttonBarHeight = 26;
private _flyoutSizeOnDown = 0;
private _urlState: HistoryUtil.DocUrl;
private _docBtnRef = React.createRef<HTMLDivElement>();
@@ -60,7 +61,7 @@ export class MainView extends React.Component {
@computed private get userDoc() { return Doc.UserDoc(); }
@computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; }
@computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
- @computed public get sidebarButtonsDoc() { return Cast(CurrentUserUtils.UserDocument.sidebarButtons, Doc) as Doc; }
+ @computed public get sidebarButtonsDoc() { return Cast(this.userDoc["tabs-buttons"], Doc) as Doc; }
public isPointerDown = false;
@@ -102,7 +103,10 @@ export class MainView extends React.Component {
}
library.add(faTerminal);
+ library.add(faWindowMaximize);
library.add(faFileAlt);
+ library.add(faAddressCard);
+ library.add(faQuestionCircle);
library.add(faStickyNote);
library.add(faFont);
library.add(faExclamation);
@@ -200,7 +204,7 @@ export class MainView extends React.Component {
@action
createNewWorkspace = async (id?: string) => {
- const workspaces = Cast(this.userDoc.workspaces, Doc) as Doc;
+ const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc;
const workspaceCount = DocListCast(workspaces.data).length + 1;
const freeformOptions: DocumentOptions = {
x: 0,
@@ -210,8 +214,13 @@ export class MainView extends React.Component {
title: "Collection " + workspaceCount,
};
const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
- Doc.AddDocToList(Doc.GetProto(CurrentUserUtils.UserDocument.documents as Doc), "data", freeformDoc);
- const mainDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().documents as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row");
+ Doc.AddDocToList(Doc.GetProto(Doc.UserDoc().myDocuments as Doc), "data", freeformDoc);
+ const mainDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myDocuments as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row");
+
+ const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
+ mainDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!]);
+ mainDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors"]);
+
Doc.AddDocToList(workspaces, "data", mainDoc);
// bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
setTimeout(() => this.openWorkspace(mainDoc), 0);
@@ -252,7 +261,7 @@ export class MainView extends React.Component {
}
// if there is a pending doc, and it has new data, show it (syip: we use a timeout to prevent collection docking view from being uninitialized)
setTimeout(async () => {
- const col = this.userDoc && await Cast(this.userDoc.optionalRightCollection, Doc);
+ const col = this.userDoc && await Cast(this.userDoc.rightSidebarCollection, Doc);
col && Cast(col.data, listSpec(Doc)) && runInAction(() => MainViewNotifs.NotifsCol = col);
}, 100);
return true;
@@ -390,15 +399,14 @@ export class MainView extends React.Component {
mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1);
@computed get flyout() {
- const sidebarContent = this.userDoc?.sidebarContainer;
+ const sidebarContent = this.userDoc?.["tabs-panelContainer"];
if (!(sidebarContent instanceof Doc)) {
return (null);
}
- const sidebarButtonsDoc = Cast(CurrentUserUtils.UserDocument.sidebarButtons, Doc) as Doc;
return <div className="mainView-flyoutContainer" >
- <div className="mainView-tabButtons" style={{ height: `${this._buttonBarHeight}px`, backgroundColor: StrCast(sidebarButtonsDoc.backgroundColor) }}>
+ <div className="mainView-tabButtons" style={{ height: `${this._buttonBarHeight}px`, backgroundColor: StrCast(this.sidebarButtonsDoc.backgroundColor) }}>
<DocumentView
- Document={sidebarButtonsDoc}
+ Document={this.sidebarButtonsDoc}
DataDoc={undefined}
LibraryPath={emptyPath}
addDocument={undefined}
@@ -459,7 +467,7 @@ export class MainView extends React.Component {
}
@computed get mainContent() {
- const sidebar = this.userDoc && this.userDoc.sidebarContainer;
+ const sidebar = this.userDoc?.["tabs-panelContainer"];
return !this.userDoc || !(sidebar instanceof Doc) ? (null) : (
<div className="mainView-mainContent" style={{ color: this.darkScheme ? "rgb(205,205,205)" : "black" }} >
<div className="mainView-flyoutContainer" onPointerLeave={this.pointerLeaveDragger} style={{ width: this.flyoutWidth }}>
@@ -496,8 +504,8 @@ export class MainView extends React.Component {
return !this._flyoutTranslate ? (<div className="mainView-expandFlyoutButton" title="Re-attach sidebar" onPointerDown={MainView.expandFlyout}><FontAwesomeIcon icon="chevron-right" color="grey" size="lg" /></div>) : (null);
}
- addButtonDoc = (doc: Doc) => Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc);
- remButtonDoc = (doc: Doc) => Doc.RemoveDocFromList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc);
+ addButtonDoc = (doc: Doc) => Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc);
+ remButtonDoc = (doc: Doc) => Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc);
moveButtonDoc = (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => this.remButtonDoc(doc) && addDocument(doc);
buttonBarXf = () => {
@@ -506,13 +514,13 @@ export class MainView extends React.Component {
return new Transform(-translateX, -translateY, 1 / scale);
}
@computed get docButtons() {
- const expandingBtns = Doc.UserDoc()?.expandingButtons;
- if (expandingBtns instanceof Doc) {
+ const dockedBtns = Doc.UserDoc()?.dockedBtns;
+ if (dockedBtns instanceof Doc) {
return <div className="mainView-docButtons" ref={this._docBtnRef}
- style={{ height: !expandingBtns.linearViewIsExpanded ? "42px" : undefined }} >
+ style={{ height: !dockedBtns.linearViewIsExpanded ? "42px" : undefined }} >
<MainViewNotifs />
<CollectionLinearView
- Document={expandingBtns}
+ Document={dockedBtns}
DataDoc={undefined}
LibraryPath={emptyPath}
fieldKey={"data"}
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 4000cade5..614217bc8 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,16 +1,14 @@
-import * as React from "react";
+import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { observable, action, trace, computed } from "mobx";
-import { Utils, emptyFunction, returnOne, returnTrue, returnEmptyString, returnZero, returnFalse, emptyPath } from "../../Utils";
-
-import './OverlayView.scss';
-import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
-import { DocListCast, Doc } from "../../new_fields/Doc";
+import * as React from "react";
+import { Doc, DocListCast } from "../../new_fields/Doc";
import { Id } from "../../new_fields/FieldSymbols";
-import { DocumentView } from "./nodes/DocumentView";
-import { Transform } from "../util/Transform";
import { NumCast } from "../../new_fields/Types";
+import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero, Utils } from "../../Utils";
+import { Transform } from "../util/Transform";
import { CollectionFreeFormLinksView } from "./collections/collectionFreeForm/CollectionFreeFormLinksView";
+import { DocumentView } from "./nodes/DocumentView";
+import './OverlayView.scss';
export type OverlayDisposer = () => void;
@@ -140,10 +138,11 @@ export class OverlayView extends React.Component {
}
@computed get overlayDocs() {
- if (!CurrentUserUtils.UserDocument) {
+ const userDocOverlays = Doc.UserDoc().myOverlayDocuments;
+ if (!userDocOverlays) {
return (null);
}
- return CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => {
+ return userDocOverlays instanceof Doc && DocListCast(userDocOverlays.data).map(d => {
setTimeout(() => d.inOverlay = true, 0);
let offsetx = 0, offsety = 0;
const onPointerMove = action((e: PointerEvent) => {
@@ -195,7 +194,7 @@ export class OverlayView extends React.Component {
addDocTab={returnFalse}
pinToPres={emptyFunction}
ContainingCollectionView={undefined}
- ContainingCollectionDoc={undefined}/>
+ ContainingCollectionDoc={undefined} />
</div>;
});
}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index c74f5555b..5e77bc0bb 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -14,11 +14,9 @@ import { List } from '../../../new_fields/List';
import { FieldId } from "../../../new_fields/RefField";
import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
import { TraceMobx } from '../../../new_fields/util';
-import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
import { emptyFunction, returnOne, returnTrue, Utils, returnZero } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { Docs } from '../../documents/Documents';
-import { DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager, dropActionType } from "../../util/DragManager";
import { Scripting } from '../../util/Scripting';
@@ -376,8 +374,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
// Because this is in a set timeout, if this component unmounts right after mounting,
// we will leak a GoldenLayout, because we try to destroy it before we ever create it
setTimeout(() => this.setupGoldenLayout(), 1);
- const userDoc = CurrentUserUtils.UserDocument;
- userDoc && DocListCast((userDoc.workspaces as Doc).data).map(d => d.workspaceBrush = false);
+ DocListCast((Doc.UserDoc().myWorkspaces as Doc).data).map(d => d.workspaceBrush = false);
this.props.Document.workspaceBrush = true;
}
this._ignoreStateChange = "";
@@ -544,9 +541,8 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
const theDoc = doc;
CollectionDockingView.Instance._removedDocs.push(theDoc);
- const userDoc = CurrentUserUtils.UserDocument;
- let recent: Doc | undefined;
- if (userDoc && (recent = await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))) {
+ const recent = await Cast(Doc.UserDoc().myRecentlyClosed, Doc);
+ if (recent) {
Doc.AddDocToList(recent, "data", doc, undefined, true, true);
}
SelectionManager.DeselectAll();
@@ -606,7 +602,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
const doc = await DocServer.GetRefField(contentItem.config.props.documentId);
if (doc instanceof Doc) {
let recent: Doc | undefined;
- if (CurrentUserUtils.UserDocument && (recent = await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))) {
+ if (recent = await Cast(Doc.UserDoc().myRecentlyClosed, Doc)) {
Doc.AddDocToList(recent, "data", doc, undefined, true, true);
}
const theDoc = doc;
@@ -681,7 +677,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
@action
public static PinDoc(doc: Doc) {
//add this new doc to props.Document
- const curPres = Cast(CurrentUserUtils.UserDocument.curPresentation, Doc) as Doc;
+ const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
if (curPres) {
const pinDoc = Doc.MakeAlias(doc);
pinDoc.presentationTargetDoc = doc;
@@ -698,7 +694,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
@action
public static UnpinDoc(doc: Doc) {
//add this new doc to props.Document
- const curPres = Cast(CurrentUserUtils.UserDocument.curPresentation, Doc) as Doc;
+ const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
if (curPres) {
const ind = DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc));
ind !== -1 && Doc.RemoveDocFromList(curPres, "data", DocListCast(curPres.data)[ind]);
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index dd84c4d6e..b15649d83 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -63,7 +63,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
const dxf = () => this.getDocTransform(d, dref.current!);
this._docXfs.push({ dxf: dxf, width: width, height: height });
const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap);
- const style = this.isStackingView ? { width: width(), marginTop: this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` };
+ const style = this.isStackingView ? { width: width(), marginTop: i ? this.gridGap : 0, height: height() } : { gridRowEnd: `span ${rowSpan}` };
return <div className={`collectionStackingView-${this.isStackingView ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} >
{this.getDisplayDoc(d, (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc, dxf, width)}
</div>;
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 1d1949c99..742a818bc 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -91,7 +91,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
public static SyncTimelineToPresentation(doc: Doc) {
const fieldKey = Doc.LayoutFieldKey(doc);
- doc[fieldKey + "-timelineCur"] = ComputedField.MakeFunction("(curPresentationItem()[this._pivotField || 'year'] || 0)");
+ doc[fieldKey + "-timelineCur"] = ComputedField.MakeFunction("(activePresentationItem()[this._pivotField || 'year'] || 0)");
}
specificMenu = (e: React.MouseEvent) => {
const layoutItems: ContextMenuProps[] = [];
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 8e95f7fbe..1e59c493f 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -100,10 +100,29 @@
border-left: dashed 1px #00000042;
}
+.treeViewItem-header {
+ border: transparent 1px solid;
+ display: flex;
+
+ .editableView-container-editing-oneLine {
+ min-width: 15px;
+ }
+ .documentView-node-topmost {
+ width: unset;
+ }
+ > svg {
+ display: none;
+ }
+
+}
+
.treeViewItem-header:hover {
.collectionTreeView-keyHeader {
display: inherit;
}
+ > svg {
+ display: inherit;
+ }
.treeViewItem-openRight {
display: inline-block;
@@ -119,18 +138,6 @@
}
}
-.treeViewItem-header {
- border: transparent 1px solid;
- display: flex;
-
- .editableView-container-editing-oneLine {
- min-width: 15px;
- }
- .documentView-node-topmost {
- width: unset;
- }
-}
-
.treeViewItem-header-above {
border-top: black 1px solid;
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 5ff8c11ee..83e536167 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -6,11 +6,10 @@ import { observer } from "mobx-react";
import { Doc, DocListCast, Field, HeightSym, WidthSym, DataSym, Opt } from '../../../new_fields/Doc';
import { Id } from '../../../new_fields/FieldSymbols';
import { List } from '../../../new_fields/List';
-import { Document, listSpec, createSchema, makeInterface } from '../../../new_fields/Schema';
+import { Document, listSpec } from '../../../new_fields/Schema';
import { ComputedField, ScriptField } from '../../../new_fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../new_fields/Types';
-import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
-import { emptyFunction, emptyPath, returnFalse, Utils, returnOne, returnZero, returnTransparent, returnTrue } from '../../../Utils';
+import { emptyFunction, emptyPath, returnFalse, Utils, returnOne, returnZero, returnTransparent, returnTrue, simulateMouseClick } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from "../../documents/DocumentTypes";
import { DocumentManager } from '../../util/DocumentManager';
@@ -32,7 +31,7 @@ import { Templates } from '../Templates';
import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
import "./CollectionTreeView.scss";
import React = require("react");
-import { CollectionViewType } from './CollectionView';
+import { CollectionViewType, CollectionView } from './CollectionView';
import { RichTextField } from '../../../new_fields/RichTextField';
import { DocumentView } from '../nodes/DocumentView';
@@ -139,6 +138,9 @@ class TreeView extends React.Component<TreeViewProps> {
@undoBatch @action remove = (document: Document, key: string) => {
return Doc.RemoveDocFromList(this.dataDoc, key, document);
}
+ @undoBatch @action removeDoc = (document: Document) => {
+ return Doc.RemoveDocFromList(this.props.containingCollection, Doc.LayoutFieldKey(this.props.containingCollection), document);
+ }
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this._treedropDisposer && this._treedropDisposer();
@@ -182,21 +184,17 @@ class TreeView extends React.Component<TreeViewProps> {
SetValue={undoBatch((value: string) => {
Doc.SetInPlace(this.props.document, key, value, false) || true;
Doc.SetInPlace(this.props.document, "editTitle", undefined, false);
- //this.props.document.editTitle = undefined;
})}
OnFillDown={undoBatch((value: string) => {
Doc.SetInPlace(this.props.document, key, value, false);
const doc = Docs.Create.FreeformDocument([], { title: "-", x: 0, y: 0, _width: 100, _height: 25, templates: new List<string>([Templates.Title.Layout]) });
- //EditableView.loadId = doc[Id];
Doc.SetInPlace(this.props.document, "editTitle", undefined, false);
- // this.props.document.editTitle = undefined;
Doc.SetInPlace(this.props.document, "editTitle", true, false);
- //doc.editTitle = true;
return this.props.addDocument(doc);
})}
onClick={() => {
SelectionManager.DeselectAll();
- Doc.UserDoc().SelectedDocs = new List([this.props.document]);
+ Doc.UserDoc().activeSelection = new List([this.props.document]);
return false;
}}
OnTab={undoBatch((shift?: boolean) => {
@@ -210,33 +208,6 @@ class TreeView extends React.Component<TreeViewProps> {
})}
/>)
- onWorkspaceContextMenu = (e: React.MouseEvent): void => {
- if (!e.isPropagationStopped()) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view
- const sort = this.props.document[`${this.fieldKey}-sortAscending`];
- if (this.props.document === CurrentUserUtils.UserDocument.recentlyClosed) {
- ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.GetProto(CurrentUserUtils.UserDocument.recentlyClosed as Doc).data = new List<Doc>(), icon: "plus" });
- } else if (this.props.document !== CurrentUserUtils.UserDocument.workspaces) {
- ContextMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.document), icon: "tv" });
- ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, "inTab", this.props.libraryPath), icon: "folder" });
- ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath), icon: "caret-square-right" });
- if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) {
- ContextMenu.Instance.addItem({ description: "Focus", event: () => (view => view && view.props.focus(this.props.document, true))(DocumentManager.Instance.getFirstDocumentView(this.props.document)), icon: "camera" });
- }
- ContextMenu.Instance.addItem({ description: "Delete Item", event: () => this.props.deleteDoc(this.props.document), icon: "trash-alt" });
- } else {
- ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.props.deleteDoc(this.props.document), icon: "trash-alt" });
- ContextMenu.Instance.addItem({ description: "Create New Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" });
- }
- ContextMenu.Instance.addItem({ description: (sort ? "Sort Descending" : (sort === false ? "Unsort" : "Sort Ascending")), event: () => this.props.document[`${this.fieldKey}-sortAscending`] = (sort ? false : (sort === false ? undefined : true)), icon: "minus" });
- ContextMenu.Instance.addItem({ description: "Toggle Theme Colors", event: () => this.props.document.darkScheme = !this.props.document.darkScheme, icon: "minus" });
- ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { const kvp = Docs.Create.KVPDocument(this.props.document, { _width: 300, _height: 300 }); this.props.addDocTab(kvp, "onRight"); }, icon: "layer-group" });
- ContextMenu.Instance.addItem({ description: "Publish", event: () => DocUtils.Publish(this.props.document, StrCast(this.props.document.title), () => { }, () => { }), icon: "file" });
- ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15);
- e.stopPropagation();
- e.preventDefault();
- }
- }
-
@undoBatch
treeDrop = (e: Event, de: DragManager.DropEvent) => {
const pt = [de.x, de.y];
@@ -356,7 +327,11 @@ class TreeView extends React.Component<TreeViewProps> {
const remDoc = (doc: Doc) => this.remove(doc, expandKey);
const addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true);
const docs = expandKey === "links" ? this.childLinks : this.childDocs;
- return <ul key={expandKey + "more"}>
+ const sortKey = `${this.fieldKey}-sortAscending`;
+ return <ul key={expandKey + "more"} onClick={(e) => {
+ this.props.document[sortKey] = (this.props.document[sortKey] ? false : (this.props.document[sortKey] === false ? undefined : true));
+ e.stopPropagation();
+ }}>
{!docs ? (null) :
TreeView.GetChildElements(docs, this.props.treeViewId, Doc.Layout(this.props.document),
this.templateDataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
@@ -421,6 +396,17 @@ class TreeView extends React.Component<TreeViewProps> {
{<FontAwesomeIcon icon={checked === "check" ? "check" : (checked === "x" ? "times" : checked === "unchecked" ? "square" : !this.treeViewOpen ? (this.childDocs ? "caret-square-right" : "caret-right") : (this.childDocs ? "caret-square-down" : "caret-down"))} />}
</div>;
}
+
+ showContextMenu = (e: React.MouseEvent) => {
+ simulateMouseClick(this._docRef.current!.ContentDiv!, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+ e.stopPropagation();
+ }
+ focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true);
+ contextMenuItems = () => {
+ const focusScript = ScriptField.MakeFunction(`DocFocus(self)`);
+ return [{ script: focusScript!, label: "Focus" }];
+ }
+ _docRef = React.createRef<DocumentView>();
/**
* Renders the EditableView title element for placement into the tree.
*/
@@ -430,19 +416,22 @@ class TreeView extends React.Component<TreeViewProps> {
const editTitle = ScriptField.MakeFunction("setInPlace(this, 'editTitle', true)");
const headerElements = (
- <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView}
- onPointerDown={action(() => {
- if (this.treeViewOpen) {
- this.props.document.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? "fields" :
- this.treeViewExpandedView === "fields" && Doc.Layout(this.props.document) ? "layout" :
- this.treeViewExpandedView === "layout" && this.props.document.links ? "links" :
- this.childDocs ? this.fieldKey : "fields";
- }
- this.treeViewOpen = true;
- })}>
- {this.treeViewExpandedView}
- </span>);
- const openRight = (<div className="treeViewItem-openRight" onPointerDown={this.onPointerDown} onClick={this.openRight}>
+ <>
+ <FontAwesomeIcon icon="cog" size="sm" onClick={e => this.showContextMenu(e)}></FontAwesomeIcon>
+ <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView}
+ onPointerDown={action(() => {
+ if (this.treeViewOpen) {
+ this.props.document.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? "fields" :
+ this.treeViewExpandedView === "fields" && Doc.Layout(this.props.document) ? "layout" :
+ this.treeViewExpandedView === "layout" && this.props.document.links ? "links" :
+ this.childDocs ? this.fieldKey : "fields";
+ }
+ this.treeViewOpen = true;
+ })}>
+ {this.treeViewExpandedView}
+ </span>
+ </>);
+ const openRight = (<div className="treeViewItem-openRight" onClick={this.openRight}>
<FontAwesomeIcon title="open in pane on right" icon="angle-right" size="lg" />
</div>);
return <>
@@ -457,6 +446,7 @@ class TreeView extends React.Component<TreeViewProps> {
{Doc.GetT(this.props.document, "editTitle", "boolean", true) ?
this.editableView("title") :
<DocumentView
+ ref={this._docRef}
Document={this.props.document}
DataDoc={undefined}
LibraryPath={this.props.libraryPath || []}
@@ -467,13 +457,14 @@ class TreeView extends React.Component<TreeViewProps> {
onClick={this.props.onChildClick || editTitle}
dropAction={this.props.dropAction}
moveDocument={this.props.moveDocument}
- removeDocument={undefined}
+ removeDocument={this.removeDoc}
ScreenToLocalTransform={this.getTransform}
ContentScaling={returnOne}
PanelWidth={returnZero}
PanelHeight={returnZero}
NativeHeight={returnZero}
NativeWidth={returnZero}
+ contextMenuItems={this.contextMenuItems}
renderDepth={1}
focus={emptyFunction}
parentActive={returnTrue}
@@ -490,14 +481,21 @@ class TreeView extends React.Component<TreeViewProps> {
}
render() {
+ const sorting = this.props.document[`${this.fieldKey}-sortAscending`];
setTimeout(() => runInAction(() => untracked(() => this._overrideTreeViewOpen = this.treeViewOpen)), 0);
- return <div className="treeViewItem-container" ref={this.createTreeDropTarget} onContextMenu={this.onWorkspaceContextMenu}>
+ return <div className="treeViewItem-container" ref={this.createTreeDropTarget}>
<li className="collection-child">
- <div className="treeViewItem-header" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+ <div className="treeViewItem-header" ref={this._header} onClick={e => {
+ e.stopPropagation();
+ e.preventDefault();
+ }} onPointerDown={e => {
+ e.stopPropagation();
+ e.preventDefault();
+ }} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
{this.renderBullet}
{this.renderTitle}
</div>
- <div className="treeViewItem-border">
+ <div className="treeViewItem-border" style={{ borderColor: sorting === undefined ? undefined : sorting ? "crimson" : "blue" }}>
{!this.treeViewOpen || this.props.renderedIds.indexOf(this.props.document[Id]) !== -1 ? (null) : this.renderContent}
</div>
</li>
@@ -692,14 +690,14 @@ export class CollectionTreeView extends CollectionSubView(Document, undefined as
}
onContextMenu = (e: React.MouseEvent): void => {
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
- if (!e.isPropagationStopped() && this.props.Document === CurrentUserUtils.UserDocument.workspaces) {
+ if (!e.isPropagationStopped() && this.props.Document === Doc.UserDoc().myWorkspaces) {
ContextMenu.Instance.addItem({ description: "Create Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" });
ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.remove(this.props.Document), icon: "minus" });
e.stopPropagation();
e.preventDefault();
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
- } else if (!e.isPropagationStopped() && this.props.Document === CurrentUserUtils.UserDocument.recentlyClosed) {
- ContextMenu.Instance.addItem({ description: "Clear All", event: () => CurrentUserUtils.UserDocument.recentlyClosed = new List<Doc>(), icon: "plus" });
+ } else if (!e.isPropagationStopped() && this.props.Document === Doc.UserDoc().myRecentlyClosed) {
+ ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.UserDoc().myRecentlyClosed = new List<Doc>(), icon: "plus" });
e.stopPropagation();
e.preventDefault();
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
@@ -740,14 +738,14 @@ export class CollectionTreeView extends CollectionSubView(Document, undefined as
heroView._showTitle = "title";
heroView._showTitleHover = "titlehover";
- Doc.AddDocToList(Doc.UserDoc().expandingButtons as Doc, "data",
+ Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data",
Docs.Create.FontIconDocument({
title: "hero view", _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias",
dragFactory: heroView, removeDropProperties: new List<string>(["dropAction"]), icon: "portrait",
onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
}));
- Doc.AddDocToList(Doc.UserDoc().expandingButtons as Doc, "data",
+ Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data",
Docs.Create.FontIconDocument({
title: "detail view", _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias",
dragFactory: detailView, removeDropProperties: new List<string>(["dropAction"]), icon: "file-alt",
@@ -782,6 +780,7 @@ export class CollectionTreeView extends CollectionSubView(Document, undefined as
}
render() {
+ if (!(this.props.Document instanceof Doc)) return (null);
const dropAction = StrCast(this.props.Document.childDropAction) as dropActionType;
const addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
const moveDoc = (d: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 7078cc01c..8f40ea2be 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -20,6 +20,7 @@ import { DocumentView } from "./DocumentView";
import { Docs } from "../../documents/Documents";
import { ComputedField } from "../../../new_fields/ScriptField";
import { Networking } from "../../Network";
+import { Upload } from "../../../server/SharedMediaTypes";
// testing testing
@@ -146,7 +147,9 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument
AudioBox.ActiveRecordings.push(this.props.Document);
this._recorder.ondataavailable = async (e: any) => {
const [{ result }] = await Networking.UploadFilesToServer(e.data);
- this.props.Document[this.props.fieldKey] = new AudioField(Utils.prepend(result.accessPaths.agnostic.client));
+ if (!(result instanceof Error)) {
+ this.props.Document[this.props.fieldKey] = new AudioField(Utils.prepend(result.accessPaths.agnostic.client));
+ }
};
this._recordStart = new Date().getTime();
runInAction(() => this.audioState = "recording");
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 81ae36cc0..692493414 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -71,7 +71,6 @@
display: inline-block;
width: 100%;
height: 100%;
- pointer-events: none;
.documentView-styleContentWrapper {
width: 100%;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e3013698d..196104fe0 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,21 +1,24 @@
import { library } from '@fortawesome/fontawesome-svg-core';
import * as fa from '@fortawesome/free-solid-svg-icons';
-import { action, computed, runInAction, trace, observable } from "mobx";
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import * as rp from "request-promise";
-import { Doc, DocListCast, Opt, WidthSym, HeightSym } from "../../../new_fields/Doc";
+import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
import { Document, PositionDocument } from '../../../new_fields/documentSchemas';
import { Id } from '../../../new_fields/FieldSymbols';
import { InkTool } from '../../../new_fields/InkField';
import { RichTextField } from '../../../new_fields/RichTextField';
import { listSpec } from "../../../new_fields/Schema";
+import { SchemaHeaderField } from '../../../new_fields/SchemaHeaderField';
import { ScriptField } from '../../../new_fields/ScriptField';
import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
import { AudioField, ImageField, PdfField, VideoField } from '../../../new_fields/URLField';
import { TraceMobx } from '../../../new_fields/util';
import { GestureUtils } from '../../../pen-gestures/GestureUtils';
-import { emptyFunction, returnOne, returnTransparent, returnTrue, Utils, OmitKeys, returnZero } from "../../../Utils";
+import { emptyFunction, OmitKeys, returnOne, returnTransparent, Utils } from "../../../Utils";
import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
+import { ClientRecommender } from '../../ClientRecommender';
import { DocServer } from "../../DocServer";
import { Docs, DocumentOptions, DocUtils } from "../../documents/Documents";
import { DocumentType } from '../../documents/DocumentTypes';
@@ -24,6 +27,7 @@ import { DocumentManager } from "../../util/DocumentManager";
import { DragManager, dropActionType } from "../../util/DragManager";
import { InteractionUtils } from '../../util/InteractionUtils';
import { Scripting } from '../../util/Scripting';
+import { SearchUtil } from '../../util/SearchUtil';
import { SelectionManager } from "../../util/SelectionManager";
import SharingManager from '../../util/SharingManager';
import { Transform } from "../../util/Transform";
@@ -35,19 +39,13 @@ import { ContextMenuProps } from '../ContextMenuItem';
import { DocComponent } from "../DocComponent";
import { EditableView } from '../EditableView';
import { InkingControl } from '../InkingControl';
+import { KeyphraseQueryView } from '../KeyphraseQueryView';
import { OverlayView } from '../OverlayView';
-import { ScriptBox } from '../ScriptBox';
import { ScriptingRepl } from '../ScriptingRepl';
import { DocumentContentsView } from "./DocumentContentsView";
import "./DocumentView.scss";
-import React = require("react");
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { SchemaHeaderField } from '../../../new_fields/SchemaHeaderField';
-import { ClientRecommender } from '../../ClientRecommender';
-import { SearchUtil } from '../../util/SearchUtil';
import { RadialMenu } from './RadialMenu';
-import { KeyphraseQueryView } from '../KeyphraseQueryView';
-import { undo } from 'prosemirror-history';
+import React = require("react");
library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight,
fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale,
@@ -65,6 +63,7 @@ export interface DocumentViewProps {
LayoutDoc?: () => Opt<Doc>;
LibraryPath: Doc[];
fitToBox?: boolean;
+ contextMenuItems?: () => { script: ScriptField, label: string }[];
rootSelected: (outsideReaction?: boolean) => boolean; // whether the root of a template has been selected
onClick?: ScriptField;
onPointerDown?: ScriptField;
@@ -306,7 +305,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
self: this.rootDoc,
thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey
}, console.log);
- if (this.props.Document !== Doc.UserDoc().undoBtn && this.props.Document !== Doc.UserDoc().redoBtn) {
+ if (this.props.Document !== Doc.UserDoc()["dockedBtn-undo"] && this.props.Document !== Doc.UserDoc()["dockedBtn-redo"]) {
UndoManager.RunInBatch(func, "on click");
} else func();
} else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself
@@ -480,15 +479,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
return;
}
+ this._downX = e.clientX;
+ this._downY = e.clientY;
if ((!e.nativeEvent.cancelBubble || this.onClickHandler || this.Document.onDragStart) &&
// if this is part of a template, let the event go up to the tempalte root unless right/ctrl clicking
!((this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0))) {
- this._downX = e.clientX;
- this._downY = e.clientY;
if ((this.active || this.Document.onDragStart || this.onClickHandler) &&
!e.ctrlKey &&
(e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) &&
- !this.Document.lockedPosition &&
!this.Document.inOverlay) {
e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag);
@@ -562,14 +560,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
static findTemplate(templateName: string, type: string, signature: string) {
let docLayoutTemplate: Opt<Doc>;
- const iconViews = DocListCast(Cast(Doc.UserDoc().iconViews, Doc, null)?.data);
+ const iconViews = DocListCast(Cast(Doc.UserDoc()["template-icons"], Doc, null)?.data);
const templBtns = DocListCast(Cast(Doc.UserDoc().templateButtons, Doc, null)?.data);
const noteTypes = DocListCast(Cast(Doc.UserDoc().noteTypes, Doc, null)?.data);
const clickFuncs = DocListCast(Cast(Doc.UserDoc().clickFuncs, Doc, null)?.data);
const allTemplates = iconViews.concat(templBtns).concat(noteTypes).concat(clickFuncs).map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc).filter(doc => doc.isTemplateDoc);
// bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document. but type is not reliable and there could be other types of template searches so this should be generalized
// first try to find a template that matches the specific document type (<typeName>_<templateName>). otherwise, fallback to a general match on <templateName>
- !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === type + "_" + templateName && (docLayoutTemplate = tempDoc));
+ !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName + "_" + type && (docLayoutTemplate = tempDoc));
!docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName && (docLayoutTemplate = tempDoc));
return docLayoutTemplate;
}
@@ -720,6 +718,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const cm = ContextMenu.Instance;
const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
+ const customScripts = Cast(this.props.Document.contextMenuScripts, listSpec(ScriptField), []);
+ Cast(this.props.Document.contextMenuLabels, listSpec("string"), []).forEach((label, i) =>
+ cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" }));
+ this.props.contextMenuItems?.().forEach(item =>
+ cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" }));
const existing = cm.findByDescription("Layout...");
const layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : [];
layoutItems.push({ description: this.Document.isBackground ? "As Foreground" : "As Background", event: (e) => this.toggleBackground(false), icon: this.Document.lockedPosition ? "unlock" : "lock" });
@@ -819,11 +822,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
icon: "brain"
});
- cm.addItem({ description: "Recommender System", subitems: recommender_subitems, icon: "brain" });
-
-
- moreItems.push({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" });
moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
+ moreItems.push({ description: "Recommender System", subitems: recommender_subitems, icon: "brain" });
+ moreItems.push({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" });
moreItems.push({ description: "Undo Debug Test", event: () => UndoManager.TraceOpenBatches(), icon: "exclamation" });
!more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
runInAction(() => {
@@ -990,7 +991,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
return typeof fallback === "string" ? fallback : "layout";
}
rootSelected = (outsideReaction?: boolean) => {
- return this.isSelected(outsideReaction) || (this.rootDoc && this.props.rootSelected?.(outsideReaction));
+ return this.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
}
childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling());
panelWidth = () => this.props.PanelWidth();
@@ -1170,7 +1171,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
<div className="documentView-contentBlocker" />
</> :
this.innards}
- {(this.Document.isBackground !== undefined || this.isSelected(false)) && this.props.renderDepth > 0 ? <div className="documentView-lock" onClick={() => this.toggleBackground(true)}> <FontAwesomeIcon icon={this.Document.isBackground ? "unlock" : "lock"} size="lg" /> </div> : (null)}
+ {(this.Document.isBackground !== undefined || this.isSelected(false)) && this.props.renderDepth > 0 && this.props.PanelWidth() > 0 ?
+ <div className="documentView-lock" onClick={() => this.toggleBackground(true)}> <FontAwesomeIcon icon={this.Document.isBackground ? "unlock" : "lock"} size="lg" /> </div>
+ : (null)}
</div>;
{ this._showKPQuery ? <KeyphraseQueryView keyphrases={this._queries}></KeyphraseQueryView> : undefined; }
}
diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss
index f0fe7a54e..68b00a5be 100644
--- a/src/client/views/nodes/FontIconBox.scss
+++ b/src/client/views/nodes/FontIconBox.scss
@@ -8,6 +8,18 @@
border-radius: 100%;
transform-origin: top left;
+ .fontIconBox-label {
+ background: gray;
+ color:white;
+ margin-left: -10px;
+ border-radius: 8px;
+ width:100%;
+ position: absolute;
+ text-align: center;
+ font-size: 8px;
+ margin-top:4px;
+ }
+
svg {
width: 95% !important;
height: 95%;
diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx
index 9329cf210..c6ea6a882 100644
--- a/src/client/views/nodes/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox.tsx
@@ -57,6 +57,7 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
boxShadow: this.props.Document.ischecked ? `4px 4px 12px black` : undefined
}}>
<FontAwesomeIcon className="fontIconBox-icon" icon={this.dataDoc.icon as any} color={this._foregroundColor} size="sm" />
+ {!this.rootDoc.label ? (null) : <div className="fontIconBox-label"> {StrCast(this.rootDoc.label).substring(0, 5)} </div>}
</button>;
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index e428e16da..80d043db1 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -49,7 +49,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
@computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); }
@computed get currentIndex() { return NumCast(this.layoutDoc._itemIndex); }
- updateCurrentPresentation = action(() => Doc.UserDoc().curPresentation = this.rootDoc);
+ updateCurrentPresentation = action(() => Doc.UserDoc().activePresentation = this.rootDoc);
next = () => {
this.updateCurrentPresentation();
@@ -253,14 +253,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
updateMinimize = undoBatch(action((e: React.ChangeEvent, mode: CollectionViewType) => {
if (BoolCast(this.layoutDoc.inOverlay) !== (mode === CollectionViewType.Invalid)) {
if (this.layoutDoc.inOverlay) {
- Doc.RemoveDocFromList((Doc.UserDoc().overlays as Doc), undefined, this.rootDoc);
+ Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
CollectionDockingView.AddRightSplit(this.rootDoc);
this.layoutDoc.inOverlay = false;
} else {
this.layoutDoc.x = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0)[0];// 500;//e.clientX + 25;
this.layoutDoc.y = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0)[1];////e.clientY - 25;
this.props.addDocTab?.(this.rootDoc, "close");
- Doc.AddDocToList((Doc.UserDoc().overlays as Doc), undefined, this.rootDoc);
+ Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
}
}
}));
@@ -292,7 +292,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.updateMinimize(e, StrCast(this.layoutDoc._viewType));
});
- childLayoutTemplate = () => this.layoutDoc._viewType === CollectionViewType.Stacking ? Cast(Doc.UserDoc().presentationTemplate, Doc, null) : undefined;
+ childLayoutTemplate = () => this.layoutDoc._viewType === CollectionViewType.Stacking ? Cast(Doc.UserDoc()["template-presentation"], Doc, null) : undefined;
render() {
const mode = StrCast(this.layoutDoc._viewType) as CollectionViewType;
this.initializeViewAliases(this.childDocs, mode);
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 0a7772044..66ddf64c9 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -7,7 +7,7 @@ import { documentSchema } from "../../../new_fields/documentSchemas";
import { HtmlField } from "../../../new_fields/HtmlField";
import { InkTool } from "../../../new_fields/InkField";
import { makeInterface } from "../../../new_fields/Schema";
-import { Cast, NumCast } from "../../../new_fields/Types";
+import { Cast, NumCast, BoolCast, StrCast } from "../../../new_fields/Types";
import { WebField } from "../../../new_fields/URLField";
import { Utils, returnOne, emptyFunction, returnZero } from "../../../Utils";
import { Docs } from "../../documents/Documents";
@@ -22,7 +22,6 @@ import React = require("react");
import * as WebRequest from 'web-request';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
-import { DocumentView } from "./DocumentView";
const htmlToText = require("html-to-text");
library.add(faStickyNote);
@@ -34,7 +33,8 @@ const WebDocument = makeInterface(documentSchema);
export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocument>(WebDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(WebBox, fieldKey); }
- @observable private _collapsed: boolean = true;
+ get _collapsed() { return StrCast(this.layoutDoc._chromeStatus) === "disabled"; }
+ set _collapsed(value) { this.layoutDoc._chromeStatus = !value ? "enabled" : "disabled"; }
@observable private _url: string = "hello";
@observable private _pressX: number = 0;
@observable private _pressY: number = 0;
@@ -68,7 +68,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
this._setPreviewCursor?.(e.screenX, e.screenY, false);
}
iframeScrolled = (e: any) => {
- const scroll = (e.target as any)?.children?.[0].scrollTop;
+ const scroll = e.target?.children?.[0].scrollTop;
this.layoutDoc.scrollTop = this._outerRef.current!.scrollTop = scroll;
}
async componentDidMount() {
@@ -345,7 +345,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
</div>}
</>);
}
- scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.props.Document.scrollTop))
+ scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.props.Document.scrollTop));
render() {
return (<div className={`webBox-container`}
style={{
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 10cfaa2f1..46b60b554 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -553,7 +553,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
highlight = (color: string) => {
// creates annotation documents for current highlights
const annotationDoc = this.makeAnnotationDocument(color);
- annotationDoc && this.props?.addDocument(annotationDoc);
+ annotationDoc && this.props.addDocument?.(annotationDoc);
return annotationDoc;
}
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index 5903a2ce9..295e82142 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -67,7 +67,7 @@ class Uploader extends React.Component {
const field = await DocServer.GetRefField(res);
let pending: Opt<Doc>;
if (field instanceof Doc) {
- pending = await Cast(field.optionalRightCollection, Doc);
+ pending = await Cast(field.rightSidebarCollection, Doc);
}
if (pending) {
this.status = "has pending docs";
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index c87ac719c..73ebbb303 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -1,51 +1,38 @@
import React = require('react');
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faEraser, faHighlighter, faLongArrowAltLeft, faMousePointer, faPenNib } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
-import { computed, action, observable } from 'mobx';
-import { CurrentUserUtils } from '../server/authentication/models/current_user_utils';
-import { FieldValue, Cast, StrCast } from '../new_fields/Types';
-import { Doc, DocListCast } from '../new_fields/Doc';
+import { DocServer } from '../client/DocServer';
import { Docs } from '../client/documents/Documents';
-import { CollectionView } from '../client/views/collections/CollectionView';
-import { DocumentView } from '../client/views/nodes/DocumentView';
-import { emptyPath, emptyFunction, returnFalse, returnOne, returnEmptyString, returnTrue, returnZero } from '../Utils';
-import { Transform } from '../client/util/Transform';
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faPenNib, faHighlighter, faEraser, faMousePointer, faBreadSlice, faTrash, faCheck, faLongArrowAltLeft } from '@fortawesome/free-solid-svg-icons';
+import { DocumentManager } from '../client/util/DocumentManager';
+import RichTextMenu from '../client/util/RichTextMenu';
import { Scripting } from '../client/util/Scripting';
-import { CollectionFreeFormView } from '../client/views/collections/collectionFreeForm/CollectionFreeFormView';
+import { Transform } from '../client/util/Transform';
+import { CollectionView } from '../client/views/collections/CollectionView';
+import { DocumentDecorations } from '../client/views/DocumentDecorations';
import GestureOverlay from '../client/views/GestureOverlay';
import { InkingControl } from '../client/views/InkingControl';
-import { InkTool } from '../new_fields/InkField';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import "./MobileInterface.scss";
-import { SelectionManager } from '../client/util/SelectionManager';
-import { DateField } from '../new_fields/DateField';
-import { GestureUtils } from '../pen-gestures/GestureUtils';
-import { DocServer } from '../client/DocServer';
-import { DocumentDecorations } from '../client/views/DocumentDecorations';
-import { OverlayView } from '../client/views/OverlayView';
-import { DictationOverlay } from '../client/views/DictationOverlay';
-import SharingManager from '../client/util/SharingManager';
-import { PreviewCursor } from '../client/views/PreviewCursor';
-import { ContextMenu } from '../client/views/ContextMenu';
+import { DocumentView } from '../client/views/nodes/DocumentView';
import { RadialMenu } from '../client/views/nodes/RadialMenu';
-import PDFMenu from '../client/views/pdf/PDFMenu';
-import MarqueeOptionsMenu from '../client/views/collections/collectionFreeForm/MarqueeOptionsMenu';
-import GoogleAuthenticationManager from '../client/apis/GoogleAuthenticationManager';
-import { listSpec } from '../new_fields/Schema';
+import { PreviewCursor } from '../client/views/PreviewCursor';
+import { Doc, DocListCast, FieldResult } from '../new_fields/Doc';
import { Id } from '../new_fields/FieldSymbols';
-import { DocumentManager } from '../client/util/DocumentManager';
-import RichTextMenu from '../client/util/RichTextMenu';
+import { InkTool } from '../new_fields/InkField';
+import { listSpec } from '../new_fields/Schema';
+import { Cast, FieldValue } from '../new_fields/Types';
import { WebField } from "../new_fields/URLField";
-import { FieldResult } from "../new_fields/Doc";
-import { List } from '../new_fields/List';
+import { CurrentUserUtils } from '../server/authentication/models/current_user_utils';
+import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero } from '../Utils';
+import "./MobileInterface.scss";
library.add(faLongArrowAltLeft);
@observer
export default class MobileInterface extends React.Component {
@observable static Instance: MobileInterface;
- @computed private get userDoc() { return CurrentUserUtils.UserDocument; }
+ @computed private get userDoc() { return Doc.UserDoc(); }
@computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; }
// @observable private currentView: "main" | "ink" | "upload" = "main";
private mainDoc: any = CurrentUserUtils.setupMobileDoc(this.userDoc);
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index bcf0d1aec..8e8f0928c 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -865,6 +865,16 @@ export namespace Doc {
return id;
}
+ export function isDocPinned(doc: Doc) {
+ //add this new doc to props.Document
+ const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
+ if (curPres) {
+ return DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)) !== -1;
+ }
+ return false;
+ }
+
+
export async function addFieldEnumerations(doc: Opt<Doc>, enumeratedFieldKey: string, enumerations: { title: string, _backgroundColor?: string, color?: string }[]) {
let optionsCollection = await DocServer.GetRefField(enumeratedFieldKey);
if (!(optionsCollection instanceof Doc)) {
@@ -906,13 +916,13 @@ Scripting.addGlobal(function redo() { return UndoManager.Redo(); });
Scripting.addGlobal(function DOC(id: string) { console.log("Can't parse a document id in a script"); return "invalid"; });
Scripting.addGlobal(function assignDoc(doc: Doc, field: string, id: string) { return Doc.assignDocToField(doc, field, id); });
Scripting.addGlobal(function docCast(doc: FieldResult): any { return DocCastAsync(doc); });
-Scripting.addGlobal(function curPresentationItem() {
- const curPres = Doc.UserDoc().curPresentation as Doc;
+Scripting.addGlobal(function activePresentationItem() {
+ const curPres = Doc.UserDoc().activePresentation as Doc;
return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)];
});
-Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); });
+Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().activeSelection = new List([doc]); });
Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
- const docs = DocListCast(Doc.UserDoc().SelectedDocs).
+ const docs = DocListCast(Doc.UserDoc().activeSelection).
filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCHOLDER && d.type !== DocumentType.KVP &&
(!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
return docs.length ? new List(docs) : prevValue;
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 9235a97b0..a2f016f94 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -18,6 +18,8 @@ import { makeTemplate } from "../../../client/util/DropConverter";
import { RichTextField } from "../../../new_fields/RichTextField";
import { PrefetchProxy } from "../../../new_fields/Proxy";
import { FormattedTextBox } from "../../../client/views/nodes/FormattedTextBox";
+import { MainView } from "../../../client/views/MainView";
+import { DocumentType } from "../../../client/documents/DocumentTypes";
export class CurrentUserUtils {
private static curr_id: string;
@@ -28,111 +30,223 @@ export class CurrentUserUtils {
public static get MainDocId() { return this.mainDocId; }
public static set MainDocId(id: string | undefined) { this.mainDocId = id; }
@computed public static get UserDocument() { return Doc.UserDoc(); }
- @computed public static get ActivePen() { return Doc.UserDoc().activePen instanceof Doc && (Doc.UserDoc().activePen as Doc).pen as Doc; }
+ @computed public static get ActivePen() { return Doc.UserDoc().activePen instanceof Doc && (Doc.UserDoc().activePen as Doc).inkPen as Doc; }
@observable public static GuestTarget: Doc | undefined;
@observable public static GuestWorkspace: Doc | undefined;
@observable public static GuestMobile: Doc | undefined;
- static setupDefaultDocTemplates(doc: Doc, buttons?: string[]) {
- const taskStatusValues = [{ title: "todo", _backgroundColor: "blue", color: "white" },
- { title: "in progress", _backgroundColor: "yellow", color: "black" },
- { title: "completed", _backgroundColor: "green", color: "white" }
- ];
- const noteTemplates = [
- Docs.Create.TextDocument("", { title: "text", style: "Note", isTemplateDoc: true, backgroundColor: "yellow" }),
- Docs.Create.TextDocument("", { title: "text", style: "Idea", isTemplateDoc: true, backgroundColor: "pink" }),
- Docs.Create.TextDocument("", { title: "text", style: "Topic", isTemplateDoc: true, backgroundColor: "lightBlue" }),
- Docs.Create.TextDocument("", { title: "text", style: "Person", isTemplateDoc: true, backgroundColor: "lightGreen" }),
- Docs.Create.TextDocument("", {
- title: "text", style: "Todo", isTemplateDoc: true, backgroundColor: "orange", _autoHeight: false,
- layout: FormattedTextBox.LayoutString("Todo"), _height: 100, _showCaption: "caption", caption: RichTextField.DashField("taskStatus")
- })
- ];
- doc.fieldTypes = Docs.Create.TreeDocument([], { title: "field enumerations" });
- Doc.addFieldEnumerations(Doc.GetProto(noteTemplates[4]), "taskStatus", taskStatusValues);
- doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(noteTemplates.map(nt => makeTemplate(nt, true, StrCast(nt.style)) ? nt : nt), { title: "Note Layouts", _height: 75 }));
+ // sets up the default User Templates - slideView, queryView, descriptionView
+ static setupUserTemplateButtons(doc: Doc) {
+ if (doc["template-button-query"] === undefined) {
+ const queryTemplate = Docs.Create.MulticolumnDocument(
+ [
+ Docs.Create.QueryDocument({ title: "query", _height: 200 }),
+ Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true })
+ ],
+ { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, hideFilterView: true }
+ );
+ queryTemplate.isTemplateDoc = makeTemplate(queryTemplate);
+ doc["template-button-query"] = CurrentUserUtils.ficon({
+ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
+ dragFactory: new PrefetchProxy(queryTemplate) as any as Doc,
+ removeDropProperties: new List<string>(["dropAction"]), title: "query view", icon: "question-circle"
+ });
+ }
+
+ if (doc["template-button-slides"] === undefined) {
+ const slideTemplate = Docs.Create.MultirowDocument(
+ [
+ Docs.Create.MulticolumnDocument([], { title: "data", _height: 200 }),
+ Docs.Create.TextDocument("", { title: "text", _height: 100 })
+ ],
+ { _width: 400, _height: 300, title: "slideView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, hideFilterView: true }
+ );
+ slideTemplate.isTemplateDoc = makeTemplate(slideTemplate);
+ doc["template-button-slides"] = CurrentUserUtils.ficon({
+ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
+ dragFactory: new PrefetchProxy(slideTemplate) as any as Doc,
+ removeDropProperties: new List<string>(["dropAction"]), title: "presentation slide", icon: "address-card"
+ });
+ }
+
+ if (doc["template-button-description"] === undefined) {
+ const descriptionTemplate = Docs.Create.TextDocument("", { title: "text", _height: 100, _showTitle: "title" });
+ Doc.GetProto(descriptionTemplate).layout = FormattedTextBox.LayoutString("description");
+ descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView");
+
+ doc["template-button-description"] = CurrentUserUtils.ficon({
+ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
+ dragFactory: new PrefetchProxy(descriptionTemplate) as any as Doc,
+ removeDropProperties: new List<string>(["dropAction"]), title: "description view", icon: "window-maximize"
+ });
+ }
+
+ if (doc["template-buttons"] === undefined) {
+ doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument([doc["template-button-slides"] as Doc, doc["template-button-description"] as Doc, doc["template-button-query"] as Doc], {
+ title: "Template Item Creators", _xMargin: 0, _showTitle: "title",
+ _autoHeight: true, _width: 500, columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
+ dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
+ }));
+ } else {
+ DocListCast(Cast(doc["template-buttons"], Doc, null)?.data); // prefetch templates
+ }
+ return doc["template-buttons"] as Doc;
}
- static setupDefaultIconTypes(doc: Doc, buttons?: string[]) {
- doc.iconView = new PrefetchProxy(Docs.Create.TextDocument("", { title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
- Doc.GetProto(doc.iconView as any as Doc).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
- doc.isTemplateDoc = makeTemplate(doc.iconView as any as Doc);
- doc.iconImageView = new PrefetchProxy(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") }));
- doc.isTemplateDoc = makeTemplate(doc.iconImageView as any as Doc, true, "image_icon");
- doc.iconColView = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") }));
- doc.isTemplateDoc = makeTemplate(doc.iconColView as any as Doc, true, "collection_icon");
- doc.iconViews = Docs.Create.TreeDocument([doc.iconView as any as Doc, doc.iconImageView as any as Doc, doc.iconColView as any as Doc], { title: "icon types", _height: 75 });
+
+ // setup the different note type skins
+ static setupNoteTemplates(doc: Doc) {
+ if (doc.noteTypes === undefined) {
+ const taskStatusValues = [
+ { title: "todo", _backgroundColor: "blue", color: "white" },
+ { title: "in progress", _backgroundColor: "yellow", color: "black" },
+ { title: "completed", _backgroundColor: "green", color: "white" }
+ ];
+ const noteTemplates = [
+ Docs.Create.TextDocument("", { title: "text", style: "Note", isTemplateDoc: true, backgroundColor: "yellow" }),
+ Docs.Create.TextDocument("", { title: "text", style: "Idea", isTemplateDoc: true, backgroundColor: "pink" }),
+ Docs.Create.TextDocument("", { title: "text", style: "Topic", isTemplateDoc: true, backgroundColor: "lightBlue" }),
+ Docs.Create.TextDocument("", { title: "text", style: "Person", isTemplateDoc: true, backgroundColor: "lightGreen" }),
+ Docs.Create.TextDocument("", {
+ title: "text", style: "Todo", isTemplateDoc: true, backgroundColor: "orange", _autoHeight: false, _height: 100, _showCaption: "caption",
+ layout: FormattedTextBox.LayoutString("Todo"), caption: RichTextField.DashField("taskStatus")
+ })
+ ];
+ doc.fieldTypes = Docs.Create.TreeDocument([], { title: "field enumerations" });
+ Doc.addFieldEnumerations(Doc.GetProto(noteTemplates[4]), "taskStatus", taskStatusValues);
+ doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(noteTemplates.map(nt => makeTemplate(nt, true, StrCast(nt.style)) ? nt : nt),
+ { title: "Note Layouts", _height: 75 }));
+ } else {
+ DocListCast(Cast(doc.noteTypes, Doc, null)?.data); // prefetch templates
+ }
+
+ return doc.noteTypes as Doc;
}
- // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools
- static setupCreatorButtons(doc: Doc, alreadyCreatedButtons?: string[]) {
- const emptyPresentation = Docs.Create.PresDocument(new List<Doc>(), { title: "Presentation", _viewType: CollectionViewType.Stacking, _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" });
- const emptyCollection = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, _LODdisable: true, _width: 150, _height: 100, title: "freeform" });
- doc.activePen = doc;
- const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [
- { title: "collection", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: emptyCollection },
- { title: "preview", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]"), { _width: 250, _height: 250, title: "container" })' },
- { title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", {_width: 300, _height: 300, title: "New Webpage" })' },
- { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth:250, title: "an image of a cat" })' },
- { title: "screenshot", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' },
- { title: "webcam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' },
- { title: "record", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` },
- { title: "clickable button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, title: "Button" })' },
- { title: "presentation", icon: "tv", click: 'openOnRight(Doc.UserDoc().curPresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().curPresentation = getCopy(this.dragFactory,true)`, dragFactory: emptyPresentation },
- { title: "script", icon: "terminal", ignoreClick: true, drag: 'Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250 title: "untitled script" })' },
- { title: "import folder", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' },
- { title: "mobile view", icon: "phone", ignoreClick: true, drag: 'Doc.UserDoc().activeMobile' },
- { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "use highlighter", icon: "highlighter", click: 'activateBrush(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "use stamp", icon: "stamp", click: 'activateStamp(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this)', backgroundColor: "orange", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc },
- { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc },
- { title: "query", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' },
+ // creates Note templates, and initial "user" templates
+ static setupDocTemplates(doc: Doc) {
+ const noteTemplates = CurrentUserUtils.setupNoteTemplates(doc);
+ const userTemplateBtns = CurrentUserUtils.setupUserTemplateButtons(doc);
+ const clickTemplates = CurrentUserUtils.setupClickEditorTemplates(doc);
+ if (doc.templateDocs === undefined) {
+ doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([noteTemplates, userTemplateBtns, clickTemplates], {
+ title: "template layouts", _xPadding: 0,
+ dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name })
+ }));
+ }
+ }
+
+ // setup templates for different document types when they are iconified from Document Decorations
+ static setupDefaultIconTemplates(doc: Doc) {
+ if (doc["template-icon-view"] === undefined) {
+ const iconView = Docs.Create.TextDocument("", {
+ title: "icon", _width: 150, _height: 30, isTemplateDoc: true,
+ onClick: ScriptField.MakeScript("deiconifyView(this)")
+ });
+ Doc.GetProto(iconView).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
+ iconView.isTemplateDoc = makeTemplate(iconView);
+ doc["template-icon-view"] = new PrefetchProxy(iconView);
+ }
+ if (doc["template-icon-view-img"] === undefined) {
+ const iconImageView = Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") });
+ iconImageView.isTemplateDoc = makeTemplate(iconImageView, true, "icon_" + DocumentType.IMG);
+ doc["template-icon-view-img"] = new PrefetchProxy(iconImageView);
+ }
+ if (doc["template-icon-view-col"] === undefined) {
+ const iconColView = Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, onClick: ScriptField.MakeScript("deiconifyView(self)") });
+ iconColView.isTemplateDoc = makeTemplate(iconColView, true, "icon_" + DocumentType.COL);
+ doc["template-icon-view-col"] = new PrefetchProxy(iconColView);
+ }
+ if (doc["template-icons"] === undefined) {
+ doc["template-icons"] = new PrefetchProxy(Docs.Create.TreeDocument([doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc, doc["template-icon-view-col"] as Doc], { title: "icon templates", _height: 75 }));
+ } else {
+ DocListCast(Cast(doc["template-icons"], Doc, null)?.data); // prefetch templates
+ }
+ return doc["template-icons"] as Doc;
+ }
+
+ static creatorBtnDescriptors(doc: Doc): {
+ title: string, label: string, icon: string, drag?: string, ignoreClick?: boolean,
+ click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc
+ }[] {
+ if (doc.emptyPresentation === undefined) {
+ doc.emptyPresentation = Docs.Create.PresDocument(new List<Doc>(),
+ { title: "Presentation", _viewType: CollectionViewType.Stacking, _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" });
+ }
+ if (doc.emptyCollection === undefined) {
+ doc.emptyCollection = Docs.Create.FreeformDocument([],
+ { _nativeWidth: undefined, _nativeHeight: undefined, _LODdisable: true, _width: 150, _height: 100, title: "freeform" });
+ }
+ return [
+ { title: "Drag a collection", label: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc },
+ { title: "Drag a web page", label: "Web", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("", { title: "New Webpage" })' },
+ { title: "Drag a cat image", label: "Img", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth:250, title: "an image of a cat" })' },
+ { title: "Drag a screenshot", label: "Grab", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' },
+ { title: "Drag a webcam", label: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' },
+ { title: "Drag a audio recorder", label: "Audio", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` },
+ { title: "Drag a clickable button", label: "Btn", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, title: "Button" })' },
+ { title: "Drag a presentation view", label: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory,true)`, dragFactory: doc.emptyPresentation as Doc },
+ { title: "Drag a scripting box", label: "Script", icon: "terminal", ignoreClick: true, drag: 'Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250 title: "untitled script" })' },
+ { title: "Drag an import folder", label: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' },
+ { title: "Drag a mobile view", label: "Phone", icon: "phone", ignoreClick: true, drag: 'Doc.UserDoc().activeMobile' },
+ // { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ // { title: "use highlighter", icon: "highlighter", click: 'activateBrush(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ // { title: "use stamp", icon: "stamp", click: 'activateStamp(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this)', backgroundColor: "orange", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ // { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.inkPen, this)`, backgroundColor: "pink", activePen: doc },
+ // { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.inkPen = this;', ischecked: `sameDocs(this.activePen.inkPen, this)`, backgroundColor: "white", activePen: doc },
+ { title: "Drag a search box", label: "Query", icon: "search", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' },
+ { title: "Drag a document previewer", label: "Prev", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]"), { _width: 250, _height: 250, title: "container" })' },
// { title: "buxton", icon: "cloud-upload-alt", ignoreClick: true, drag: "Docs.Create.Buxton()" },
];
- return docProtoData.filter(d => !alreadyCreatedButtons?.includes(d.title)).map(data => Docs.Create.FontIconDocument({
- _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100,
- icon: data.icon,
- title: data.title,
- ignoreClick: data.ignoreClick,
- dropAction: data.click ? "copy" : undefined,
- onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined,
- onClick: data.click ? ScriptField.MakeScript(data.click) : undefined,
- ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined,
- activePen: data.activePen,
- backgroundColor: data.backgroundColor, removeDropProperties: new List<string>(["dropAction"]),
- dragFactory: data.dragFactory,
- }));
}
- static async updateCreatorButtons(doc: Doc) {
- const toolsBtn = await Cast(doc.ToolsBtn, Doc);
- if (toolsBtn) {
- const stackingDoc = await Cast(toolsBtn.sourcePanel, Doc);
- if (stackingDoc) {
- const stackdocs = await Cast(stackingDoc.data, listSpec(Doc));
- if (stackdocs) {
- const dragset = await Cast(stackdocs[0], Doc);
- if (dragset) {
- const dragdocs = await Cast(dragset.data, listSpec(Doc));
- if (dragdocs) {
- const dragDocs = await Promise.all(dragdocs);
- this.setupCreatorButtons(doc, dragDocs.map(d => StrCast(d.title))).map(nb => Doc.AddDocToList(dragset, "data", nb));
- }
- }
- }
+ // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools
+ static async setupCreatorButtons(doc: Doc) {
+ let alreadyCreatedButtons: string[] = [];
+ const dragCreatorSet = await Cast(doc.myItemCreators, Doc, null);
+ if (dragCreatorSet) {
+ const dragCreators = await Cast(dragCreatorSet.data, listSpec(Doc));
+ if (dragCreators) {
+ const dragDocs = await Promise.all(dragCreators);
+ alreadyCreatedButtons = dragDocs.map(d => StrCast(d.title));
}
}
+ const creatorBtns = CurrentUserUtils.creatorBtnDescriptors(doc).filter(d => !alreadyCreatedButtons?.includes(d.title)).
+ map(data => Docs.Create.FontIconDocument({
+ _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100,
+ icon: data.icon,
+ title: data.title,
+ label: data.label,
+ ignoreClick: data.ignoreClick,
+ dropAction: data.click ? "copy" : undefined,
+ onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined,
+ onClick: data.click ? ScriptField.MakeScript(data.click) : undefined,
+ ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined,
+ activePen: data.activePen,
+ backgroundColor: data.backgroundColor, removeDropProperties: new List<string>(["dropAction"]),
+ dragFactory: data.dragFactory,
+ }));
+
+ if (dragCreatorSet === undefined) {
+ doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, {
+ title: "Standard Item Creators", _showTitle: "title", _xMargin: 0,
+ _autoHeight: true, _width: 500, columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
+ dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
+ }));
+ } else {
+ creatorBtns.forEach(nb => Doc.AddDocToList(doc.myItemCreators as Doc, "data", nb));
+ }
+ return doc.myItemCreators as Doc;
}
static setupMobileButtons(doc: Doc, buttons?: string[]) {
const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [
{ title: "record", icon: "microphone", ignoreClick: true, click: "FILL" },
- { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "use highlighter", icon: "highlighter", click: 'activateBrush(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc },
- { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc },
- // { title: "draw", icon: "pen-nib", click: 'switchMobileView(setupMobileInkingDoc, renderMobileInking, onSwitchMobileInking);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "red", activePen: doc },
+ { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ { title: "use highlighter", icon: "highlighter", click: 'activateBrush(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.inkPen, this)`, backgroundColor: "pink", activePen: doc },
+ { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.inkPen = this;', ischecked: `sameDocs(this.activePen.inkPen, this)`, backgroundColor: "white", activePen: doc },
+ // { title: "draw", icon: "pen-nib", click: 'switchMobileView(setupMobileInkingDoc, renderMobileInking, onSwitchMobileInking);', ischecked: `sameDocs(this.activePen.inkPen, this)`, backgroundColor: "red", activePen: doc },
{ title: "upload", icon: "upload", click: 'switchMobileView(setupMobileUploadDoc, renderMobileUpload, onSwitchMobileUpload);', backgroundColor: "orange" },
// { title: "upload", icon: "upload", click: 'uploadImageMobile();', backgroundColor: "cyan" },
];
@@ -146,11 +260,11 @@ export class CurrentUserUtils {
static setupThumbButtons(doc: Doc) {
const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, pointerDown?: string, pointerUp?: string, ischecked?: string, clipboard?: Doc, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [
- { title: "use pen", icon: "pen-nib", pointerUp: "resetPen()", pointerDown: 'setPen(2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "use highlighter", icon: "highlighter", pointerUp: "resetPen()", pointerDown: 'setPen(20, this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "notepad", icon: "clipboard", pointerUp: "GestureOverlay.Instance.closeFloatingDoc()", pointerDown: 'GestureOverlay.Instance.openFloatingDoc(this.clipboard)', clipboard: Docs.Create.FreeformDocument([], { _width: 300, _height: 300 }), backgroundColor: "orange", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "interpret text", icon: "font", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('inktotext')", backgroundColor: "orange", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
- { title: "ignore gestures", icon: "signature", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('ignoregesture')", backgroundColor: "green", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
+ { title: "use pen", icon: "pen-nib", pointerUp: "resetPen()", pointerDown: 'setPen(2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ { title: "use highlighter", icon: "highlighter", pointerUp: "resetPen()", pointerDown: 'setPen(20, this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ { title: "notepad", icon: "clipboard", pointerUp: "GestureOverlay.Instance.closeFloatingDoc()", pointerDown: 'GestureOverlay.Instance.openFloatingDoc(this.clipboard)', clipboard: Docs.Create.FreeformDocument([], { _width: 300, _height: 300 }), backgroundColor: "orange", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ { title: "interpret text", icon: "font", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('inktotext')", backgroundColor: "orange", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
+ { title: "ignore gestures", icon: "signature", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('ignoregesture')", backgroundColor: "green", ischecked: `sameDocs(this.activePen.inkPen, this)`, activePen: doc },
];
return docProtoData.map(data => Docs.Create.FontIconDocument({
_nativeWidth: 10, _nativeHeight: 10, _width: 10, _height: 10, title: data.title, icon: data.icon,
@@ -200,202 +314,242 @@ export class CurrentUserUtils {
});
}
- // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. when clicked, this panel will be displayed in the target container (ie, sidebarContainer)
- static setupToolsPanel(sidebarContainer: Doc, doc: Doc) {
+ // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker.
+ // when clicked, this panel will be displayed in the target container (ie, sidebarContainer)
+ static async setupToolsBtnPanel(doc: Doc, sidebarContainer: Doc) {
// setup a masonry view of all he creators
- const dragCreators = Docs.Create.MasonryDocument(CurrentUserUtils.setupCreatorButtons(doc), {
- _width: 500, _autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "buttons",
- dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), _yMargin: 5
- });
+ const creatorBtns = await CurrentUserUtils.setupCreatorButtons(doc);
+ const templateBtns = CurrentUserUtils.setupUserTemplateButtons(doc);
+
+ if (doc.myCreators === undefined) {
+ doc.myCreators = new PrefetchProxy(Docs.Create.StackingDocument([creatorBtns, templateBtns], {
+ title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0,
+ _width: 500, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
+ }));
+ }
// setup a color picker
- const color = Docs.Create.ColorDocument({
- title: "color picker", _width: 300, dropAction: "alias", forceActive: true, removeDropProperties: new List<string>(["dropAction", "forceActive"])
- });
+ if (doc.myColorPicker === undefined) {
+ const color = Docs.Create.ColorDocument({
+ title: "color picker", _width: 300, dropAction: "alias", forceActive: true, removeDropProperties: new List<string>(["dropAction", "forceActive"])
+ });
+ doc.myColorPicker = new PrefetchProxy(color);
+ }
- return Docs.Create.ButtonDocument({
- _width: 35, _height: 25, title: "Tools", fontSize: 10, targetContainer: sidebarContainer,
- letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
- sourcePanel: Docs.Create.StackingDocument([dragCreators, color], {
- _width: 500, lockedPosition: true, _chromeStatus: "disabled", title: "tools stack", forceActive: true
- }),
- onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel"),
- });
+ if (doc["tabs-button-tools"] === undefined) {
+ doc["tabs-button-tools"] = new PrefetchProxy(Docs.Create.ButtonDocument({
+ _width: 35, _height: 25, title: "Tools", fontSize: 10,
+ letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
+ sourcePanel: new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc, doc.myColorPicker as Doc], {
+ _width: 500, lockedPosition: true, _chromeStatus: "disabled", title: "tools stack", forceActive: true
+ })) as any as Doc,
+ targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc,
+ onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel"),
+ }));
+ }
+ (doc["tabs-button-tools"] as Doc).sourcePanel; // prefetch sourcePanel
+ return doc["tabs-button-tools"] as Doc;
}
- // setup the Library button which will display the library panel. This panel includes a collection of workspaces, documents, and recently closed views
- static setupLibraryPanel(sidebarContainer: Doc, doc: Doc) {
+ static setupWorkspaces(doc: Doc) {
// setup workspaces library item
- doc.workspaces = Docs.Create.TreeDocument([], {
- title: "WORKSPACES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true,
- });
-
- doc.documents = Docs.Create.TreeDocument([], {
- title: "DOCUMENTS", _height: 42, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: true, lockedPosition: true,
- });
+ if (doc.myWorkspaces === undefined) {
+ doc.myWorkspaces = new PrefetchProxy(Docs.Create.TreeDocument([], {
+ title: "WORKSPACES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true,
+ }));
+ }
+ const newWorkspace = ScriptField.MakeScript(`createNewWorkspace()`);
+ (doc.myWorkspaces as Doc).contextMenuScripts = new List<ScriptField>([newWorkspace!]);
+ (doc.myWorkspaces as Doc).contextMenuLabels = new List<string>(["Create New Workspace"]);
+ return doc.myWorkspaces as Doc;
+ }
+ static setupDocumentCollection(doc: Doc) {
+ if (doc.myDocuments === undefined) {
+ doc.myDocuments = new PrefetchProxy(Docs.Create.TreeDocument([], {
+ title: "DOCUMENTS", _height: 42, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: true, lockedPosition: true,
+ }));
+ }
+ return doc.myDocuments as Doc;
+ }
+ static setupRecentlyClosed(doc: Doc) {
// setup Recently Closed library item
- doc.recentlyClosed = Docs.Create.TreeDocument([], {
- title: "RECENTLY CLOSED", _height: 75, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: true, lockedPosition: true,
- });
+ if (doc.myRecentlyClosed === undefined) {
+ doc.myRecentlyClosed = new PrefetchProxy(Docs.Create.TreeDocument([], {
+ title: "RECENTLY CLOSED", _height: 75, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: true, lockedPosition: true,
+ }));
+ }
+ // this is equivalent to using PrefetchProxies to make sure the recentlyClosed doc is ready
+ PromiseValue(Cast(doc.myRecentlyClosed, Doc)).then(recent => recent && PromiseValue(recent.data).then(DocListCast));
+ const clearAll = ScriptField.MakeScript(`self.data = new List([])`);
+ (doc.myRecentlyClosed as Doc).contextMenuScripts = new List<ScriptField>([clearAll!]);
+ (doc.myRecentlyClosed as Doc).contextMenuLabels = new List<string>(["Clear All"]);
- return Docs.Create.ButtonDocument({
- _width: 50, _height: 25, title: "Library", fontSize: 10,
- letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
- sourcePanel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, Docs.Prototypes.MainLinkDocument(), doc, doc.recentlyClosed as Doc], {
- title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "place", lockedPosition: true, boxShadow: "0 0", dontRegisterChildren: true
- }),
- targetContainer: sidebarContainer,
- onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel;")
- });
+ return doc.myRecentlyClosed as Doc;
+ }
+ // setup the Library button which will display the library panel. This panel includes a collection of workspaces, documents, and recently closed views
+ static setupLibraryPanel(doc: Doc, sidebarContainer: Doc) {
+ const workspaces = CurrentUserUtils.setupWorkspaces(doc);
+ const documents = CurrentUserUtils.setupDocumentCollection(doc);
+ const recentlyClosed = CurrentUserUtils.setupRecentlyClosed(doc);
+
+ if (doc["tabs-button-library"] === undefined) {
+ doc["tabs-button-library"] = new PrefetchProxy(Docs.Create.ButtonDocument({
+ _width: 50, _height: 25, title: "Library", fontSize: 10,
+ letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
+ sourcePanel: new PrefetchProxy(Docs.Create.TreeDocument([workspaces, documents, recentlyClosed, doc], {
+ title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "place", lockedPosition: true, boxShadow: "0 0", dontRegisterChildren: true
+ })) as any as Doc,
+ targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc,
+ onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel;")
+ }));
+ }
+ return doc["tabs-button-library"] as Doc;
}
// setup the Search button which will display the search panel.
- static setupSearchPanel(sidebarContainer: Doc) {
- return Docs.Create.ButtonDocument({
- _width: 50, _height: 25, title: "Search", fontSize: 10,
- letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
- sourcePanel: Docs.Create.QueryDocument({ title: "search stack", }),
- targetContainer: sidebarContainer,
- lockedPosition: true,
- onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel")
- });
+ static setupSearchBtnPanel(doc: Doc, sidebarContainer: Doc) {
+ if (doc["tabs-button-search"] === undefined) {
+ doc["tabs-button-search"] = new PrefetchProxy(Docs.Create.ButtonDocument({
+ _width: 50, _height: 25, title: "Search", fontSize: 10,
+ letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
+ sourcePanel: new PrefetchProxy(Docs.Create.QueryDocument({ title: "search stack", })) as any as Doc,
+ targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc,
+ lockedPosition: true,
+ onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel")
+ }));
+ }
+ return doc["tabs-button-search"] as Doc;
}
- // setup the list of sidebar mode buttons which determine what is displayed in the sidebar
- static setupSidebarButtons(doc: Doc) {
- const sidebarContainer = new Doc();
- doc.sidebarContainer = new PrefetchProxy(sidebarContainer);
- sidebarContainer._chromeStatus = "disabled";
- sidebarContainer.onClick = ScriptField.MakeScript("freezeSidebar()");
+ static setupSidebarContainer(doc: Doc) {
+ if (doc["tabs-panelContainer"] === undefined) {
+ const sidebarContainer = new Doc();
+ sidebarContainer._chromeStatus = "disabled";
+ sidebarContainer.onClick = ScriptField.MakeScript("freezeSidebar()");
+ doc["tabs-panelContainer"] = new PrefetchProxy(sidebarContainer);
+ }
+ return doc["tabs-panelContainer"] as Doc;
+ }
- doc.ToolsBtn = new PrefetchProxy(this.setupToolsPanel(sidebarContainer, doc));
- doc.LibraryBtn = new PrefetchProxy(this.setupLibraryPanel(sidebarContainer, doc));
- doc.SearchBtn = new PrefetchProxy(this.setupSearchPanel(sidebarContainer));
+ // setup the list of sidebar mode buttons which determine what is displayed in the sidebar
+ static async setupSidebarButtons(doc: Doc) {
+ const sidebarContainer = CurrentUserUtils.setupSidebarContainer(doc);
+ const toolsBtn = await CurrentUserUtils.setupToolsBtnPanel(doc, sidebarContainer);
+ const libraryBtn = CurrentUserUtils.setupLibraryPanel(doc, sidebarContainer);
+ const searchBtn = CurrentUserUtils.setupSearchBtnPanel(doc, sidebarContainer);
// Finally, setup the list of buttons to display in the sidebar
- doc.sidebarButtons = new PrefetchProxy(Docs.Create.StackingDocument([doc.SearchBtn as any as Doc, doc.LibraryBtn as any as Doc, doc.ToolsBtn as any as Doc], {
- _width: 500, _height: 80, boxShadow: "0 0", _pivotField: "title", hideHeadings: true, ignoreClick: true, _chromeStatus: "view-mode",
- title: "sidebar btn row stack", backgroundColor: "dimGray",
- }));
+ if (doc["tabs-buttons"] === undefined) {
+ doc["tabs-buttons"] = new PrefetchProxy(Docs.Create.StackingDocument([searchBtn, libraryBtn, toolsBtn], {
+ _width: 500, _height: 80, boxShadow: "0 0", _pivotField: "title", hideHeadings: true, ignoreClick: true, _chromeStatus: "view-mode",
+ title: "sidebar btn row stack", backgroundColor: "dimGray",
+ }));
+ (toolsBtn.onClick as ScriptField).script.run({ this: toolsBtn });
+ }
}
+ static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
+ ...opts,
+ _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true,
+ dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
+ backgroundColor: "black", treeViewPreventOpen: true, lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true
+ })) as any as Doc
+
+ static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
+ ...opts,
+ dropAction: "alias", removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100
+ })) as any as Doc
+
/// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window
- static setupExpandingButtons(doc: Doc) {
- const queryTemplate = Docs.Create.MulticolumnDocument(
- [
- Docs.Create.QueryDocument({ title: "query", _height: 200, forceActive: true }),
- Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true, forceActive: true })
- ],
- { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false, forceActive: true, hideFilterView: true });
- queryTemplate.isTemplateDoc = makeTemplate(queryTemplate);
- const slideTemplate = Docs.Create.MultirowDocument(
- [
- Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, forceActive: true }),
- Docs.Create.TextDocument("", { title: "text", _height: 100, forceActive: true })
- ],
- { _width: 400, _height: 300, title: "slideView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false, forceActive: true, hideFilterView: true });
- slideTemplate.isTemplateDoc = makeTemplate(slideTemplate);
- const descriptionTemplate = Docs.Create.TextDocument("", { title: "text", _height: 100, _showTitle: "title" });
- Doc.GetProto(descriptionTemplate).layout = FormattedTextBox.LayoutString("description");
- descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView");
-
- const ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
- ...opts,
- dropAction: "alias", removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100
- })) as any as Doc;
- const blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
- ...opts,
- _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true,
- dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
- backgroundColor: "black", treeViewPreventOpen: true, lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true
- })) as any as Doc;
-
- doc.undoBtn = ficon({ onClick: ScriptField.MakeScript("undo()"), title: "undo button", icon: "undo-alt" });
- doc.redoBtn = ficon({ onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" });
- doc.slidesBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: slideTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "presentation slide", icon: "sticky-note" });
- doc.descriptionBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: descriptionTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "description view", icon: "sticky-note" });
- doc.queryBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: queryTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "query view", icon: "sticky-note" });
- doc.templateButtons = blist({ title: "template buttons", ignoreClick: true }, [doc.slidesBtn as Doc, doc.descriptionBtn as Doc, doc.queryBtn as Doc]);
- doc.expandingButtons = blist({ title: "expanding buttons", ignoreClick: true }, [doc.undoBtn as Doc, doc.redoBtn as Doc, doc.templateButtons as Doc]);
- doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([doc.noteTypes as Doc, doc.templateButtons as Doc, doc.clickFuncs as Doc], {
- title: "template layouts", _xPadding: 0,
- dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name })
- }));
+ static setupDockedButtons(doc: Doc) {
+ if (doc["dockedBtn-pen"] === undefined) {
+ doc["dockedBtn-pen"] = CurrentUserUtils.ficon({
+ onClick: ScriptField.MakeScript("activatePen(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this,2, this.backgroundColor)"),
+ author: "systemTemplates", title: "ink mode", icon: "pen-nib", ischecked: ComputedField.MakeFunction(`sameDocs(this.activePen.inkPen, this)`), activePen: doc
+ });
+ }
+ if (doc["dockedBtn-undo"] === undefined) {
+ doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), title: "undo button", icon: "undo-alt" });
+ }
+ if (doc["dockedBtn-redo"] === undefined) {
+ doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" });
+ }
+ if (doc.dockedBtns === undefined) {
+ doc.dockedBtns = CurrentUserUtils.blist({ title: "docked buttons", ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc, doc["dockedBtn-pen"] as Doc]);
+ }
}
-
// sets up the default set of documents to be shown in the Overlay layer
static setupOverlays(doc: Doc) {
- doc.overlays = new PrefetchProxy(Docs.Create.FreeformDocument([], { title: "Overlays", backgroundColor: "#aca3a6" }));
+ if (doc.myOverlayDocuments === undefined) {
+ doc.myOverlayDocuments = new PrefetchProxy(Docs.Create.FreeformDocument([], { title: "overlay documents", backgroundColor: "#aca3a6" }));
+ }
}
// the initial presentation Doc to use
static setupDefaultPresentation(doc: Doc) {
- doc.presentationTemplate = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ title: "pres element template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data" }));
- doc.curPresentation = Docs.Create.PresDocument(new List<Doc>(), { title: "Presentation", _viewType: CollectionViewType.Stacking, _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" });
+ if (doc["template-presentation"] === undefined) {
+ doc["template-presentation"] = new PrefetchProxy(Docs.Create.PresElementBoxDocument({
+ title: "pres element template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data"
+ }));
+ }
+ if (doc.activePresentation === undefined) {
+ doc.activePresentation = Docs.Create.PresDocument(new List<Doc>(), {
+ title: "Presentation", _viewType: CollectionViewType.Stacking,
+ _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0"
+ });
+ }
}
- static setupMobileUploads(doc: Doc) {
- doc.optionalRightCollection = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "New mobile uploads" }));
+ static setupRightSidebar(doc: Doc) {
+ if (doc.rightSidebarCollection === undefined) {
+ doc.rightSidebarCollection = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Right Sidebar" }));
+ }
}
- static setupChildClicks(doc: Doc) {
- const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript(
- "docCast(thisContainer.target).then((target) => { target && docCast(this.source).then((source) => { target.proto.data = new List([source || this]); } ); } )",
- { target: Doc.name }), { title: "On Child Clicked (open in target)", _width: 300, _height: 200 });
- const onClick = Docs.Create.ScriptingDocument(undefined, { title: "onClick", "onClick-rawScript": "console.log('click')", isTemplateDoc: true, isTemplateForField: "onClick", _width: 300, _height: 200 }, "onClick");
- const onCheckedClick = Docs.Create.ScriptingDocument(undefined,
- { title: "onCheckedClick", "onCheckedClick-rawScript": "console.log(heading + checked + containingTreeView)", "onCheckedClick-params": new List<string>(["heading", "checked", "containingTreeView"]), isTemplateDoc: true, isTemplateForField: "onCheckedClick", _width: 300, _height: 200 }, "onCheckedClick");
- doc.childClickFuncs = Docs.Create.TreeDocument([openInTarget], { title: "on Child Click function templates" });
- doc.clickFuncs = Docs.Create.TreeDocument([onClick, onCheckedClick], { title: "onClick funcs" });
- }
-
- static updateUserDocument(doc: Doc) {
- doc.title = Doc.CurrentUserEmail;
- new InkingControl();
- (doc.iconTypes === undefined) && CurrentUserUtils.setupDefaultIconTypes(doc);
- (doc.noteTypes === undefined) && CurrentUserUtils.setupDefaultDocTemplates(doc);
- (doc.childClickFuncs === undefined) && CurrentUserUtils.setupChildClicks(doc);
- (doc.optionalRightCollection === undefined) && CurrentUserUtils.setupMobileUploads(doc);
- (doc.overlays === undefined) && CurrentUserUtils.setupOverlays(doc);
- (doc.expandingButtons === undefined) && CurrentUserUtils.setupExpandingButtons(doc);
- (doc.curPresentation === undefined) && CurrentUserUtils.setupDefaultPresentation(doc);
- (doc.sidebarButtons === undefined) && CurrentUserUtils.setupSidebarButtons(doc);
+ static setupClickEditorTemplates(doc: Doc) {
+ if (doc.childClickFuncs === undefined) {
+ const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript(
+ "docCast(thisContainer.target).then((target) => { target && docCast(this.source).then((source) => { target.proto.data = new List([source || this]); } ); } )",
+ { target: Doc.name }), { title: "On Child Clicked (open in target)", _width: 300, _height: 200 });
+ doc.childClickFuncs = Docs.Create.TreeDocument([openInTarget], { title: "on Child Click function templates" });
+ }
// this is equivalent to using PrefetchProxies to make sure all the childClickFuncs have been retrieved.
PromiseValue(Cast(doc.childClickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast));
- // this is equivalent to using PrefetchProxies to make sure the recentlyClosed doc is ready
- PromiseValue(Cast(doc.recentlyClosed, Doc)).then(recent => recent && PromiseValue(recent.data).then(DocListCast));
- // this is equivalent to using PrefetchProxies to make sure all the sidebarButtons and noteType internal Doc's have been retrieved.
- PromiseValue(Cast(doc.noteTypes, Doc)).then(noteTypes => noteTypes && PromiseValue(noteTypes.data).then(DocListCast));
+
+ if (doc.clickFuncs === undefined) {
+ const onClick = Docs.Create.ScriptingDocument(undefined, {
+ title: "onClick", "onClick-rawScript": "console.log('click')",
+ isTemplateDoc: true, isTemplateForField: "onClick", _width: 300, _height: 200
+ }, "onClick");
+ const onCheckedClick = Docs.Create.ScriptingDocument(undefined, {
+ title: "onCheckedClick", "onCheckedClick-rawScript": "console.log(heading + checked + containingTreeView)", "onCheckedClick-params": new List<string>(["heading", "checked", "containingTreeView"]), isTemplateDoc: true, isTemplateForField: "onCheckedClick", _width: 300, _height: 200
+ }, "onCheckedClick");
+ doc.clickFuncs = Docs.Create.TreeDocument([onClick, onCheckedClick], { title: "onClick funcs" });
+ }
PromiseValue(Cast(doc.clickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast));
- PromiseValue(Cast(doc.childClickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast));
- PromiseValue(Cast(doc.sidebarButtons, Doc)).then(stackingDoc => {
- stackingDoc && PromiseValue(Cast(stackingDoc.data, listSpec(Doc))).then(sidebarButtons => {
- sidebarButtons && sidebarButtons.map((sidebarBtn, i) => {
- sidebarBtn && PromiseValue(Cast(sidebarBtn, Doc)).then(async btn => {
- btn && btn.sourcePanel && btn.targetContainer && i === 1 && (btn.onClick as ScriptField).script.run({ this: btn });
- });
- });
- });
- });
+
+ return doc.clickFuncs as Doc;
+ }
+
+ static async updateUserDocument(doc: Doc) {
+ new InkingControl();
+ doc.title = Doc.CurrentUserEmail;
+ doc.activePen = doc;
+ CurrentUserUtils.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon
+ CurrentUserUtils.setupRightSidebar(doc); // sets up the right sidebar collection for mobile upload documents and sharing
+ CurrentUserUtils.setupOverlays(doc); // documents in overlay layer
+ CurrentUserUtils.setupDockedButtons(doc); // the bottom bar of font icons
+ CurrentUserUtils.setupDefaultPresentation(doc); // presentation that's initially triggered
+ await CurrentUserUtils.setupSidebarButtons(doc); // the pop-out left sidebar of tools/panels
+ doc.globalLinkDatabase = Docs.Prototypes.MainLinkDocument();
// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet
- doc.undoBtn && reaction(() => UndoManager.undoStack.slice(), () => Doc.GetProto(doc.undoBtn as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true });
- doc.redoBtn && reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(doc.redoBtn as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true });
+ doc["dockedBtn-undo"] && reaction(() => UndoManager.undoStack.slice(), () => Doc.GetProto(doc["dockedBtn-undo"] as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true });
+ doc["dockedBtn-redo"] && reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(doc["dockedBtn-redo"] as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true });
- this.updateCreatorButtons(doc);
return doc;
}
-
- public static IsDocPinned(doc: Doc) {
- //add this new doc to props.Document
- const curPres = Cast(CurrentUserUtils.UserDocument.curPresentation, Doc) as Doc;
- if (curPres) {
- return DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)) !== -1;
- }
- return false;
- }
-
public static async loadCurrentUser() {
return rp.get(Utils.prepend("/getCurrentUser")).then(response => {
if (response) {
@@ -423,3 +577,4 @@ export class CurrentUserUtils {
Scripting.addGlobal(function setupMobileInkingDoc(userDoc: Doc) { return CurrentUserUtils.setupMobileInkingDoc(userDoc); });
Scripting.addGlobal(function setupMobileUploadDoc(userDoc: Doc) { return CurrentUserUtils.setupMobileUploadDoc(userDoc); });
+Scripting.addGlobal(function createNewWorkspace() { return MainView.Instance.createNewWorkspace(); }); \ No newline at end of file
diff --git a/src/server/database.ts b/src/server/database.ts
index 1da31c5ff..ad285765b 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -52,8 +52,6 @@ export namespace Database {
private currentWrites: { [id: string]: Promise<void> } = {};
private db?: mongodb.Db;
private onConnect: (() => void)[] = [];
- constructor() {
- }
doConnect() {
console.error(`\nConnecting to Mongo with URL : ${url}\n`);