From a73a72586c72cd620c16dd7bc0baad88c8e49a34 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 11 Oct 2019 01:38:48 -0400 Subject: switching search around to left-hand side. --- src/client/views/MainView.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ba4224875..1ec21f638 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -12,7 +12,7 @@ import { Id } from '../../new_fields/FieldSymbols'; import { InkTool } from '../../new_fields/InkField'; import { List } from '../../new_fields/List'; import { listSpec } from '../../new_fields/Schema'; -import { BoolCast, Cast, FieldValue, StrCast } from '../../new_fields/Types'; +import { BoolCast, Cast, FieldValue, StrCast, PromiseValue } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils'; @@ -463,7 +463,7 @@ export class MainView extends React.Component { return (null); } return : null, + //this.isSearchVisible ?
: null, ]; } @@ -648,7 +648,9 @@ export class MainView extends React.Component { @observable isSearchVisible = false; @action.bound toggleSearch = () => { - this.isSearchVisible = !this.isSearchVisible; + this.isSearchVisible = !MainView.Instance.isSearchVisible; + MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0; + PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0))); } @computed private get dictationOverlay() { -- cgit v1.2.3-70-g09d2 From 3afceef2f8c2be1bddf67cecd97086a41ec6dc48 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 11 Oct 2019 16:47:42 -0400 Subject: changes to menu layouts --- src/client/documents/Documents.ts | 2 + src/client/views/GlobalKeyHandler.ts | 30 +++++- src/client/views/Main.tsx | 5 - src/client/views/MainView.tsx | 108 +++++++++++++-------- .../collections/CollectionMasonryViewFieldRow.tsx | 2 +- .../CollectionStackingViewFieldColumn.tsx | 4 +- src/client/views/nodes/ButtonBox.scss | 2 + src/client/views/nodes/DragBox.tsx | 4 +- src/client/views/nodes/IconBox.tsx | 4 +- src/client/views/search/IconBar.tsx | 2 +- src/client/views/search/IconButton.scss | 2 +- .../authentication/models/current_user_utils.ts | 73 +++++++++++--- 12 files changed, 167 insertions(+), 71 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7f6ab50d8..6b56fb443 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -74,6 +74,7 @@ export interface DocumentOptions { dropAction?: dropActionType; backgroundLayout?: string; chromeStatus?: string; + columnWidth?: number; fontSize?: number; curPage?: number; currentTimecode?: number; @@ -83,6 +84,7 @@ export interface DocumentOptions { dockingConfig?: string; autoHeight?: boolean; dbDoc?: Doc; + icon?: string; // [key: string]: Opt; } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 557b3e366..9d239d0bf 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -9,6 +9,7 @@ import { DictationManager } from "../util/DictationManager"; import SharingManager from "../util/SharingManager"; import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; import { Cast, PromiseValue } from "../../new_fields/Types"; +import { ScriptField } from "../../new_fields/ScriptField"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -162,12 +163,31 @@ export default class KeyManager { } } break; + case "c": + if (MainView.Instance.flyoutWidth > 0) { + MainView.Instance.flyoutWidth = 0; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } else { + MainView.Instance.flyoutWidth = 400; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Create, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } + break; + case "l": + if (MainView.Instance.flyoutWidth > 0) { + MainView.Instance.flyoutWidth = 0; + } else { + MainView.Instance.flyoutWidth = 400; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } + break; case "f": - stopPropagation = false; - preventDefault = false; - MainView.Instance.isSearchVisible = !MainView.Instance.isSearchVisible; - MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0; - PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0))); + if (MainView.Instance.flyoutWidth > 0) { + MainView.Instance.flyoutWidth = 0; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } else { + MainView.Instance.flyoutWidth = 400; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } break; case "o": let target = SelectionManager.SelectedDocuments()[0]; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 3bd898ac0..a91a2b69e 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -38,11 +38,6 @@ let swapDocs = async () => { if (info.id !== "__guest__") { // a guest will not have an id registered await CurrentUserUtils.loadUserDocument(info); - // updates old user documents to prevent chrome on tree view. - (await Cast(CurrentUserUtils.UserDocument.workspaces, Doc))!.chromeStatus = "disabled"; - (await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))!.chromeStatus = "disabled"; - (await Cast(CurrentUserUtils.UserDocument.sidebar, Doc))!.chromeStatus = "disabled"; - CurrentUserUtils.UserDocument.chromeStatus = "disabled"; await swapDocs(); } document.getElementById('root')!.addEventListener('wheel', event => { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 1ec21f638..6f60de1c4 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -15,7 +15,7 @@ import { listSpec } from '../../new_fields/Schema'; import { BoolCast, Cast, FieldValue, StrCast, PromiseValue } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse, Utils } from '../../Utils'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; import { ClientUtils } from '../util/ClientUtils'; @@ -40,6 +40,8 @@ import { PreviewCursor } from './PreviewCursor'; import { FilterBox } from './search/FilterBox'; import { OverlayView } from './OverlayView'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; +import { CollectionStackingView } from './collections/CollectionStackingView'; +import { ScriptField } from '../../new_fields/ScriptField'; @observer export class MainView extends React.Component { @@ -459,33 +461,63 @@ export class MainView extends React.Component { @computed get flyout() { let sidebar: FieldResult; - if (!this.userDoc || !((sidebar = this.userDoc.sidebar) instanceof Doc)) { + if (!this.userDoc || !((sidebar = this.userDoc.sidebarContainer) instanceof Doc)) { return (null); } - return - ; + (Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc).columnWidth = this.flyoutWidthFunc() / 3 - 30; + return
+
+ + +
+
+ + +
; } @computed @@ -493,7 +525,7 @@ export class MainView extends React.Component { if (!this.userDoc) { return (
{this.dockingContent}
); } - let sidebar = this.userDoc.sidebar; + let sidebar = this.userDoc.sidebarContainer; if (!(sidebar instanceof Doc)) { return (null); } @@ -585,16 +617,16 @@ export class MainView extends React.Component { // let googlePhotosSearch = () => GooglePhotosClientUtils.CollectionFromSearch(Docs.Create.MasonryDocument, { included: [GooglePhotosClientUtils.ContentCategories.LANDSCAPES] }); let btns: [React.RefObject, IconName, string, () => Doc | Promise][] = [ - [React.createRef(), "object-group", "Add Collection", addColNode], - [React.createRef(), "tv", "Add Presentation Trail", addPresNode], - [React.createRef(), "globe-asia", "Add Website", addWebNode], - [React.createRef(), "bolt", "Add Button", addButtonDocument], - [React.createRef(), "file", "Add Document Dragger", addDragboxNode], + //[React.createRef(), "object-group", "Add Collection", addColNode], + //[React.createRef(), "tv", "Add Presentation Trail", addPresNode], + //[React.createRef(), "globe-asia", "Add Website", addWebNode], + //[React.createRef(), "bolt", "Add Button", addButtonDocument], + //[React.createRef(), "file", "Add Document Dragger", addDragboxNode], // [React.createRef(), "object-group", "Test Google Photos Search", googlePhotosSearch], - [React.createRef(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode + //[React.createRef(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode //[React.createRef(), "play", "Add Youtube Searcher", addYoutubeSearcher], ]; - if (!ClientUtils.RELEASE) btns.unshift([React.createRef(), "cat", "Add Cat Image", addImageNode]); + //if (!ClientUtils.RELEASE) btns.unshift([React.createRef(), "cat", "Add Cat Image", addImageNode]); return < div id="add-nodes-menu" style={{ left: (this.flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > @@ -603,7 +635,7 @@ export class MainView extends React.Component {
    -
  • + {/*
  • */}
  • {btns.map(btn => @@ -612,7 +644,7 @@ export class MainView extends React.Component {
)} -
  • + {/*
  • */}
  • */} -
  • -
  • - {btns.map(btn => -
  • - -
  • )} - {/*
  • */} -
  • -
  • -
  • -
  • -
  • -
  • -
  • - + {/*
  • */} + + + + {DocListCast(CurrentUserUtils.UserDocument.docButtons).map(doc =>
    + 35 / NumCast(doc.nativeWidth, 35)} + PanelWidth={() => 35} + PanelHeight={() => 35} + renderDepth={0} + focus={emptyFunction} + backgroundColor={returnEmptyString} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + zoomToScale={emptyFunction} + getScale={returnOne}> + +
    )} + {/*
  • */} + + + + + + + ; } @@ -668,16 +674,6 @@ export class MainView extends React.Component { this._colorPickerDisplay = close ? false : !this._colorPickerDisplay; } - /* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */ - @computed - get miscButtons() { - return [ - //this.isSearchVisible ?
    : null, - ]; - - } - - @observable isSearchVisible = false; @action.bound toggleSearch = () => { PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); @@ -716,7 +712,6 @@ export class MainView extends React.Component { {this.nodesMenu()} - {this.miscButtons} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 6f5587b5a..a325e86c6 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -188,7 +188,7 @@ class TreeView extends React.Component { 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 view7 - if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) { + if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking && 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, this.resolvedDataDoc, "inTab"), icon: "folder" }); ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "onRight"), icon: "caret-square-right" }); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.scss b/src/client/views/nodes/CollectionFreeFormDocumentView.scss index c0d9e1267..af9232c2f 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.scss +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.scss @@ -2,4 +2,6 @@ transform-origin: left top; position: absolute; background-color: transparent; + top:0; + left:0; } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 758222e52..20920a9b8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -614,6 +614,7 @@ export class DocumentView extends DocComponent(Docu DataDoc={this.props.DataDoc} />); } render() { + if (!this.props.Document) return (null); let animDims = this.props.Document.animateToDimensions ? Array.from(Cast(this.props.Document.animateToDimensions, listSpec("number"))!) : undefined; const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined; const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx index 8429382e3..ab3368b94 100644 --- a/src/client/views/nodes/DragBox.tsx +++ b/src/client/views/nodes/DragBox.tsx @@ -51,9 +51,15 @@ export class DragBox extends DocComponent(DragDocu const onDragStart = this.Document.onDragStart; e.stopPropagation(); e.preventDefault(); - let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; - let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); - DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY); + DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([this.props.Document]), e.clientX, e.clientY, { + finishDrag: (dropData) => { + let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; + let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); + dropData.droppedDocuments = [doc]; + }, + handlers: { dragComplete: emptyFunction }, + hideSource: false + }); } e.stopPropagation(); e.preventDefault(); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 02a82e0ed..63b412a23 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -93,7 +93,7 @@ export class PDFBox extends DocAnnotatableComponent if (e.key === "PageUp" || e.key === "ArrowUp" || e.key === "ArrowLeft") { this.backPage(); } - }) + }); @undoBatch @action diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index e1bb91838..7408fd92b 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -127,46 +127,38 @@ export class CurrentUserUtils { Search.targetContainer = doc.sidebarContainer; Search.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.searchBox"); - let createCollection = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Collection", icon: "folder" }); - let createWebPage = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Web Page", icon: "globe-asia" }); + let createCollection = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "folder" }); + let createWebPage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); createWebPage.onDragStart = ScriptField.MakeFunction('Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })'); - let createCatImage = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Image", icon: "cat" }); + let createCatImage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })'); - let createButton = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Button", icon: "bolt" }); + let createButton = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); createButton.onDragStart = ScriptField.MakeFunction('Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })'); - let createPresentation = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Presentation", icon: "tv" }); + let createPresentation = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); createPresentation.onDragStart = ScriptField.MakeFunction('Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })'); - let createFolderImport = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Import Folder", icon: "cloud-upload-alt" }); + let createFolderImport = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); const creators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, height: 50, columnWidth: 35, chromeStatus: "disabled", title: "buttons" }); Create.targetContainer = doc.sidebarContainer; Create.creators = creators; Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); - const buttons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "buttons" }); - buttons.sectionFilter = "title"; - buttons.boxShadow = "0 0"; - buttons.ignoreClick = true; - buttons.hideHeadings = true; - doc.libraryButtons = buttons; + const libraryButtons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "buttons" }); + libraryButtons.sectionFilter = "title"; + libraryButtons.boxShadow = "0 0"; + libraryButtons.ignoreClick = true; + libraryButtons.hideHeadings = true; + libraryButtons.backgroundColor = "lightgrey"; + doc.libraryButtons = libraryButtons; doc.Library = Library; doc.Create = Create; doc.Search = Search; - (Library.onClick as ScriptField).script.run({ this: Library }); - //(doc.sidebarContainer as Doc).proto = library; } - PromiseValue(Cast(doc.libraryButtons, Doc)).then(libraryButtons => { - if (libraryButtons) { - libraryButtons.backgroundColor = "lightgrey"; - } - }); - - PromiseValue(Cast(doc.sidebar, Doc)).then(sidebar => { - if (sidebar) { - sidebar.backgroundColor = "lightgrey"; - } - }); + PromiseValue(Cast(doc.libraryButtons, Doc)).then(libraryButtons => { }); + PromiseValue(Cast(doc.Library, Doc)).then(library => library && library.library && library.targetContainer && (library.onClick as ScriptField).script.run({ this: library })); + PromiseValue(Cast(doc.Create, Doc)).then(async create => create && create.creators && create.targetContainer); + PromiseValue(Cast(doc.Search, Doc)).then(async search => search && search.searchBox && search.targetContainer); if (doc.overlays === undefined) { const overlays = Docs.Create.FreeformDocument([], { title: "Overlays" }); @@ -178,8 +170,7 @@ export class CurrentUserUtils { PromiseValue(Cast(doc.overlays, Doc)).then(overlays => overlays && Doc.AddDocToList(overlays, "data", doc.linkFollowBox = Docs.Create.LinkFollowBoxDocument({ x: 250, y: 20, width: 500, height: 370, title: "Link Follower" }))); } - StrCast(doc.title).indexOf("@") !== -1 && (doc.title = (StrCast(doc.title).split("@")[0] + "'s Library").toUpperCase()); - StrCast(doc.title).indexOf("'s Library") !== -1 && (doc.title = StrCast(doc.title).toUpperCase()); + doc.title = "DOCUMENTS"; doc.backgroundColor = "#eeeeee"; doc.width = 100; doc.preventTreeViewOpen = true; -- cgit v1.2.3-70-g09d2 From 34a8b9dd402a247e7ad0a57115935b1e3a04a8d3 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 12:25:02 -0400 Subject: cleaned up notifs and bottom menu icons --- src/client/views/Main.scss | 21 +++----- src/client/views/MainView.tsx | 57 +++++++++------------- src/client/views/MainViewNotifs.scss | 18 +++++++ src/client/views/MainViewNotifs.tsx | 32 ++++++++++++ .../views/collections/CollectionTreeView.tsx | 26 +--------- .../authentication/models/current_user_utils.ts | 1 - 6 files changed, 79 insertions(+), 76 deletions(-) create mode 100644 src/client/views/MainViewNotifs.scss create mode 100644 src/client/views/MainViewNotifs.tsx (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 705da7b35..debb941c8 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -93,21 +93,6 @@ button:hover { right: 0px; } -.main-notifs-badge { - position: absolute; - top: -10px; - right: -10px; - color: white; - background: #f44b42; - font-weight: 300; - border-radius: 100%; - width: 25px; - height: 25px; - text-align: center; - padding-top: 4px; - font-size: 12px; -} - //toolbar stuff #toolbar { position: absolute; @@ -237,6 +222,12 @@ ul#add-options-list { padding: 0; } } +.mainView-logout { + position: absolute; + right: 0; + bottom: 0; + font-size: 8px; +} .mainView-libraryFlyout { height: 100%; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 1fa231659..e8ffa5987 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -16,7 +16,7 @@ import { ScriptField } from '../../new_fields/ScriptField'; import { BoolCast, Cast, FieldValue, PromiseValue, StrCast, NumCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils, returnFalse } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; @@ -40,6 +40,7 @@ import { OverlayView } from './OverlayView'; import PDFMenu from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; +import { MainViewNotifs } from './MainViewNotifs'; @observer export class MainView extends React.Component { @@ -47,6 +48,7 @@ export class MainView extends React.Component { @observable addMenuToggle = React.createRef(); @observable public pwidth: number = 0; @observable public pheight: number = 0; + private _buttonBarHeight = 85; private dropDisposer?: DragManager.DragDropDisposer; @observable private dictationState = DictationManager.placeholder; @@ -138,24 +140,6 @@ export class MainView extends React.Component { firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); window.removeEventListener("keydown", KeyManager.Instance.handle); window.addEventListener("keydown", KeyManager.Instance.handle); - - if (this.userDoc) { - reaction(() => { - let workspaces = this.userDoc.workspaces; - let recent = this.userDoc.recentlyClosed; - if (!(recent instanceof Doc)) return 0; - if (!(workspaces instanceof Doc)) return 0; - let workspacesDoc = workspaces; - let recentDoc = recent; - let libraryHeight = this.getPHeight() - workspacesDoc[HeightSym]() - recentDoc[HeightSym]() - 20 + this.userDoc[HeightSym]() * 0.00001; - return libraryHeight; - }, (libraryHeight: number) => { - if (libraryHeight && Math.abs(this.userDoc[HeightSym]() - libraryHeight) > 5) { - this.userDoc.height = libraryHeight; - } - (Cast(this.userDoc.recentlyClosed, Doc) as Doc).allowClear = true; - }, { fireImmediately: true }); - } } componentWillUnMount() { @@ -340,7 +324,7 @@ export class MainView extends React.Component { if (this.userDoc && (col = await Cast(this.userDoc.optionalRightCollection, Doc))) { const l = Cast(col.data, listSpec(Doc)); if (l) { - runInAction(() => CollectionTreeView.NotifsCol = col); + runInAction(() => MainViewNotifs.NotifsCol = col); } } }, 100); @@ -349,7 +333,7 @@ export class MainView extends React.Component { drop = action((e: Event, de: DragManager.DropEvent) => { (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc)); - }) + }); onDrop = (e: React.DragEvent) => { e.preventDefault(); @@ -368,6 +352,9 @@ export class MainView extends React.Component { getPHeight = () => { return this.pheight; } + getContentsHeight = () => { + return this.pheight - this._buttonBarHeight; + } @observable flyoutWidth: number = 250; @observable flyoutTranslate: boolean = true; @@ -465,12 +452,12 @@ export class MainView extends React.Component { if (!(sidebarContent instanceof Doc)) { return (null); } - (Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc).columnWidth = this.flyoutWidthFunc() / 3 - 30; - let buttonBarHeight = 85; + let libraryButtonDoc = Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc; + libraryButtonDoc.columnWidth = this.flyoutWidthFunc() / 3 - 30; return
    -
    +
    -
    +
    +
    ; } @computed get mainContent() { - if (!this.userDoc) { - return (
    {this.dockingContent}
    ); - } - let sidebar = this.userDoc.sidebarContainer; - if (!(sidebar instanceof Doc)) { + let sidebar = this.userDoc && this.userDoc.sidebarContainer; + if (!this.userDoc || !(sidebar instanceof Doc)) { return (null); } return ( @@ -617,6 +604,7 @@ export class MainView extends React.Component { return < div id="add-nodes-menu" style={{ left: (this.flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > + @@ -632,7 +620,7 @@ export class MainView extends React.Component { addDocument={undefined} addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} - removeDocument={undefined} + removeDocument={(doc: Doc) => Doc.RemoveDocFromList(CurrentUserUtils.UserDocument, "docButtons", doc)} ruleProvider={undefined} onClick={undefined} ScreenToLocalTransform={Transform.Identity} @@ -662,7 +650,6 @@ export class MainView extends React.Component { -
    ; } diff --git a/src/client/views/MainViewNotifs.scss b/src/client/views/MainViewNotifs.scss new file mode 100644 index 000000000..25ec95643 --- /dev/null +++ b/src/client/views/MainViewNotifs.scss @@ -0,0 +1,18 @@ +.mainNotifs-container { + position:absolute; + + .mainNotifs-badge { + position: absolute; + top: -10px; + right: -10px; + color: white; + background: #f44b42; + font-weight: 300; + border-radius: 100%; + width: 25px; + height: 25px; + text-align: center; + padding-top: 4px; + font-size: 12px; + } +} \ No newline at end of file diff --git a/src/client/views/MainViewNotifs.tsx b/src/client/views/MainViewNotifs.tsx new file mode 100644 index 000000000..09fa1cb0c --- /dev/null +++ b/src/client/views/MainViewNotifs.tsx @@ -0,0 +1,32 @@ +import { action, computed, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import "normalize.css"; +import * as React from 'react'; +import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; +import { emptyFunction } from '../../Utils'; +import { SetupDrag } from '../util/DragManager'; +import "./MainViewNotifs.scss"; +import { CollectionDockingView } from './collections/CollectionDockingView'; + + +@observer +export class MainViewNotifs extends React.Component { + + @observable static NotifsCol: Opt; + openNotifsCol = () => { + if (MainViewNotifs.NotifsCol) { + CollectionDockingView.AddRightSplit(MainViewNotifs.NotifsCol, undefined); + } + } + render() { + const length = MainViewNotifs.NotifsCol ? DocListCast(MainViewNotifs.NotifsCol.data).length : 0; + const notifsRef = React.createRef(); + const dragNotifs = action(() => MainViewNotifs.NotifsCol!); + return
    + +
    ; + } +} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a325e86c6..abaa9662c 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -517,8 +517,6 @@ export class CollectionTreeView extends CollectionSubView(Document) { private treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; - @observable static NotifsCol: Opt; - @computed get resolvedDataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; } protected createTreeDropTarget = (ele: HTMLDivElement) => { @@ -557,31 +555,10 @@ export class CollectionTreeView extends CollectionSubView(Document) { } outerXf = () => Utils.GetScreenTransform(this._mainEle!); onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {}); - openNotifsCol = () => { - if (CollectionTreeView.NotifsCol) { - this.props.addDocTab(CollectionTreeView.NotifsCol, undefined, "onRight"); - } - } - @computed get renderNotifsButton() { - const length = CollectionTreeView.NotifsCol ? DocListCast(CollectionTreeView.NotifsCol.data).length : 0; - const notifsRef = React.createRef(); - const dragNotifs = action(() => CollectionTreeView.NotifsCol!); - return
    -
    - -
    0 ? { "display": "initial" } : { "display": "none" }}> - {length} -
    -
    -
    ; - } @computed get renderClearButton() { return
    - @@ -614,7 +591,6 @@ export class CollectionTreeView extends CollectionSubView(Document) { TreeView.loadId = doc[Id]; Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true, false, false, false); })} /> - {this.props.Document.workspaceLibrary ? this.renderNotifsButton : (null)} {this.props.Document.allowClear ? this.renderClearButton : (null)}
      { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 7408fd92b..874f49f10 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -115,7 +115,6 @@ export class CurrentUserUtils { library.xMargin = 5; library.yMargin = 5; library.boxShadow = "1 1 3"; - library.workspaceLibrary = true; // flag that this is the document that shows the Notifications button when documents are shared Library.targetContainer = doc.sidebarContainer; Library.library = library; Library.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.library"); -- cgit v1.2.3-70-g09d2 From 8910a2649a1b2edea9843df1b780937ad0e69fb5 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 13:09:53 -0400 Subject: color picker as document in sidebar now. --- src/client/documents/DocumentTypes.ts | 1 + src/client/documents/Documents.ts | 10 ++++++++++ src/client/util/DocumentManager.ts | 6 ++---- src/client/views/GlobalKeyHandler.ts | 4 ++-- src/client/views/MainView.tsx | 7 +------ src/client/views/nodes/ColorBox.scss | 10 ++++++++++ src/client/views/nodes/ColorBox.tsx | 16 ++++++++++++++++ src/client/views/nodes/DocumentContentsView.tsx | 7 ++++++- src/client/views/nodes/QueryBox.tsx | 19 ++----------------- .../authentication/models/current_user_utils.ts | 4 +++- 10 files changed, 53 insertions(+), 31 deletions(-) create mode 100644 src/client/views/nodes/ColorBox.scss create mode 100644 src/client/views/nodes/ColorBox.tsx (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 7abaa4043..dad2de0b5 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -22,4 +22,5 @@ export enum DocumentType { LINKFOLLOW = "linkfollow", PRESELEMENT = "preselement", QUERY = "search", + COLOR = "color", } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6b56fb443..e783848ff 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -46,6 +46,7 @@ import { DocumentType } from "./DocumentTypes"; import { LinkFollowBox } from "../views/linking/LinkFollowBox"; import { PresElementBox } from "../views/presentationview/PresElementBox"; import { QueryBox } from "../views/nodes/QueryBox"; +import { ColorBox } from "../views/nodes/ColorBox"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -69,6 +70,7 @@ export interface DocumentOptions { templates?: List; viewType?: number; backgroundColor?: string; + ignoreClick?: boolean; opacity?: number; defaultBackgroundColor?: string; dropAction?: dropActionType; @@ -127,6 +129,10 @@ export namespace Docs { layout: { view: QueryBox }, options: { width: 400, fitWidth: true } }], + [DocumentType.COLOR, { + layout: { view: ColorBox }, + options: { nativeWidth: 220, nativeHeight: 300 } + }], [DocumentType.IMG, { layout: { view: ImageBox, ext: anno }, options: {} @@ -386,6 +392,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.QUERY), "", options); } + export function ColorDocument(options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.COLOR), "", options); + } + export function TextDocument(options: DocumentOptions = {}) { return InstanceFromProto(Prototypes.get(DocumentType.TEXT), "", options); } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 24285a70a..00de39671 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,16 +1,14 @@ -import { action, computed, observable, trace } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { Doc, DocListCastAsync } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; +import { List } from '../../new_fields/List'; import { Cast, NumCast, StrCast } from '../../new_fields/Types'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { CollectionView } from '../views/collections/CollectionView'; import { DocumentView } from '../views/nodes/DocumentView'; import { LinkManager } from './LinkManager'; -import { undoBatch, UndoManager } from './UndoManager'; import { Scripting } from './Scripting'; -import { List } from '../../new_fields/List'; import { SelectionManager } from './SelectionManager'; -import { notDeepEqual } from 'assert'; export class DocumentManager { diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 82f5a573c..f3e1933d7 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -165,10 +165,10 @@ export default class KeyManager { break; case "c": PromiseValue(Cast(CurrentUserUtils.UserDocument.Create, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); - if (MainView.Instance.flyoutWidth === 75) { + if (MainView.Instance.flyoutWidth === 240) { MainView.Instance.flyoutWidth = 0; } else { - MainView.Instance.flyoutWidth = 75; + MainView.Instance.flyoutWidth = 240; } break; case "l": diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e8ffa5987..cc412a609 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -5,7 +5,6 @@ import { action, computed, configure, observable, reaction, runInAction } from ' import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; -import { SketchPicker } from 'react-color'; import Measure from 'react-measure'; import { Doc, DocListCast, Field, FieldResult, HeightSym, Opt } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; @@ -640,11 +639,7 @@ export class MainView extends React.Component {
    )} {/*
  • */} - + diff --git a/src/client/views/nodes/ColorBox.scss b/src/client/views/nodes/ColorBox.scss new file mode 100644 index 000000000..8df617fca --- /dev/null +++ b/src/client/views/nodes/ColorBox.scss @@ -0,0 +1,10 @@ +.colorBox-container { + width:100%; + height:100%; + position: relative; + pointer-events:all; + + .sketch-picker { + margin:auto; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx new file mode 100644 index 000000000..4aff770f9 --- /dev/null +++ b/src/client/views/nodes/ColorBox.tsx @@ -0,0 +1,16 @@ +import React = require("react"); +import { observer } from "mobx-react"; +import { SketchPicker } from 'react-color'; +import { FieldView, FieldViewProps } from './FieldView'; +import "./ColorBox.scss"; +import { InkingControl } from "../InkingControl"; + +@observer +export class ColorBox extends React.Component { + public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(ColorBox, fieldKey); } + render() { + return
    + +
    ; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index d4e7c6d4e..f2a581c42 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -25,6 +25,7 @@ import { KeyValueBox } from "./KeyValueBox"; import { PDFBox } from "./PDFBox"; import { PresBox } from "./PresBox"; import { QueryBox } from "./QueryBox"; +import { ColorBox } from "./ColorBox"; import { PresElementBox } from "../presentationview/PresElementBox"; import { VideoBox } from "./VideoBox"; import { WebBox } from "./WebBox"; @@ -100,7 +101,11 @@ export class DocumentContentsView extends React.Component(), { width: 200, height: 500, title: "a presentation trail" })'); let createFolderImport = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); - const creators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, height: 50, columnWidth: 35, chromeStatus: "disabled", title: "buttons" }); + const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, chromeStatus: "disabled", title: "buttons" }); + const color = Docs.Create.ColorDocument({ title: "color picker", width: 400, ignoreClick: true }); + const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }) Create.targetContainer = doc.sidebarContainer; Create.creators = creators; Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); -- cgit v1.2.3-70-g09d2 From ed89b0fbf26c5bf4263198938dae07e6f32ab436 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 13:43:13 -0400 Subject: a few more tweaks and now the bottom buttons are customizable --- src/client/views/MainView.tsx | 11 ++++++++++- src/client/views/nodes/DragBox.tsx | 5 +++-- src/new_fields/Doc.ts | 1 + src/server/authentication/models/current_user_utils.ts | 4 ++-- 4 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cc412a609..18e5052b7 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -40,6 +40,7 @@ import PDFMenu from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; import { MainViewNotifs } from './MainViewNotifs'; +import { DocumentType } from '../documents/DocumentTypes'; @observer export class MainView extends React.Component { @@ -331,7 +332,15 @@ export class MainView extends React.Component { } drop = action((e: Event, de: DragManager.DropEvent) => { - (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc)); + (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => { + if (doc.type !== DocumentType.DRAGBOX) { + let dbox = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); + dbox.factory = doc; + dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.factory, true)'); + doc = dbox; + } + Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); + }); }); onDrop = (e: React.DragEvent) => { diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx index ab3368b94..4fca96382 100644 --- a/src/client/views/nodes/DragBox.tsx +++ b/src/client/views/nodes/DragBox.tsx @@ -44,7 +44,7 @@ export class DragBox extends DocComponent(DragDocu } } - onDragMove = (e: MouseEvent) => { + onDragMove = async (e: MouseEvent) => { if (!e.cancelBubble && (Math.abs(this._downX - e.clientX) > 5 || Math.abs(this._downY - e.clientY) > 5)) { document.removeEventListener("pointermove", this.onDragMove); document.removeEventListener("pointerup", this.onDragUp); @@ -52,7 +52,7 @@ export class DragBox extends DocComponent(DragDocu e.stopPropagation(); e.preventDefault(); DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([this.props.Document]), e.clientX, e.clientY, { - finishDrag: (dropData) => { + finishDrag: async (dropData) => { let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); dropData.droppedDocuments = [doc]; @@ -60,6 +60,7 @@ export class DragBox extends DocComponent(DragDocu handlers: { dragComplete: emptyFunction }, hideSource: false }); + await this.props.Document.factory; // if there's a factory Doc that is being copied, make sure it's not pending. } e.stopPropagation(); e.preventDefault(); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index eb752f8c6..66036f673 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -730,6 +730,7 @@ export namespace Doc { Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; }); Scripting.addGlobal(function getProto(doc: any) { return Doc.GetProto(doc); }); Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); }); +Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return Doc.MakeCopy(doc, copyProto); }); Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); }); Scripting.addGlobal(function aliasDocs(field: any) { return new List(field.map((d: any) => Doc.MakeAlias(d))); }); Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 09bab959d..9a7b6442b 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -130,7 +130,7 @@ export class CurrentUserUtils { let createWebPage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); createWebPage.onDragStart = ScriptField.MakeFunction('Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })'); let createCatImage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); - createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })'); + createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })'); let createButton = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); createButton.onDragStart = ScriptField.MakeFunction('Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })'); let createPresentation = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); @@ -139,7 +139,7 @@ export class CurrentUserUtils { createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, chromeStatus: "disabled", title: "buttons" }); const color = Docs.Create.ColorDocument({ title: "color picker", width: 400, ignoreClick: true }); - const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }) + const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }); Create.targetContainer = doc.sidebarContainer; Create.creators = creators; Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); -- cgit v1.2.3-70-g09d2 From 988822bdeeed82b0c1ef611f2f7a3111d029d564 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 19:37:06 -0400 Subject: a bunch of fixes to clean up drag box stuff. --- src/client/documents/DocumentTypes.ts | 2 +- src/client/documents/Documents.ts | 14 +- src/client/util/DragManager.ts | 19 +- src/client/views/GlobalKeyHandler.ts | 1 - src/client/views/Main.scss | 17 +- src/client/views/MainView.tsx | 250 ++++++++------------- src/client/views/nodes/ButtonBox.tsx | 3 +- src/client/views/nodes/DocumentContentsView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 27 ++- src/client/views/nodes/DragBox.scss | 13 -- src/client/views/nodes/DragBox.tsx | 115 ---------- src/client/views/nodes/FontIconBox.scss | 13 ++ src/client/views/nodes/FontIconBox.tsx | 21 ++ .../authentication/models/current_user_utils.ts | 29 ++- 14 files changed, 194 insertions(+), 334 deletions(-) delete mode 100644 src/client/views/nodes/DragBox.scss delete mode 100644 src/client/views/nodes/DragBox.tsx create mode 100644 src/client/views/nodes/FontIconBox.scss create mode 100644 src/client/views/nodes/FontIconBox.tsx (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index dad2de0b5..432e53825 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -17,7 +17,7 @@ export enum DocumentType { TEMPLATE = "template", EXTENSION = "extension", YOUTUBE = "youtube", - DRAGBOX = "dragbox", + FONTICONBOX = "fonticonbox", PRES = "presentation", LINKFOLLOW = "linkfollow", PRESELEMENT = "preselement", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e783848ff..1f89d2993 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -37,7 +37,7 @@ import { DocumentManager } from "../util/DocumentManager"; import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox"; import { Scripting, CompileScript } from "../util/Scripting"; import { ButtonBox } from "../views/nodes/ButtonBox"; -import { DragBox } from "../views/nodes/DragBox"; +import { FontIconBox } from "../views/nodes/FontIconBox"; import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; import { PresBox } from "../views/nodes/PresBox"; import { ComputedField } from "../../new_fields/ScriptField"; @@ -71,6 +71,7 @@ export interface DocumentOptions { viewType?: number; backgroundColor?: string; ignoreClick?: boolean; + lockedPosition?: boolean; opacity?: number; defaultBackgroundColor?: string; dropAction?: dropActionType; @@ -82,6 +83,7 @@ export interface DocumentOptions { currentTimecode?: number; documentText?: string; borderRounding?: string; + boxShadow?: string; schemaColumns?: List; dockingConfig?: string; autoHeight?: boolean; @@ -127,7 +129,7 @@ export namespace Docs { }], [DocumentType.QUERY, { layout: { view: QueryBox }, - options: { width: 400, fitWidth: true } + options: { width: 400 } }], [DocumentType.COLOR, { layout: { view: ColorBox }, @@ -183,8 +185,8 @@ export namespace Docs { layout: { view: PresBox }, options: {} }], - [DocumentType.DRAGBOX, { - layout: { view: DragBox }, + [DocumentType.FONTICONBOX, { + layout: { view: FontIconBox }, options: { width: 40, height: 40 }, }], [DocumentType.LINKFOLLOW, { @@ -476,8 +478,8 @@ export namespace Docs { } - export function DragboxDocument(options?: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.DRAGBOX), undefined, { ...(options || {}) }); + export function FontIconDocument(options?: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.FONTICONBOX), undefined, { ...(options || {}) }); } export function LinkFollowBoxDocument(options?: DocumentOptions) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 7259f66e3..2c316ccdf 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,6 +1,6 @@ import { action, runInAction } from "mobx"; import { Doc, Field } from "../../new_fields/Doc"; -import { Cast, StrCast } from "../../new_fields/Types"; +import { Cast, StrCast, ScriptCast } from "../../new_fields/Types"; import { URLField } from "../../new_fields/URLField"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; @@ -13,6 +13,7 @@ import { Docs } from "../documents/Documents"; import { ScriptField } from "../../new_fields/ScriptField"; import { List } from "../../new_fields/List"; import { PrefetchProxy } from "../../new_fields/Proxy"; +import { listSpec } from "../../new_fields/Schema"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag( @@ -207,7 +208,6 @@ export namespace DragManager { } draggedDocuments: Doc[]; droppedDocuments: Doc[]; - removeDropProperties: string[] = []; offset: number[]; dropAction: dropActionType; userDropAction: dropActionType; @@ -234,17 +234,18 @@ export namespace DragManager { export let StartDragFunctions: (() => void)[] = []; - export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + export async function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { runInAction(() => StartDragFunctions.map(func => func())); + await dragData.draggedDocuments.map(d => d.dragFactory); StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag : (dropData: { [id: string]: any }) => { - (dropData.droppedDocuments = dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? - dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) : - dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? - dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : - dragData.draggedDocuments + (dropData.droppedDocuments = + dragData.draggedDocuments.map(d => ScriptCast(d.onDragStart) ? ScriptCast(d.onDragStart).script.run({ this: d }).result : + dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? Doc.MakeAlias(d) : + dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? Doc.MakeCopy(d, true) : d) ); - dragData.removeDropProperties.map(prop => dropData.droppedDocuments.map((d: Doc) => d[prop] = undefined)); + dropData.droppedDocuments.forEach((drop: Doc, i: number) => + Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []).map(prop => drop[prop] = undefined)); }); } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index f3e1933d7..38fce4cf7 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -73,7 +73,6 @@ export default class KeyManager { SelectionManager.DeselectAll(); } } - main.toggleColorPicker(true); SelectionManager.DeselectAll(); DictationManager.Controls.stop(); SharingManager.Instance.close(); diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index debb941c8..55195b616 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -185,7 +185,22 @@ button:hover { overflow: auto; z-index: 1; } - +.mainContent { + width:100%; + height:100%; + position:absolute; +} +.mainView-flyoutContainer{ + display:flex; + flex-direction: column; + position: absolute; + width:100%; + height:100%; + border: black 1px solid; + .documentView-node-topmost { + background: lightgrey; + } +} #mainContent-div { width: 100%; height: 100%; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 18e5052b7..aac4af9f6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,4 +1,4 @@ -import { IconName, library } from '@fortawesome/fontawesome-svg-core'; +import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faChevronRight, faClone, faCloudUploadAlt, faCommentAlt, faCut, faEllipsisV, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faPenNib, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faTv, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; @@ -6,60 +6,74 @@ import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; import Measure from 'react-measure'; -import { Doc, DocListCast, Field, FieldResult, HeightSym, Opt } from '../../new_fields/Doc'; +import { Doc, DocListCast, Field, FieldResult, Opt } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; import { InkTool } from '../../new_fields/InkField'; import { List } from '../../new_fields/List'; +import { ObjectField } from '../../new_fields/ObjectField'; import { listSpec } from '../../new_fields/Schema'; import { ScriptField } from '../../new_fields/ScriptField'; -import { BoolCast, Cast, FieldValue, PromiseValue, StrCast, NumCast } from '../../new_fields/Types'; +import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils, returnFalse } from '../../Utils'; +import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; import { DictationManager } from '../util/DictationManager'; -import { SetupDrag, DragManager } from '../util/DragManager'; +import { DragManager } from '../util/DragManager'; import { HistoryUtil } from '../util/History'; import SharingManager from '../util/SharingManager'; import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; import { CollectionBaseView, CollectionViewType } from './collections/CollectionBaseView'; import { CollectionDockingView } from './collections/CollectionDockingView'; -import { CollectionTreeView } from './collections/CollectionTreeView'; import { ContextMenu } from './ContextMenu'; import { DocumentDecorations } from './DocumentDecorations'; import KeyManager from './GlobalKeyHandler'; import { InkingControl } from './InkingControl'; import "./Main.scss"; import MainViewModal from './MainViewModal'; +import { MainViewNotifs } from './MainViewNotifs'; import { DocumentView } from './nodes/DocumentView'; import { OverlayView } from './OverlayView'; import PDFMenu from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; -import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; -import { MainViewNotifs } from './MainViewNotifs'; -import { DocumentType } from '../documents/DocumentTypes'; @observer export class MainView extends React.Component { public static Instance: MainView; - @observable addMenuToggle = React.createRef(); - @observable public pwidth: number = 0; - @observable public pheight: number = 0; - private _buttonBarHeight = 85; - private dropDisposer?: DragManager.DragDropDisposer; - - @observable private dictationState = DictationManager.placeholder; - @observable private dictationSuccessState: boolean | undefined = undefined; - @observable private dictationDisplayState = false; - @observable private dictationListeningState: DictationManager.Controls.ListeningUIStatus = false; + private _buttonBarHeight = 75; + private _flyoutSizeOnDown = 0; + private _urlState: HistoryUtil.DocUrl; + private _dropDisposer?: DragManager.DragDropDisposer; + + @observable private _dictationState = DictationManager.placeholder; + @observable private _dictationSuccessState: boolean | undefined = undefined; + @observable private _dictationDisplayState = false; + @observable private _dictationListeningState: DictationManager.Controls.ListeningUIStatus = false; + + @observable private _panelWidth: number = 0; + @observable private _panelHeight: number = 0; + @observable private _flyoutTranslate: boolean = true; + @observable public addMenuToggle = React.createRef(); + @observable public flyoutWidth: number = 250; public hasActiveModal = false; - + public isPointerDown = false; public overlayTimeout: NodeJS.Timeout | undefined; + private set mainContainer(doc: Opt) { + if (doc) { + !("presentationView" in doc) && (doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })])); + this.userDoc ? (this.userDoc.activeWorkspace = doc) : (CurrentUserUtils.GuestWorkspace = doc); + } + } + + @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; } + @computed private get userDoc() { return CurrentUserUtils.UserDocument; } + @computed public get mainFreeform(): Opt { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } + public initiateDictationFade = () => { let duration = DictationManager.Commands.dictationFadeDuration; this.overlayTimeout = setTimeout(() => { @@ -69,13 +83,6 @@ export class MainView extends React.Component { setTimeout(() => this.dictatedPhrase = DictationManager.placeholder, 500); }, duration); } - - private urlState: HistoryUtil.DocUrl; - - @computed private get userDoc() { - return CurrentUserUtils.UserDocument; - } - public cancelDictationFade = () => { if (this.overlayTimeout) { clearTimeout(this.overlayTimeout); @@ -83,54 +90,15 @@ export class MainView extends React.Component { } } - @computed private get mainContainer(): Opt { - return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; - } - @computed get mainFreeform(): Opt { - let docs = DocListCast(this.mainContainer!.data); - return (docs && docs.length > 1) ? docs[1] : undefined; - } - public isPointerDown = false; - private set mainContainer(doc: Opt) { - if (doc) { - if (!("presentationView" in doc)) { - doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })]); - } - this.userDoc ? (this.userDoc.activeWorkspace = doc) : (CurrentUserUtils.GuestWorkspace = doc); - } - } - - @computed public get dictatedPhrase() { - return this.dictationState; - } - - public set dictatedPhrase(value: string) { - runInAction(() => this.dictationState = value); - } - - @computed public get dictationSuccess() { - return this.dictationSuccessState; - } - - public set dictationSuccess(value: boolean | undefined) { - runInAction(() => this.dictationSuccessState = value); - } - - @computed public get dictationOverlayVisible() { - return this.dictationDisplayState; - } + @computed public get dictatedPhrase() { return this._dictationState; } + @computed public get dictationSuccess() { return this._dictationSuccessState; } + @computed public get dictationOverlayVisible() { return this._dictationDisplayState; } + @computed public get isListening() { return this._dictationListeningState; } - public set dictationOverlayVisible(value: boolean) { - runInAction(() => this.dictationDisplayState = value); - } - - @computed public get isListening() { - return this.dictationListeningState; - } - - public set isListening(value: DictationManager.Controls.ListeningUIStatus) { - runInAction(() => this.dictationListeningState = value); - } + public set dictatedPhrase(value: string) { runInAction(() => this._dictationState = value); } + public set dictationSuccess(value: boolean | undefined) { runInAction(() => this._dictationSuccessState = value); } + public set dictationOverlayVisible(value: boolean) { runInAction(() => this._dictationDisplayState = value); } + public set isListening(value: DictationManager.Controls.ListeningUIStatus) { runInAction(() => this._dictationListeningState = value); } componentWillMount() { var tag = document.createElement('script'); @@ -147,13 +115,13 @@ export class MainView extends React.Component { //close presentation window.removeEventListener("pointerdown", this.globalPointerDown); window.removeEventListener("pointerup", this.globalPointerUp); - this.dropDisposer && this.dropDisposer(); + this._dropDisposer && this._dropDisposer(); } constructor(props: Readonly<{}>) { super(props); MainView.Instance = this; - this.urlState = HistoryUtil.parseUrl(window.location) || {} as any; + this._urlState = HistoryUtil.parseUrl(window.location) || {} as any; // causes errors to be generated when modifying an observable outside of an action configure({ enforceActions: "observed" }); if (window.location.pathname !== RouteStore.home) { @@ -233,7 +201,7 @@ export class MainView extends React.Component { { fireImmediately: true } ); } else { - if (received && this.urlState.sharing) { + if (received && this._urlState.sharing) { reaction( () => { let docking = CollectionDockingView.Instance; @@ -264,8 +232,8 @@ export class MainView extends React.Component { let freeformOptions: DocumentOptions = { x: 0, y: 400, - width: this.pwidth * .7, - height: this.pheight, + width: this._panelWidth * .7, + height: this._panelHeight, title: "My Blank Collection" }; let workspaces: FieldResult; @@ -293,7 +261,7 @@ export class MainView extends React.Component { openWorkspace = async (doc: Doc, fromHistory = false) => { CurrentUserUtils.MainDocId = doc[Id]; this.mainContainer = doc; - let state = this.urlState; + let state = this._urlState; if (state.sharing === true && !this.userDoc) { DocServer.Control.makeReadOnly(); } else { @@ -318,25 +286,21 @@ export class MainView extends React.Component { DocServer.Control.makeEditable(); } } - let col: Opt; // 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 () => { - if (this.userDoc && (col = await Cast(this.userDoc.optionalRightCollection, Doc))) { - const l = Cast(col.data, listSpec(Doc)); - if (l) { - runInAction(() => MainViewNotifs.NotifsCol = col); - } - } + const col = this.userDoc && await Cast(this.userDoc.optionalRightCollection, Doc); + col && Cast(col.data, listSpec(Doc)) && runInAction(() => MainViewNotifs.NotifsCol = col); }, 100); return true; } drop = action((e: Event, de: DragManager.DropEvent) => { (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => { - if (doc.type !== DocumentType.DRAGBOX) { - let dbox = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); - dbox.factory = doc; - dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.factory, true)'); + if (!doc.onDragStart) { + let dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); + dbox.dragFactory = doc; + dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; + dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); doc = dbox; } Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); @@ -351,30 +315,22 @@ export class MainView extends React.Component { @action onResize = (r: any) => { - this.pwidth = r.offset.width; - this.pheight = r.offset.height; - } - getPWidth = () => { - return this.pwidth; - } - getPHeight = () => { - return this.pheight; - } - getContentsHeight = () => { - return this.pheight - this._buttonBarHeight; + this._panelWidth = r.offset.width; + this._panelHeight = r.offset.height; } + getPWidth = () => this._panelWidth; + getPHeight = () => this._panelHeight; + getContentsHeight = () => this._panelHeight - this._buttonBarHeight; - @observable flyoutWidth: number = 250; - @observable flyoutTranslate: boolean = true; @computed get dockingContent() { - let flyoutWidth = this.flyoutWidth; - let countWidth = this.flyoutTranslate; - let mainCont = this.mainContainer; return {({ measureRef }) => -
    - {!mainCont ? (null) : - + {!this.mainContainer ? (null) : + ; } - _downsize = 0; onPointerDown = (e: React.PointerEvent) => { - this._downsize = e.clientX; + this._flyoutSizeOnDown = e.clientX; document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -417,15 +372,15 @@ export class MainView extends React.Component { pointerOverDragger = () => { if (this.flyoutWidth === 0) { this.flyoutWidth = 250; - this.flyoutTranslate = false; + this._flyoutTranslate = false; } } @action pointerLeaveDragger = () => { - if (!this.flyoutTranslate) { + if (!this._flyoutTranslate) { this.flyoutWidth = 0; - this.flyoutTranslate = true; + this._flyoutTranslate = true; } } @@ -435,7 +390,7 @@ export class MainView extends React.Component { } @action onPointerUp = (e: PointerEvent) => { - if (Math.abs(e.clientX - this._downsize) < 4) { + if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4) { if (this.flyoutWidth < 5) this.flyoutWidth = 250; else this.flyoutWidth = 0; } @@ -461,8 +416,8 @@ export class MainView extends React.Component { return (null); } let libraryButtonDoc = Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc; - libraryButtonDoc.columnWidth = this.flyoutWidthFunc() / 3 - 30; - return
    + libraryButtonDoc.columnWidth = this.flyoutWidth / 3 - 30; + return
    + const sidebar = this.userDoc && this.userDoc.sidebarContainer; + return !this.userDoc || !(sidebar instanceof Doc) ? (null) : ( +
    {this.flyout} {this.expandButton} @@ -556,10 +508,10 @@ export class MainView extends React.Component { } @computed get expandButton() { - return !this.flyoutTranslate ? (
    { + return !this._flyoutTranslate ? (
    { runInAction(() => { this.flyoutWidth = 250; - this.flyoutTranslate = true; + this._flyoutTranslate = true; }); }}>
    ) : (null); } @@ -572,14 +524,6 @@ export class MainView extends React.Component { return { fontSize: "50%" }; } - onColorClick = (e: React.MouseEvent) => { - let target = (e.nativeEvent as any).path[0]; - let parent = (e.nativeEvent as any).path[1]; - if (target.localName === "input" || parent.localName === "span") { - e.stopPropagation(); - } - } - setWriteMode = (mode: DocServer.WriteMode) => { console.log(DocServer.WriteMode[mode]); const mode1 = mode; @@ -596,13 +540,12 @@ export class MainView extends React.Component { } protected createDropTarget = (ele: HTMLLabelElement) => { //used for stacking and masonry view - this.dropDisposer && this.dropDisposer(); + this._dropDisposer && this._dropDisposer(); if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); } } - @observable private _colorPickerDisplay = false; /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */ nodesMenu() { // let youtubeurl = "https://www.youtube.com/embed/TqcApsGRzWw"; @@ -610,14 +553,13 @@ export class MainView extends React.Component { // let googlePhotosSearch = () => GooglePhotosClientUtils.CollectionFromSearch(Docs.Create.MasonryDocument, { included: [GooglePhotosClientUtils.ContentCategories.LANDSCAPES] }); - return < div id="add-nodes-menu" style={{ left: (this.flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > + return < div id="add-nodes-menu" style={{ left: (this._flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > - +
    - {/*
  • */} @@ -658,18 +600,6 @@ export class MainView extends React.Component {
    ; } - - - @action - toggleColorPicker = (close = false) => { - this._colorPickerDisplay = close ? false : !this._colorPickerDisplay; - } - - @action.bound - toggleSearch = () => { - PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); - } - @computed private get dictationOverlay() { let success = this.dictationSuccess; let result = this.isListening && !this.isListening.interim ? DictationManager.placeholder : `"${this.dictatedPhrase}"`; diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index f08ea4891..3cf8c3eb3 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -70,7 +70,8 @@ export class ButtonBox extends DocComponent(Butt let missingParams = params && params.filter(p => this.props.Document[p] === undefined); params && params.map(p => DocListCast(this.props.Document[p])); // bcz: really hacky form of prefetching ... return ( -
    +
    {(this.Document.text || this.Document.title)} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index f2a581c42..19ffdf0cd 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -16,7 +16,7 @@ import { AudioBox } from "./AudioBox"; import { ButtonBox } from "./ButtonBox"; import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; -import { DragBox } from "./DragBox"; +import { FontIconBox } from "./FontIconBox"; import { FieldView, FieldViewProps } from "./FieldView"; import { FormattedTextBox } from "./FormattedTextBox"; import { IconBox } from "./IconBox"; @@ -102,7 +102,7 @@ export class DocumentContentsView extends React.Component(Docu if (this._mainCont.current) { let dragData = new DragManager.DocumentDragData([this.props.Document]); const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0); - dragData.offset = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); + dragData.offset = this.Document.onDragStart ? [0, 0] : this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); dragData.dropAction = dropAction; - dragData.moveDocument = this.props.moveDocument; + dragData.moveDocument = this.Document.onDragStart ? undefined : this.props.moveDocument; dragData.applyAsTemplate = applyAsTemplate; - dragData.removeDropProperties = this.Document.removeDropProperties || []; DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { handlers: { dragComplete: action((emptyFunction)) }, - hideSource: !dropAction + hideSource: !dropAction && !this.Document.onDragStart }); } } @@ -246,7 +247,7 @@ export class DocumentView extends DocComponent(Docu this._hitTemplateDrag = true; } } - if (this.active && e.button === 0 && !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); + if ((this.active || this.Document.onDragStart) && e.button === 0 && !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); document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -258,9 +259,9 @@ export class DocumentView extends DocComponent(Docu if (e.cancelBubble && this.active) { document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView) } - else if (!e.cancelBubble && (SelectionManager.IsSelected(this) || this.props.parentActive()) && !this.Document.lockedPosition && !this.Document.inOverlay) { + else if (!e.cancelBubble && (SelectionManager.IsSelected(this) || this.props.parentActive() || this.Document.onDragStart) && !this.Document.lockedPosition && !this.Document.inOverlay) { if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - if (!e.altKey && !this.topMost && e.buttons === 1) { + if (!e.altKey && (!this.topMost || this.Document.onDragStart) && e.buttons === 1) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); @@ -475,6 +476,12 @@ export class DocumentView extends DocComponent(Docu }); !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); + let funcs: ContextMenuProps[] = []; + funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); + funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); + funcs.push({ description: "Drag Document", icon: "edit", event: () => this.Document.onDragStart = undefined }); + ContextMenu.Instance.addItem({ description: "OnDrag...", subitems: funcs, icon: "asterisk" }); + let existing = ContextMenu.Instance.findByDescription("Layout..."); let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; layoutItems.push({ description: this.Document.isBackground ? "As Foreground" : "As Background", event: this.makeBackground, icon: this.Document.lockedPosition ? "unlock" : "lock" }); @@ -627,8 +634,8 @@ export class DocumentView extends DocComponent(Docu this.props.backgroundColor(this.Document) || StrCast(this.layoutDoc.backgroundColor) : ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.Document); - const nativeWidth = this.props.Document.fitWidth ? this.props.PanelWidth() : this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%"; - const nativeHeight = this.props.Document.fitWidth ? this.props.PanelHeight() : this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; + const nativeWidth = this.props.Document.fitWidth ? this.props.PanelWidth() - 2 : this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%"; + const nativeHeight = this.props.Document.fitWidth ? this.props.PanelHeight() - 2 : this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined; const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.getLayoutPropStr("showTitle"); const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.getLayoutPropStr("showCaption"); diff --git a/src/client/views/nodes/DragBox.scss b/src/client/views/nodes/DragBox.scss deleted file mode 100644 index fbb9b9c1c..000000000 --- a/src/client/views/nodes/DragBox.scss +++ /dev/null @@ -1,13 +0,0 @@ -.dragBox-outerDiv { - width: 100%; - height: 100%; - pointer-events: all; - border-radius: inherit; - background: black; - border-radius: 100%; - svg { - margin:18%; - width:65% !important; - height:65%; - } -} diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx deleted file mode 100644 index 1fd6cb5a5..000000000 --- a/src/client/views/nodes/DragBox.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit } from '@fortawesome/free-regular-svg-icons'; -import { observer } from 'mobx-react'; -import * as React from 'react'; -import { Doc } from '../../../new_fields/Doc'; -import { createSchema, makeInterface, listSpec } from '../../../new_fields/Schema'; -import { ScriptField } from '../../../new_fields/ScriptField'; -import { emptyFunction } from '../../../Utils'; -import { CompileScript } from '../../util/Scripting'; -import { ContextMenu } from '../ContextMenu'; -import { DocComponent } from '../DocComponent'; -import { OverlayView } from '../OverlayView'; -import { ScriptBox } from '../ScriptBox'; -import { DocumentIconContainer } from './DocumentIcon'; -import './DragBox.scss'; -import { FieldView, FieldViewProps } from './FieldView'; -import { DragManager } from '../../util/DragManager'; -import { Docs } from '../../documents/Documents'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Cast } from '../../../new_fields/Types'; -import { ContextMenuProps } from '../ContextMenuItem'; - -library.add(faEdit as any); - -const DragSchema = createSchema({ - onDragStart: ScriptField, - text: "string" -}); - -type DragDocument = makeInterface<[typeof DragSchema]>; -const DragDocument = makeInterface(DragSchema); -@observer -export class DragBox extends DocComponent(DragDocument) { - _downX: number = 0; - _downY: number = 0; - public static LayoutString() { return FieldView.LayoutString(DragBox); } - _mainCont = React.createRef(); - onDragStart = (e: React.PointerEvent) => { - if (!e.ctrlKey && !e.altKey && !e.shiftKey && !this.props.isSelected() && e.button === 0) { - document.removeEventListener("pointermove", this.onDragMove); - document.addEventListener("pointermove", this.onDragMove); - document.removeEventListener("pointerup", this.onDragUp); - document.addEventListener("pointerup", this.onDragUp); - e.stopPropagation(); - e.preventDefault(); - } - } - - onDragMove = async (e: MouseEvent) => { - if (!e.cancelBubble && (Math.abs(this._downX - e.clientX) > 5 || Math.abs(this._downY - e.clientY) > 5)) { - document.removeEventListener("pointermove", this.onDragMove); - document.removeEventListener("pointerup", this.onDragUp); - const onDragStart = this.Document.onDragStart; - e.stopPropagation(); - e.preventDefault(); - let dragData = new DragManager.DocumentDragData([this.props.Document]); - const factory = await Cast(this.props.Document.factory, Doc);// if there's a factory Doc that is being copied, make sure it's not pending. - dragData.removeDropProperties = factory ? Cast(factory.removeDropProperties, listSpec("string"), []) : []; - DragManager.StartDocumentDrag([this._mainCont.current!], dragData, e.clientX, e.clientY, { - finishDrag: async (dropData) => { - let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; - let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); - dropData.droppedDocuments = [doc]; - dragData.removeDropProperties.map(prop => dropData.droppedDocuments.map((d: Doc) => d[prop] = undefined)); - }, - handlers: { dragComplete: emptyFunction }, - hideSource: false - }); - } - e.stopPropagation(); - e.preventDefault(); - } - - onDragUp = (e: MouseEvent) => { - document.removeEventListener("pointermove", this.onDragMove); - document.removeEventListener("pointerup", this.onDragUp); - } - - onContextMenu = () => { - let funcs: ContextMenuProps[] = []; - funcs.push({ description: "Set Make Aliases", icon: "edit", event: () => this.props.Document.factory && (this.props.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.factory)')) }); - funcs.push({ description: "Set Make Copies", icon: "edit", event: () => this.props.Document.factory && (this.props.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.factory, true)')) }); - funcs.push({ - description: "Edit OnClick script", icon: "edit", event: () => { - let overlayDisposer: () => void = emptyFunction; - const script = this.Document.onDragStart; - let originalText: string | undefined = undefined; - if (script) originalText = script.script.originalScript; - // tslint:disable-next-line: no-unnecessary-callback-wrapper - let scriptingBox = overlayDisposer()} onSave={(text, onError) => { - const script = CompileScript(text, { - params: { this: Doc.name }, - typecheck: false, - editable: true, - transformer: DocumentIconContainer.getTransformer() - }); - if (!script.compiled) { - onError(script.errors.map(error => error.messageText).join("\n")); - return; - } - this.Document.onClick = new ScriptField(script); - overlayDisposer(); - }} showDocumentIcons />; - overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${this.Document.title || ""} OnDragStart` }); - } - }); - ContextMenu.Instance.addItem({ description: "DragBox Funcs...", subitems: funcs, icon: "asterisk" }); - } - - render() { - return (
    - -
    ); - } -} \ No newline at end of file diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss new file mode 100644 index 000000000..75d093fcb --- /dev/null +++ b/src/client/views/nodes/FontIconBox.scss @@ -0,0 +1,13 @@ +.fontIconBox-outerDiv { + width: 100%; + height: 100%; + pointer-events: all; + border-radius: inherit; + background: black; + border-radius: 100%; + svg { + margin:18%; + width:65% !important; + height:65%; + } +} diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx new file mode 100644 index 000000000..3b580d851 --- /dev/null +++ b/src/client/views/nodes/FontIconBox.tsx @@ -0,0 +1,21 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { createSchema, makeInterface } from '../../../new_fields/Schema'; +import { DocComponent } from '../DocComponent'; +import './FontIconBox.scss'; +import { FieldView, FieldViewProps } from './FieldView'; +const FontIconSchema = createSchema({ + icon: "string" +}); + +type FontIconDocument = makeInterface<[typeof FontIconSchema]>; +const FontIconDocument = makeInterface(FontIconSchema); +@observer +export class FontIconBox extends DocComponent(FontIconDocument) { + public static LayoutString() { return FieldView.LayoutString(FontIconBox); } + + render() { + return
    ; + } +} \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 74a41d8cf..9f9f79dc4 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -99,9 +99,9 @@ export class CurrentUserUtils { } if (doc.Library === undefined) { - let Search = Docs.Create.ButtonDocument({ width: 50, height: 35, title: "Search" }); - let Library = Docs.Create.ButtonDocument({ width: 50, height: 35, title: "Library" }); - let Create = Docs.Create.ButtonDocument({ width: 35, height: 35, title: "Create" }); + let Search = Docs.Create.ButtonDocument({ width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Search" }); + let Library = Docs.Create.ButtonDocument({ width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Library" }); + let Create = Docs.Create.ButtonDocument({ width: 35, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Create" }); if (doc.sidebarContainer === undefined) { doc.sidebarContainer = new Doc(); (doc.sidebarContainer as Doc).chromeStatus = "disabled"; @@ -114,40 +114,39 @@ export class CurrentUserUtils { library.xMargin = 5; library.yMargin = 5; library.dropAction = "alias"; - library.boxShadow = "1 1 3"; Library.targetContainer = doc.sidebarContainer; Library.library = library; Library.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.library"); - const searchBox = Docs.Create.QueryDocument({ title: "Searching" }); - searchBox.boxShadow = "0 0"; + const searchBox = Docs.Create.QueryDocument({ title: "search stack" }); searchBox.ignoreClick = true; Search.searchBox = searchBox; Search.targetContainer = doc.sidebarContainer; Search.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.searchBox"); - let createCollection = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "folder" }); - let createWebPage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); + let createCollection = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "folder" }); + createCollection.onDragStart = ScriptField.MakeFunction('Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })'); + let createWebPage = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); createWebPage.onDragStart = ScriptField.MakeFunction('Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })'); - let createCatImage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); + let createCatImage = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })'); - let createButton = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); + let createButton = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); createButton.onDragStart = ScriptField.MakeFunction('Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })'); - let createPresentation = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); + let createPresentation = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); createPresentation.onDragStart = ScriptField.MakeFunction('Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })'); - let createFolderImport = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); + let createFolderImport = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); - const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, chromeStatus: "disabled", title: "buttons" }); + const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons" }); const color = Docs.Create.ColorDocument({ title: "color picker", width: 400 }); color.dropAction = "alias"; color.ignoreClick = true; color.removeDropProperties = new List(["dropAction", "ignoreClick"]); - const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }); + const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "creator stack" }); Create.targetContainer = doc.sidebarContainer; Create.creators = creators; Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); - const libraryButtons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "buttons" }); + const libraryButtons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "library stack" }); libraryButtons.sectionFilter = "title"; libraryButtons.boxShadow = "0 0"; libraryButtons.ignoreClick = true; -- cgit v1.2.3-70-g09d2 From f709ba0ba84ed057d06f9e9ab8a9315388e73c7e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 13 Oct 2019 00:01:49 -0400 Subject: cleaning up MainView --- src/client/util/DictationManager.ts | 21 ++- src/client/util/SharingManager.tsx | 5 +- src/client/views/CollectionLinearView.scss | 74 ++++++++ src/client/views/CollectionLinearView.tsx | 106 ++++++++++++ src/client/views/DictationOverlay.tsx | 71 ++++++++ src/client/views/GlobalKeyHandler.ts | 8 +- src/client/views/InkingControl.tsx | 5 +- src/client/views/Main.scss | 219 ----------------------- src/client/views/MainView.scss | 97 +++++++++++ src/client/views/MainView.tsx | 268 +++++------------------------ src/client/views/nodes/DocumentView.tsx | 9 +- src/client/views/nodes/ImageBox.scss | 4 + 12 files changed, 421 insertions(+), 466 deletions(-) create mode 100644 src/client/views/CollectionLinearView.scss create mode 100644 src/client/views/CollectionLinearView.tsx create mode 100644 src/client/views/DictationOverlay.tsx create mode 100644 src/client/views/MainView.scss (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 3b2307073..182cfb70a 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -14,6 +14,7 @@ import { HistogramField } from "../northstar/dash-fields/HistogramField"; import { MainView } from "../views/MainView"; import { Utils } from "../../Utils"; import { RichTextField } from "../../new_fields/RichTextField"; +import { DictationOverlay } from "../views/DictationOverlay"; /** * This namespace provides a singleton instance of a manager that @@ -88,12 +89,11 @@ export namespace DictationManager { export const listen = async (options?: Partial) => { let results: string | undefined; - let main = MainView.Instance; let overlay = options !== undefined && options.useOverlay; if (overlay) { - main.dictationOverlayVisible = true; - main.isListening = { interim: false }; + DictationOverlay.Instance.dictationOverlayVisible = true; + DictationOverlay.Instance.isListening = { interim: false }; } try { @@ -101,21 +101,21 @@ export namespace DictationManager { if (results) { Utils.CopyText(results); if (overlay) { - main.isListening = false; + DictationOverlay.Instance.isListening = false; let execute = options && options.tryExecute; - main.dictatedPhrase = execute ? results.toLowerCase() : results; - main.dictationSuccess = execute ? await DictationManager.Commands.execute(results) : true; + DictationOverlay.Instance.dictatedPhrase = execute ? results.toLowerCase() : results; + DictationOverlay.Instance.dictationSuccess = execute ? await DictationManager.Commands.execute(results) : true; } options && options.tryExecute && await DictationManager.Commands.execute(results); } } catch (e) { if (overlay) { - main.isListening = false; - main.dictatedPhrase = results = `dictation error: ${"error" in e ? e.error : "unknown error"}`; - main.dictationSuccess = false; + DictationOverlay.Instance.isListening = false; + DictationOverlay.Instance.dictatedPhrase = results = `dictation error: ${"error" in e ? e.error : "unknown error"}`; + DictationOverlay.Instance.dictationSuccess = false; } } finally { - overlay && main.initiateDictationFade(); + overlay && DictationOverlay.Instance.initiateDictationFade(); } return results; @@ -146,7 +146,6 @@ export namespace DictationManager { recognizer.start(); return new Promise((resolve, reject) => { - recognizer.onerror = (e: SpeechRecognitionError) => { if (!(indefinite && e.error === "no-speech")) { recognizer.stop(); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index d37cd1b80..2082d6324 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -18,6 +18,7 @@ import { DocumentView } from "../views/nodes/DocumentView"; import { SelectionManager } from "./SelectionManager"; import { DocumentManager } from "./DocumentManager"; import { CollectionView } from "../views/collections/CollectionView"; +import { DictationOverlay } from "../views/DictationOverlay"; library.add(fa.faCopy); @@ -71,7 +72,7 @@ export default class SharingManager extends React.Component<{}> { this.populateUsers().then(action(() => { this.targetDocView = target; this.targetDoc = target.props.Document; - MainView.Instance.hasActiveModal = true; + DictationOverlay.Instance.hasActiveModal = true; this.isOpen = true; if (!this.sharingDoc) { this.sharingDoc = new Doc; @@ -84,7 +85,7 @@ export default class SharingManager extends React.Component<{}> { this.users = []; setTimeout(action(() => { this.copied = false; - MainView.Instance.hasActiveModal = false; + DictationOverlay.Instance.hasActiveModal = false; this.targetDoc = undefined; }), 500); }); diff --git a/src/client/views/CollectionLinearView.scss b/src/client/views/CollectionLinearView.scss new file mode 100644 index 000000000..30be07a9f --- /dev/null +++ b/src/client/views/CollectionLinearView.scss @@ -0,0 +1,74 @@ +@import "globalCssVariables"; +@import "nodeModuleOverrides"; + +.collectionLinearView { + + >label { + background: $dark-color; + color: $light-color; + display: inline-block; + border-radius: 18px; + font-size: 25px; + width: 36px; + height: 36px; + margin-right: 10px; + cursor: pointer; + transition: transform 0.2s; + } + + label p { + padding-left: 10.5px; + } + + label:hover { + background: $main-accent; + transform: scale(1.15); + } + + >input { + display: none; + } + >input:not(:checked)~.collectionLinearView-content { + display: none; + } + + >input:checked~label { + transform: rotate(45deg); + transition: transform 0.5s; + cursor: pointer; + } + + .collectionLinearView-content { + display: flex; + opacity: 1; + margin: 0; + padding: 0; + position: relative; + float: right; + .collectionFreeFormDocumentView-container { + position: relative; + } + .collectionLinearView-docBtn { + position:relative; + margin-right: 10px; + width: 35px; + height: 35px; + } + .collectionLinearView-round-button { + width: 36px; + height: 36px; + border-radius: 18px; + font-size: 15px; + } + + .collectionLinearView-round-button:hover { + transform: scale(1.15); + } + + } + + .collectionLinearView-add-button { + position: relative; + margin-right: 10px; + } +} diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx new file mode 100644 index 000000000..18e3598a5 --- /dev/null +++ b/src/client/views/CollectionLinearView.tsx @@ -0,0 +1,106 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, observable, computed } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; +import { InkTool } from '../../new_fields/InkField'; +import { ObjectField } from '../../new_fields/ObjectField'; +import { ScriptField } from '../../new_fields/ScriptField'; +import { NumCast, StrCast } from '../../new_fields/Types'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse } from '../../Utils'; +import { Docs } from '../documents/Documents'; +import { DragManager } from '../util/DragManager'; +import { Transform } from '../util/Transform'; +import { UndoManager } from '../util/UndoManager'; +import { InkingControl } from './InkingControl'; +import { DocumentView } from './nodes/DocumentView'; +import "./CollectionLinearView.scss"; + +interface CollectionLinearViewProps { + Document: Doc; + fieldKey: string; +} + +@observer +export class CollectionLinearView extends React.Component{ + @observable public addMenuToggle = React.createRef(); + private _dropDisposer?: DragManager.DragDropDisposer; + + componentWillUnmount() { + this._dropDisposer && this._dropDisposer(); + } + + protected createDropTarget = (ele: HTMLLabelElement) => { //used for stacking and masonry view + this._dropDisposer && this._dropDisposer(); + if (ele) { + this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + } + } + + drop = action((e: Event, de: DragManager.DropEvent) => { + (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => { + if (!doc.onDragStart) { + let dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); + dbox.dragFactory = doc; + dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; + dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); + doc = dbox; + } + Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc); + }); + }); + + selected = (tool: InkTool) => { + if (!InkingControl.Instance || InkingControl.Instance.selectedTool === InkTool.None) return { display: "none" }; + if (InkingControl.Instance.selectedTool === tool) { + return { color: "#61aaa3", fontSize: "50%" }; + } + return { fontSize: "50%" }; + } + + render() { + return
    + + + +
    + + + + {DocListCast(this.props.Document[this.props.fieldKey]).map(doc =>
    + Doc.RemoveDocFromList(this.props.Document, this.props.fieldKey, doc)} + ruleProvider={undefined} + onClick={undefined} + ScreenToLocalTransform={Transform.Identity} + ContentScaling={() => 35 / NumCast(doc.nativeWidth, 35)} + PanelWidth={() => 35} + PanelHeight={() => 35} + renderDepth={0} + focus={emptyFunction} + backgroundColor={returnEmptyString} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + zoomToScale={emptyFunction} + getScale={returnOne}> + +
    )} + {/*
  • */} + + + + + + +
    +
    ; + } +} \ No newline at end of file diff --git a/src/client/views/DictationOverlay.tsx b/src/client/views/DictationOverlay.tsx new file mode 100644 index 000000000..2accf9bfd --- /dev/null +++ b/src/client/views/DictationOverlay.tsx @@ -0,0 +1,71 @@ +import { computed, observable, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; +import "normalize.css"; +import * as React from 'react'; +import { DictationManager } from '../util/DictationManager'; +import "./Main.scss"; +import MainViewModal from './MainViewModal'; + +@observer +export class DictationOverlay extends React.Component { + public static Instance: DictationOverlay; + @observable private _dictationState = DictationManager.placeholder; + @observable private _dictationSuccessState: boolean | undefined = undefined; + @observable private _dictationDisplayState = false; + @observable private _dictationListeningState: DictationManager.Controls.ListeningUIStatus = false; + + public isPointerDown = false; + public overlayTimeout: NodeJS.Timeout | undefined; + public hasActiveModal = false; + + constructor(props: any) { + super(props); + DictationOverlay.Instance = this; + } + + public initiateDictationFade = () => { + let duration = DictationManager.Commands.dictationFadeDuration; + this.overlayTimeout = setTimeout(() => { + this.dictationOverlayVisible = false; + this.dictationSuccess = undefined; + DictationOverlay.Instance.hasActiveModal = false; + setTimeout(() => this.dictatedPhrase = DictationManager.placeholder, 500); + }, duration); + } + public cancelDictationFade = () => { + if (this.overlayTimeout) { + clearTimeout(this.overlayTimeout); + this.overlayTimeout = undefined; + } + } + + @computed public get dictatedPhrase() { return this._dictationState; } + @computed public get dictationSuccess() { return this._dictationSuccessState; } + @computed public get dictationOverlayVisible() { return this._dictationDisplayState; } + @computed public get isListening() { return this._dictationListeningState; } + + public set dictatedPhrase(value: string) { runInAction(() => this._dictationState = value); } + public set dictationSuccess(value: boolean | undefined) { runInAction(() => this._dictationSuccessState = value); } + public set dictationOverlayVisible(value: boolean) { runInAction(() => this._dictationDisplayState = value); } + public set isListening(value: DictationManager.Controls.ListeningUIStatus) { runInAction(() => this._dictationListeningState = value); } + + render() { + let success = this.dictationSuccess; + let result = this.isListening && !this.isListening.interim ? DictationManager.placeholder : `"${this.dictatedPhrase}"`; + let dialogueBoxStyle = { + background: success === undefined ? "gainsboro" : success ? "lawngreen" : "red", + borderColor: this.isListening ? "red" : "black", + fontStyle: "italic" + }; + let overlayStyle = { + backgroundColor: this.isListening ? "red" : "darkslategrey" + }; + return (); + } +} \ No newline at end of file diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 38fce4cf7..f31a29bdc 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -122,10 +122,10 @@ export default class KeyManager { let preventDefault = true; switch (keyname) { - case "n": - let toggle = MainView.Instance.addMenuToggle.current!; - toggle.checked = !toggle.checked; - break; + // case "n": + // let toggle = MainView.Instance.addMenuToggle.current!; + // toggle.checked = !toggle.checked; + // break; } return { diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index ee8b77050..38734a03d 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -18,7 +18,7 @@ library.add(faPen, faHighlighter, faEraser, faBan); @observer export class InkingControl extends React.Component { - static Instance: InkingControl = new InkingControl({}); + @observable static Instance: InkingControl; @observable private _selectedTool: InkTool = InkTool.None; @observable private _selectedColor: string = "rgb(244, 67, 54)"; @observable private _selectedWidth: string = "5"; @@ -26,7 +26,7 @@ export class InkingControl extends React.Component { constructor(props: Readonly<{}>) { super(props); - InkingControl.Instance = this; + runInAction(() => InkingControl.Instance = this); } @action @@ -45,7 +45,6 @@ export class InkingControl extends React.Component { switchColor = action((color: ColorResult): void => { this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff"); if (InkingControl.Instance.selectedTool === InkTool.None) { - // if (MainOverlayTextBox.Instance.SetColor(color.hex)) return; let selected = SelectionManager.SelectedDocuments(); let oldColors = selected.map(view => { let targetDoc = view.props.Document.layout instanceof Doc ? view.props.Document.layout : view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document); diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 55195b616..0335e12a5 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -21,7 +21,6 @@ div { } - .jsx-parser { width: 100%; height: 100%; @@ -64,228 +63,10 @@ button:hover { cursor: pointer; } -.clear-db-button { - position: absolute; - right: 45%; - bottom: 3%; - font-size: 50%; -} - -.round-button { - width: 36px; - height: 36px; - border-radius: 18px; - font-size: 15px; -} - -.round-button:hover { - transform: scale(1.15); -} - -.add-button { - position: relative; - margin-right: 10px; -} - -.main-undoButtons { - position: absolute; - width: 150px; - right: 0px; -} - -//toolbar stuff -#toolbar { - position: absolute; - right: 8px; - top: 5px; - - .toolbar-button { - display: block; - margin-bottom: 10px; - } -} - -.toolbar-color-picker { - background-color: $light-color; - border-radius: 5px; - padding: 12px; - position: absolute; - bottom: 36px; - left: -3px; - box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; -} - -.toolbar-color-button { - border-radius: 11px; - width: 22px; - height: 22px; - cursor: pointer; - text-align: center; // span { - // color: $light-color; - // font-size: 8px; - // user-select: none; - // } - margin-top: -2.55px; - margin-left: -2.55px; -} - -// add nodes menu. Note that the + button is actually an input label, not an actual button. -#add-nodes-menu { - position: absolute; - bottom: 22px; - left: 250px; - - >label { - background: $dark-color; - color: $light-color; - display: inline-block; - border-radius: 18px; - font-size: 25px; - width: 36px; - height: 36px; - margin-right: 10px; - cursor: pointer; - transition: transform 0.2s; - } - - label p { - padding-left: 10.5px; - } - - label:hover { - background: $main-accent; - transform: scale(1.15); - } - - >input { - display: none; - } - - >input:not(:checked)~#add-options-content { - display: none; - } - - >input:checked~label { - transform: rotate(45deg); - transition: transform 0.5s; - cursor: pointer; - } -} - #root { overflow: visible; } -#main-div { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - overflow: auto; - z-index: 1; -} -.mainContent { - width:100%; - height:100%; - position:absolute; -} -.mainView-flyoutContainer{ - display:flex; - flex-direction: column; - position: absolute; - width:100%; - height:100%; - border: black 1px solid; - .documentView-node-topmost { - background: lightgrey; - } -} -#mainContent-div { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - overflow: hidden; -} - -#add-options-content { - display: flex; - opacity: 1; - margin: 0; - padding: 0; - position: relative; - float: right; - .mainView-docBtn { - position:relative; - margin-right: 10px; - width: 35px; - height: 35px; - } - .collectionFreeFormDocumentView-container { - position: relative; - } -} - -ul#add-options-list { - list-style: none; - padding: 5 0 0 0; - - >li { - display: inline-block; - padding: 0; - } -} -.mainView-logout { - position: absolute; - right: 0; - bottom: 0; - font-size: 8px; -} - -.mainView-libraryFlyout { - height: 100%; - position: absolute; - display: flex; - flex-direction: column; -} - -.expandFlyoutButton { - position: absolute; - top: 30px; - right: 30px; - cursor: pointer; -} - -.mainView-libraryHandle { - width: 20px; - height: 40px; - top: 50%; - border: 1px solid black; - border-radius: 5px; - position: absolute; - z-index: 1; -} - .svg-inline--fa { vertical-align: unset; -} - -.mainView-workspace { - height: 200px; - position: relative; - display: flex; -} - -.mainView-library { - height: 75%; - position: relative; - display: flex; -} - -.mainView-recentlyClosed { - height: 25%; - position: relative; - display: flex; } \ No newline at end of file diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss new file mode 100644 index 000000000..e61494e71 --- /dev/null +++ b/src/client/views/MainView.scss @@ -0,0 +1,97 @@ +@import "globalCssVariables"; +@import "nodeModuleOverrides"; + + +.mainView-tabButtons { + position: relative; + width:100%; +} +// add nodes menu. Note that the + button is actually an input label, not an actual button. +.mainView-docButtons { + position: absolute; + bottom: 20px; + left: 250px; +} + +.mainView-container { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + overflow: auto; + z-index: 1; +} +.mainView-mainContent { + width:100%; + height:100%; + position:absolute; +} +.mainView-flyoutContainer{ + display:flex; + flex-direction: column; + position: absolute; + width:100%; + height:100%; + border: black 1px solid; + .documentView-node-topmost { + background: lightgrey; + } +} +.mainView-mainDiv { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + overflow: hidden; +} + +.mainView-logout { + position: absolute; + right: 0; + bottom: 0; + font-size: 8px; +} + +.mainView-libraryFlyout { + height: 100%; + position: absolute; + display: flex; + flex-direction: column; +} + +.mainView-expandFlyoutButton { + position: absolute; + top: 30px; + right: 30px; + cursor: pointer; +} + +.mainView-libraryHandle { + width: 20px; + height: 40px; + top: 50%; + border: 1px solid black; + border-radius: 5px; + position: absolute; + z-index: 1; +} + +.mainView-workspace { + height: 200px; + position: relative; + display: flex; +} + +.mainView-library { + height: 75%; + position: relative; + display: flex; +} + +.mainView-recentlyClosed { + height: 25%; + position: relative; + display: flex; +} \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index aac4af9f6..4367785b6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -8,32 +8,26 @@ import * as React from 'react'; import Measure from 'react-measure'; import { Doc, DocListCast, Field, FieldResult, Opt } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; -import { InkTool } from '../../new_fields/InkField'; import { List } from '../../new_fields/List'; -import { ObjectField } from '../../new_fields/ObjectField'; import { listSpec } from '../../new_fields/Schema'; -import { ScriptField } from '../../new_fields/ScriptField'; -import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast } from '../../new_fields/Types'; +import { Cast, FieldValue, StrCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; -import { DictationManager } from '../util/DictationManager'; -import { DragManager } from '../util/DragManager'; import { HistoryUtil } from '../util/History'; import SharingManager from '../util/SharingManager'; import { Transform } from '../util/Transform'; -import { UndoManager } from '../util/UndoManager'; +import { CollectionLinearView } from './CollectionLinearView'; import { CollectionBaseView, CollectionViewType } from './collections/CollectionBaseView'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { ContextMenu } from './ContextMenu'; +import { DictationOverlay } from './DictationOverlay'; import { DocumentDecorations } from './DocumentDecorations'; import KeyManager from './GlobalKeyHandler'; -import { InkingControl } from './InkingControl'; -import "./Main.scss"; -import MainViewModal from './MainViewModal'; +import "./MainView.scss"; import { MainViewNotifs } from './MainViewNotifs'; import { DocumentView } from './nodes/DocumentView'; import { OverlayView } from './OverlayView'; @@ -46,59 +40,17 @@ export class MainView extends React.Component { private _buttonBarHeight = 75; private _flyoutSizeOnDown = 0; private _urlState: HistoryUtil.DocUrl; - private _dropDisposer?: DragManager.DragDropDisposer; - - @observable private _dictationState = DictationManager.placeholder; - @observable private _dictationSuccessState: boolean | undefined = undefined; - @observable private _dictationDisplayState = false; - @observable private _dictationListeningState: DictationManager.Controls.ListeningUIStatus = false; @observable private _panelWidth: number = 0; @observable private _panelHeight: number = 0; @observable private _flyoutTranslate: boolean = true; - @observable public addMenuToggle = React.createRef(); @observable public flyoutWidth: number = 250; - public hasActiveModal = false; - public isPointerDown = false; - public overlayTimeout: NodeJS.Timeout | undefined; - - private set mainContainer(doc: Opt) { - if (doc) { - !("presentationView" in doc) && (doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })])); - this.userDoc ? (this.userDoc.activeWorkspace = doc) : (CurrentUserUtils.GuestWorkspace = doc); - } - } - - @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; } @computed private get userDoc() { return CurrentUserUtils.UserDocument; } + @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; } @computed public get mainFreeform(): Opt { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } - public initiateDictationFade = () => { - let duration = DictationManager.Commands.dictationFadeDuration; - this.overlayTimeout = setTimeout(() => { - this.dictationOverlayVisible = false; - this.dictationSuccess = undefined; - this.hasActiveModal = false; - setTimeout(() => this.dictatedPhrase = DictationManager.placeholder, 500); - }, duration); - } - public cancelDictationFade = () => { - if (this.overlayTimeout) { - clearTimeout(this.overlayTimeout); - this.overlayTimeout = undefined; - } - } - - @computed public get dictatedPhrase() { return this._dictationState; } - @computed public get dictationSuccess() { return this._dictationSuccessState; } - @computed public get dictationOverlayVisible() { return this._dictationDisplayState; } - @computed public get isListening() { return this._dictationListeningState; } - - public set dictatedPhrase(value: string) { runInAction(() => this._dictationState = value); } - public set dictationSuccess(value: boolean | undefined) { runInAction(() => this._dictationSuccessState = value); } - public set dictationOverlayVisible(value: boolean) { runInAction(() => this._dictationDisplayState = value); } - public set isListening(value: DictationManager.Controls.ListeningUIStatus) { runInAction(() => this._dictationListeningState = value); } + public isPointerDown = false; componentWillMount() { var tag = document.createElement('script'); @@ -112,10 +64,8 @@ export class MainView extends React.Component { componentWillUnMount() { window.removeEventListener("keydown", KeyManager.Instance.handle); - //close presentation window.removeEventListener("pointerdown", this.globalPointerDown); window.removeEventListener("pointerup", this.globalPointerUp); - this._dropDisposer && this._dropDisposer(); } constructor(props: Readonly<{}>) { @@ -183,7 +133,6 @@ export class MainView extends React.Component { globalPointerUp = () => this.isPointerDown = false; initEventListeners = () => { - // window.addEventListener("pointermove", (e) => this.reportLocation(e)) window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler window.addEventListener("dragover", (e) => e.preventDefault(), false); // drag event handler // click interactions for the context menu @@ -202,24 +151,16 @@ export class MainView extends React.Component { ); } else { if (received && this._urlState.sharing) { - reaction( - () => { - let docking = CollectionDockingView.Instance; - return docking && docking.initialized; - }, - initialized => { - if (initialized && received) { - DocServer.GetRefField(received).then(field => { - if (field instanceof Doc && field.viewType !== CollectionViewType.Docking) { - CollectionDockingView.AddRightSplit(field, undefined); - } - }); + reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized, + initialized => initialized && received && DocServer.GetRefField(received).then(field => { + if (field instanceof Doc && field.viewType !== CollectionViewType.Docking) { + CollectionDockingView.AddRightSplit(field, undefined); } - }, + }), ); } - let doc: Opt; - if (this.userDoc && (doc = await Cast(this.userDoc.activeWorkspace, Doc))) { + let doc = this.userDoc && await Cast(this.userDoc.activeWorkspace, Doc); + if (doc) { this.openWorkspace(doc); } else { this.createNewWorkspace(); @@ -250,17 +191,17 @@ export class MainView extends React.Component { mainDoc.title = `Workspace ${DocListCast(workspaces.data).length}`; } // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) - setTimeout(() => { - this.openWorkspace(mainDoc); - // let pendingDocument = Docs.StackingDocument([], { title: "New Mobile Uploads" }); - // mainDoc.optionalRightCollection = pendingDocument; - }, 0); + setTimeout(() => this.openWorkspace(mainDoc), 0); } @action openWorkspace = async (doc: Doc, fromHistory = false) => { CurrentUserUtils.MainDocId = doc[Id]; - this.mainContainer = doc; + + if (doc) { // this has the side-effect of setting the main container since we're assigning the active/guest workspace + !("presentationView" in doc) && (doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })])); + this.userDoc ? (this.userDoc.activeWorkspace = doc) : (CurrentUserUtils.GuestWorkspace = doc); + } let state = this._urlState; if (state.sharing === true && !this.userDoc) { DocServer.Control.makeReadOnly(); @@ -280,7 +221,7 @@ export class MainView extends React.Component { } CollectionBaseView.SetSafeMode(true); } else if (state.nro || state.nro === null || state.readonly === false) { - } else if (BoolCast(doc.readOnly)) { + } else if (doc.readOnly) { DocServer.Control.makeReadOnly(); } else { DocServer.Control.makeEditable(); @@ -294,19 +235,6 @@ export class MainView extends React.Component { return true; } - drop = action((e: Event, de: DragManager.DropEvent) => { - (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => { - if (!doc.onDragStart) { - let dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); - dbox.dragFactory = doc; - dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; - dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); - doc = dbox; - } - Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); - }); - }); - onDrop = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); @@ -323,14 +251,12 @@ export class MainView extends React.Component { getContentsHeight = () => this._panelHeight - this._buttonBarHeight; @computed get dockingContent() { + const mainContainer = this.mainContainer; return {({ measureRef }) => -
    - {!this.mainContainer ? (null) : - + {!mainContainer ? (null) : + { if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4) { - if (this.flyoutWidth < 5) this.flyoutWidth = 250; - else this.flyoutWidth = 0; + this.flyoutWidth = this.flyoutWidth < 5 ? 250 : 0; } document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -418,7 +343,7 @@ export class MainView extends React.Component { let libraryButtonDoc = Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc; libraryButtonDoc.columnWidth = this.flyoutWidth / 3 - 30; return
    -
    +
    -
    +
    +
    @@ -508,7 +433,7 @@ export class MainView extends React.Component { } @computed get expandButton() { - return !this._flyoutTranslate ? (
    { + return !this._flyoutTranslate ? (
    { runInAction(() => { this.flyoutWidth = 250; this._flyoutTranslate = true; @@ -516,126 +441,25 @@ export class MainView extends React.Component { }}>
    ) : (null); } - selected = (tool: InkTool) => { - if (!InkingControl.Instance || InkingControl.Instance.selectedTool === InkTool.None) return { display: "none" }; - if (InkingControl.Instance.selectedTool === tool) { - return { color: "#61aaa3", fontSize: "50%" }; - } - return { fontSize: "50%" }; - } - - setWriteMode = (mode: DocServer.WriteMode) => { - console.log(DocServer.WriteMode[mode]); - const mode1 = mode; - const mode2 = mode === DocServer.WriteMode.Default ? mode : DocServer.WriteMode.Playground; - DocServer.setFieldWriteMode("x", mode1); - DocServer.setFieldWriteMode("y", mode1); - DocServer.setFieldWriteMode("width", mode1); - DocServer.setFieldWriteMode("height", mode1); - - DocServer.setFieldWriteMode("panX", mode2); - DocServer.setFieldWriteMode("panY", mode2); - DocServer.setFieldWriteMode("scale", mode2); - DocServer.setFieldWriteMode("viewType", mode2); - } - - protected createDropTarget = (ele: HTMLLabelElement) => { //used for stacking and masonry view - this._dropDisposer && this._dropDisposer(); - if (ele) { - this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); - } - } - - /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */ - nodesMenu() { - // let youtubeurl = "https://www.youtube.com/embed/TqcApsGRzWw"; - // let addYoutubeSearcher = action(() => Docs.Create.YoutubeDocument(youtubeurl, { width: 600, height: 600, title: "youtube search" })); - - // let googlePhotosSearch = () => GooglePhotosClientUtils.CollectionFromSearch(Docs.Create.MasonryDocument, { included: [GooglePhotosClientUtils.ContentCategories.LANDSCAPES] }); - - return < div id="add-nodes-menu" style={{ left: (this._flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > - + @computed get docButtons() { + return
    - - - -
    - - - - {DocListCast(CurrentUserUtils.UserDocument.docButtons).map(doc =>
    - Doc.RemoveDocFromList(CurrentUserUtils.UserDocument, "docButtons", doc)} - ruleProvider={undefined} - onClick={undefined} - ScreenToLocalTransform={Transform.Identity} - ContentScaling={() => 35 / NumCast(doc.nativeWidth, 35)} - PanelWidth={() => 35} - PanelHeight={() => 35} - renderDepth={0} - focus={emptyFunction} - backgroundColor={returnEmptyString} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} - bringToFront={emptyFunction} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - zoomToScale={emptyFunction} - getScale={returnOne}> - -
    )} - {/*
  • */} - - - - - - -
    -
    ; - } - - @computed private get dictationOverlay() { - let success = this.dictationSuccess; - let result = this.isListening && !this.isListening.interim ? DictationManager.placeholder : `"${this.dictatedPhrase}"`; - let dialogueBoxStyle = { - background: success === undefined ? "gainsboro" : success ? "lawngreen" : "red", - borderColor: this.isListening ? "red" : "black", - fontStyle: "italic" - }; - let overlayStyle = { - backgroundColor: this.isListening ? "red" : "darkslategrey" - }; - return ( - - ); + +
    ; } render() { - return ( -
    - {this.dictationOverlay} - - - - {this.mainContent} - - - {this.nodesMenu()} - - -
    - ); + return (
    + + + + + {this.mainContent} + + + {this.docButtons} + + +
    ); } -} +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 98ae7442f..7334de92c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -26,7 +26,6 @@ import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent } from "../DocComponent"; import { EditableView } from '../EditableView'; -import { MainView } from '../MainView'; import { OverlayView } from '../OverlayView'; import { ScriptBox } from '../ScriptBox'; import { ScriptingRepl } from '../ScriptingRepl'; @@ -39,6 +38,7 @@ import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { ImageField } from '../../../new_fields/URLField'; import SharingManager from '../../util/SharingManager'; import { Scripting } from '../../util/Scripting'; +import { DictationOverlay } from '../DictationOverlay'; library.add(fa.faEdit); library.add(fa.faTrash); @@ -423,10 +423,9 @@ export class DocumentView extends DocComponent(Docu Doc.GetProto(this.props.Document).transcript = await DictationManager.Controls.listen({ continuous: { indefinite: true }, interimHandler: (results: string) => { - let main = MainView.Instance; - main.dictationSuccess = true; - main.dictatedPhrase = results; - main.isListening = { interim: true }; + DictationOverlay.Instance.dictationSuccess = true; + DictationOverlay.Instance.dictatedPhrase = results; + DictationOverlay.Instance.isListening = { interim: true }; } }); } diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss index 97d858f58..2b81c16c0 100644 --- a/src/client/views/nodes/ImageBox.scss +++ b/src/client/views/nodes/ImageBox.scss @@ -9,6 +9,10 @@ pointer-events: none; } +.imageBox-container { + border-radius: inherit; +} + .imageBox-cont-interactive { pointer-events: all; } -- cgit v1.2.3-70-g09d2 From baf6ed901d341cade58741d363bbc475519558ae Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 13 Oct 2019 03:10:29 -0400 Subject: made CollectionLinearView out of doc buttons --- src/client/views/CollectionLinearView.scss | 13 ++- src/client/views/CollectionLinearView.tsx | 111 +++++++++++---------- src/client/views/MainView.tsx | 34 ++++++- .../views/collections/CollectionBaseView.tsx | 6 +- src/client/views/collections/CollectionSubView.tsx | 1 + src/client/views/collections/CollectionView.tsx | 2 + .../views/collections/CollectionViewChromes.tsx | 1 + .../authentication/models/current_user_utils.ts | 2 + 8 files changed, 111 insertions(+), 59 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/views/CollectionLinearView.scss b/src/client/views/CollectionLinearView.scss index 30be07a9f..46a226eef 100644 --- a/src/client/views/CollectionLinearView.scss +++ b/src/client/views/CollectionLinearView.scss @@ -1,8 +1,13 @@ @import "globalCssVariables"; @import "nodeModuleOverrides"; +.collectionLinearView-outer{ + overflow: hidden; + height:100%; + padding:5px; +} .collectionLinearView { - + display:flex; >label { background: $dark-color; color: $light-color; @@ -18,6 +23,8 @@ label p { padding-left: 10.5px; + width: 500px; + height: 500px; } label:hover { @@ -41,18 +48,14 @@ .collectionLinearView-content { display: flex; opacity: 1; - margin: 0; padding: 0; position: relative; - float: right; .collectionFreeFormDocumentView-container { position: relative; } .collectionLinearView-docBtn { position:relative; margin-right: 10px; - width: 35px; - height: 35px; } .collectionLinearView-round-button { width: 36px; diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 18e3598a5..692f940f8 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -7,22 +7,23 @@ import { InkTool } from '../../new_fields/InkField'; import { ObjectField } from '../../new_fields/ObjectField'; import { ScriptField } from '../../new_fields/ScriptField'; import { NumCast, StrCast } from '../../new_fields/Types'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse } from '../../Utils'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse, Utils } from '../../Utils'; import { Docs } from '../documents/Documents'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; import { InkingControl } from './InkingControl'; -import { DocumentView } from './nodes/DocumentView'; +import { DocumentView, documentSchema } from './nodes/DocumentView'; import "./CollectionLinearView.scss"; +import { makeInterface } from '../../new_fields/Schema'; +import { CollectionSubView } from './collections/CollectionSubView'; -interface CollectionLinearViewProps { - Document: Doc; - fieldKey: string; -} + +type LinearDocument = makeInterface<[typeof documentSchema,]>; +const LinearDocument = makeInterface(documentSchema); @observer -export class CollectionLinearView extends React.Component{ +export class CollectionLinearView extends CollectionSubView(LinearDocument) { @observable public addMenuToggle = React.createRef(); private _dropDisposer?: DragManager.DragDropDisposer; @@ -30,7 +31,7 @@ export class CollectionLinearView extends React.Component { //used for stacking and masonry view + protected createDropTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view this._dropDisposer && this._dropDisposer(); if (ele) { this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); @@ -38,16 +39,18 @@ export class CollectionLinearView extends React.Component { - (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => { - if (!doc.onDragStart) { - let dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); + (de.data as DragManager.DocumentDragData).draggedDocuments.map((doc, i) => { + let dbox = doc; + if (!doc.onDragStart && this.props.Document.convertToButtons) { + dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); dbox.dragFactory = doc; dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); - doc = dbox; } - Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc); + (de.data as DragManager.DocumentDragData).droppedDocuments[i] = dbox; }); + e.stopPropagation(); + return super.drop(e, de); }); selected = (tool: InkTool) => { @@ -58,49 +61,55 @@ export class CollectionLinearView extends React.Component NumCast(this.props.Document.height) - 5; render() { - return
    - - + let guid = Utils.GenerateGuid(); + return
    + +
    - - + {this.props.showHiddenControls ? : (null)} + {this.props.showHiddenControls ? : (null)} - {DocListCast(this.props.Document[this.props.fieldKey]).map(doc =>
    - Doc.RemoveDocFromList(this.props.Document, this.props.fieldKey, doc)} - ruleProvider={undefined} - onClick={undefined} - ScreenToLocalTransform={Transform.Identity} - ContentScaling={() => 35 / NumCast(doc.nativeWidth, 35)} - PanelWidth={() => 35} - PanelHeight={() => 35} - renderDepth={0} - focus={emptyFunction} - backgroundColor={returnEmptyString} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} - bringToFront={emptyFunction} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - zoomToScale={emptyFunction} - getScale={returnOne}> - -
    )} + {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => +
    + this.dimension() / (10 + NumCast(pair.layout.nativeWidth, this.dimension()))} // ugh - need to get rid of this inline function to avoid recomputing + PanelWidth={this.dimension} + PanelHeight={this.dimension} + renderDepth={this.props.renderDepth + 1} + focus={emptyFunction} + backgroundColor={returnEmptyString} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + zoomToScale={emptyFunction} + getScale={returnOne}> + +
    )} {/*
  • */} - - - - - - + {this.props.showHiddenControls ? <> + + + + + + : (null)}
    -
    ; +
    ; } } \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4367785b6..5756c1510 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -441,10 +441,42 @@ export class MainView extends React.Component { }}>
    ) : (null); } + addButtonDoc = (doc: Doc) => { + Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); + return true; + } + remButtonDoc = (doc: Doc) => { + Doc.RemoveDocFromList(CurrentUserUtils.UserDocument, "docButtons", doc); + return true; + } @computed get docButtons() { return
    - +
    ; } diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 61919427a..7798964ea 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -23,6 +23,7 @@ export enum CollectionViewType { Stacking, Masonry, Pivot, + Linear, } export namespace CollectionViewType { @@ -35,7 +36,8 @@ export namespace CollectionViewType { ["tree", CollectionViewType.Tree], ["stacking", CollectionViewType.Stacking], ["masonry", CollectionViewType.Masonry], - ["pivot", CollectionViewType.Pivot] + ["pivot", CollectionViewType.Pivot], + ["linear", CollectionViewType.Linear] ]); export const valueOf = (value: string) => { @@ -177,7 +179,7 @@ export class CollectionBaseView extends React.Component {
    diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index fdbe5339d..6e8e4fa12 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -33,6 +33,7 @@ export interface CollectionViewProps extends FieldViewProps { VisibleHeight?: () => number; chromeCollapsed: boolean; setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void; + showHiddenControls?: boolean; // hack for showing the undo/redo/ink controls in a linear view -- needs to be redone } export interface SubCollectionViewProps extends CollectionViewProps { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 893763840..3d5b4e562 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -19,6 +19,7 @@ import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; import { CollectionViewBaseChrome } from './CollectionViewChromes'; import { ImageUtils } from '../../util/Import & Export/ImageUtils'; +import { CollectionLinearView } from '../CollectionLinearView'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy); @@ -66,6 +67,7 @@ export class CollectionView extends React.Component { case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } case CollectionViewType.Pivot: { this.props.Document.freeformLayoutEngine = "pivot"; return (); } + case CollectionViewType.Linear: { return (); } case CollectionViewType.Freeform: default: this.props.Document.freeformLayoutEngine = undefined; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 72f3514b6..3a66c05f4 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -399,6 +399,7 @@ export class CollectionViewBaseChrome extends React.ComponentStacking View +
    Date: Sun, 13 Oct 2019 19:17:45 -0400 Subject: minor cleanups --- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/util/UndoManager.ts | 4 +- src/client/views/CollectionLinearView.scss | 118 ++++++++++----------- src/client/views/CollectionLinearView.tsx | 103 ++++++++++-------- src/client/views/DocumentDecorations.tsx | 8 +- src/client/views/MainView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FontIconBox.tsx | 2 +- src/new_fields/Doc.ts | 5 +- .../authentication/models/current_user_utils.ts | 21 +++- 10 files changed, 150 insertions(+), 118 deletions(-) (limited to 'src/client/views/MainView.tsx') diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index c82d3bc63..31d98887f 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -850,7 +850,7 @@ export class TooltipTextMenu { } this.view = view; let state = view.state; - DocumentDecorations.Instance.TextBar && DocumentDecorations.Instance.setTextBar(DocumentDecorations.Instance.TextBar); + DocumentDecorations.Instance.showTextBar(); props && (this.editorProps = props); // Don't do anything if the document/selection didn't change if (lastState && lastState.doc.eq(state.doc) && diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 7abb9d1ee..472afac1d 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -73,8 +73,8 @@ export namespace UndoManager { } type UndoBatch = UndoEvent[]; - let undoStack: UndoBatch[] = observable([]); - let redoStack: UndoBatch[] = observable([]); + export let undoStack: UndoBatch[] = observable([]); + export let redoStack: UndoBatch[] = observable([]); let currentBatch: UndoBatch | undefined; let batchCounter = 0; let undoing = false; diff --git a/src/client/views/CollectionLinearView.scss b/src/client/views/CollectionLinearView.scss index 46a226eef..1e6bb5922 100644 --- a/src/client/views/CollectionLinearView.scss +++ b/src/client/views/CollectionLinearView.scss @@ -5,73 +5,69 @@ overflow: hidden; height:100%; padding:5px; -} -.collectionLinearView { - display:flex; - >label { - background: $dark-color; - color: $light-color; - display: inline-block; - border-radius: 18px; - font-size: 25px; - width: 36px; - height: 36px; - margin-right: 10px; - cursor: pointer; - transition: transform 0.2s; - } + .collectionLinearView { + display:flex; + >label { + background: $dark-color; + color: $light-color; + display: inline-block; + border-radius: 18px; + font-size: 25px; + width: 36px; + height: 36px; + margin-right: 10px; + cursor: pointer; + transition: transform 0.2s; + } - label p { - padding-left: 10.5px; - width: 500px; - height: 500px; - } + label p { + padding-left: 10.5px; + width: 500px; + height: 500px; + } - label:hover { - background: $main-accent; - transform: scale(1.15); - } + label:hover { + background: $main-accent; + transform: scale(1.15); + } - >input { - display: none; - } - >input:not(:checked)~.collectionLinearView-content { - display: none; - } + >input { + display: none; + } + >input:not(:checked)~.collectionLinearView-content { + display: none; + } - >input:checked~label { - transform: rotate(45deg); - transition: transform 0.5s; - cursor: pointer; - } + >input:checked~label { + transform: rotate(45deg); + transition: transform 0.5s; + cursor: pointer; + } - .collectionLinearView-content { - display: flex; - opacity: 1; - padding: 0; - position: relative; - .collectionFreeFormDocumentView-container { + .collectionLinearView-content { + display: flex; + opacity: 1; + padding: 0; position: relative; - } - .collectionLinearView-docBtn { - position:relative; - margin-right: 10px; - } - .collectionLinearView-round-button { - width: 36px; - height: 36px; - border-radius: 18px; - font-size: 15px; - } - - .collectionLinearView-round-button:hover { - transform: scale(1.15); + + .collectionLinearView-docBtn { + position:relative; + margin-right: 10px; + } + .collectionLinearView-docBtn:hover { + transform: scale(1.15); + } + + .collectionLinearView-round-button { + width: 36px; + height: 36px; + border-radius: 18px; + font-size: 15px; + } + + .collectionLinearView-round-button:hover { + transform: scale(1.15); + } } - - } - - .collectionLinearView-add-button { - position: relative; - margin-right: 10px; } } diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 692f940f8..49c67a448 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -1,8 +1,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable, computed } from 'mobx'; +import { action, observable, computed, IReactionDisposer, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; +import { Doc, DocListCast, Opt, HeightSym } from '../../new_fields/Doc'; import { InkTool } from '../../new_fields/InkField'; import { ObjectField } from '../../new_fields/ObjectField'; import { ScriptField } from '../../new_fields/ScriptField'; @@ -25,12 +25,26 @@ const LinearDocument = makeInterface(documentSchema); @observer export class CollectionLinearView extends CollectionSubView(LinearDocument) { @observable public addMenuToggle = React.createRef(); + @observable private _checked = false; private _dropDisposer?: DragManager.DragDropDisposer; + private _heightDisposer?: IReactionDisposer; componentWillUnmount() { this._dropDisposer && this._dropDisposer(); + this._heightDisposer && this._heightDisposer(); } + componentDidMount() { + // is there any reason this needs to exist? -syip. yes, it handles autoHeight for stacking views (masonry isn't yet supported). + this._heightDisposer = reaction(() => NumCast(this.props.Document.height, 0) + this.childDocs.length + (this._checked ? 1 : 0), + () => { + if (true || this.props.Document.fitWidth) { + this.props.Document.width = 36 + (this._checked ? this.childDocs.length * (this.props.Document[HeightSym]() + 10) : 10); + } + }, + { fireImmediately: true } + ); + } protected createDropTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view this._dropDisposer && this._dropDisposer(); if (ele) { @@ -66,50 +80,49 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { dimension = () => NumCast(this.props.Document.height) - 5; render() { let guid = Utils.GenerateGuid(); - return
    - - - -
    - {this.props.showHiddenControls ? : (null)} - {this.props.showHiddenControls ? : (null)} + return
    +
    + this._checked = this.addMenuToggle.current!.checked)} /> + - {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => -
    - this.dimension() / (10 + NumCast(pair.layout.nativeWidth, this.dimension()))} // ugh - need to get rid of this inline function to avoid recomputing - PanelWidth={this.dimension} - PanelHeight={this.dimension} - renderDepth={this.props.renderDepth + 1} - focus={emptyFunction} - backgroundColor={returnEmptyString} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} - bringToFront={emptyFunction} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - zoomToScale={emptyFunction} - getScale={returnOne}> - -
    )} - {/*
  • */} - {this.props.showHiddenControls ? <> - - - - - - : (null)} +
    + {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => +
    + this.dimension() / (10 + NumCast(pair.layout.nativeWidth, this.dimension()))} // ugh - need to get rid of this inline function to avoid recomputing + PanelWidth={this.dimension} + PanelHeight={this.dimension} + renderDepth={this.props.renderDepth + 1} + focus={emptyFunction} + backgroundColor={returnEmptyString} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + zoomToScale={emptyFunction} + getScale={returnOne}> + +
    )} + {/*
  • */} + {this.props.showHiddenControls ? <> + + + + + + : (null)} +
    -
    ; +
    ; } } \ No newline at end of file diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 1d9f0c74b..3d73f048d 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -547,10 +547,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } TextBar: HTMLDivElement | undefined; - setTextBar = (ele: HTMLDivElement) => { + private setTextBar = (ele: HTMLDivElement) => { if (ele) { this.TextBar = ele; - TooltipTextMenu.Toolbar && Array.from(ele.childNodes).indexOf(TooltipTextMenu.Toolbar) === -1 && ele.appendChild(TooltipTextMenu.Toolbar); + } + } + public showTextBar = () => { + if (this.TextBar) { + TooltipTextMenu.Toolbar && Array.from(this.TextBar.childNodes).indexOf(TooltipTextMenu.Toolbar) === -1 && this.TextBar.appendChild(TooltipTextMenu.Toolbar); } } render() { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 5756c1510..39585113b 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -334,6 +334,7 @@ export class MainView extends React.Component { return CollectionDockingView.AddRightSplit(doc, undefined); } } + mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1); @computed get flyout() { let sidebarContent = this.userDoc && this.userDoc.sidebarContainer; @@ -379,7 +380,7 @@ export class MainView extends React.Component { removeDocument={returnFalse} ruleProvider={undefined} onClick={undefined} - ScreenToLocalTransform={Transform.Identity} + ScreenToLocalTransform={this.mainContainerXf} ContentScaling={returnOne} PanelWidth={this.flyoutWidthFunc} PanelHeight={this.getContentsHeight} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7334de92c..188c18ba7 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -185,7 +185,7 @@ export class DocumentView extends DocComponent(Docu (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { e.stopPropagation(); let preventDefault = true; - if (this._doubleTap && this.props.renderDepth) { + if (this._doubleTap && this.props.renderDepth && (!this.onClickHandler || !this.onClickHandler.script)) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click let fullScreenAlias = Doc.MakeAlias(this.props.Document); let layoutNative = await PromiseValue(Cast(this.props.Document.layoutNative, Doc)); if (layoutNative && fullScreenAlias.layout === layoutNative.layout) { diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index 3b580d851..3f5afb6d1 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -16,6 +16,6 @@ export class FontIconBox extends DocComponent( public static LayoutString() { return FieldView.LayoutString(FontIconBox); } render() { - return
    ; + return ; } } \ No newline at end of file diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 66036f673..4bed113e3 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -14,6 +14,7 @@ import { ComputedField } from "./ScriptField"; import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; import { intersectRect } from "../Utils"; +import { UndoManager } from "../client/util/UndoManager"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -733,4 +734,6 @@ Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); }); Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return Doc.MakeCopy(doc, copyProto); }); Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); }); Scripting.addGlobal(function aliasDocs(field: any) { return new List(field.map((d: any) => Doc.MakeAlias(d))); }); -Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); \ No newline at end of file +Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); +Scripting.addGlobal(function undo() { return UndoManager.Undo(); }); +Scripting.addGlobal(function redo() { return UndoManager.Redo(); }); \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 3858907ba..73cac879e 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,4 +1,4 @@ -import { action, computed, observable, runInAction } from "mobx"; +import { action, computed, observable, runInAction, reaction } from "mobx"; import * as rp from 'request-promise'; import { DocServer } from "../../../client/DocServer"; import { Docs } from "../../../client/documents/Documents"; @@ -13,6 +13,8 @@ import { Cast, StrCast, PromiseValue } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; import { RouteStore } from "../../RouteStore"; import { ScriptField } from "../../../new_fields/ScriptField"; +import { ButtonBox } from "../../../client/views/nodes/ButtonBox"; +import { UndoManager } from "../../../client/util/UndoManager"; export class CurrentUserUtils { private static curr_id: string; @@ -32,7 +34,6 @@ export class CurrentUserUtils { doc.viewType = CollectionViewType.Tree; doc.layout = CollectionView.LayoutString(); doc.title = Doc.CurrentUserEmail; - this.updateUserDocument(doc); doc.data = new List(); doc.gridGap = 5; doc.xMargin = 5; @@ -41,11 +42,21 @@ export class CurrentUserUtils { doc.boxShadow = "0 0"; doc.convertToButtons = true; // for CollectionLinearView used as the docButton layout doc.optionalRightCollection = Docs.Create.StackingDocument([], { title: "New mobile uploads" }); - return doc; + return this.updateUserDocument(doc);// this should be the last } static updateUserDocument(doc: Doc) { + if (doc.undoBtn === undefined) { + doc.undoBtn = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "undo-alt" }); + (doc.undoBtn as Doc).onClick = ScriptField.MakeScript('undo()'); + Doc.AddDocToList(doc, "docButtons", doc.undoBtn as Doc); + } + if (doc.redoBtn === undefined) { + doc.redoBtn = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "redo-alt" }); + (doc.redoBtn as Doc).onClick = ScriptField.MakeScript('redo()'); + Doc.AddDocToList(doc, "docButtons", doc.redoBtn as Doc); + } // setup workspaces library item if (doc.workspaces === undefined) { const workspaces = Docs.Create.TreeDocument([], { title: "WORKSPACES", height: 100 }); @@ -181,6 +192,10 @@ export class CurrentUserUtils { doc.preventTreeViewOpen = true; doc.forceActive = true; doc.lockedPosition = true; + doc.undoBtn && reaction(() => UndoManager.undoStack.slice(), () => (doc.undoBtn as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true }); + doc.redoBtn && reaction(() => UndoManager.redoStack.slice(), () => (doc.redoBtn as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); + + return doc; } public static loadCurrentUser() { -- cgit v1.2.3-70-g09d2