From f504934782b6458585148e3412b5fef975515931 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 23 Aug 2020 16:26:28 -0400 Subject: added settings for default text titles. fixed image audio annotatoins. fixed captions to not set title. added properties buttons for layout options and removed template layout button. fixed warnings. --- src/client/views/linking/LinkMenu.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 8ecde959f..519b78add 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -93,7 +93,6 @@ export class LinkMenu extends React.Component { } render() { - console.log("computed", this.position.x, this.position.b); const sourceDoc = this.props.docView.props.Document; const groups: Map = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); return
-- cgit v1.2.3-70-g09d2 From 505ad0d2e2a37795f1877b2319a8ba3a1ce65d28 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 24 Aug 2020 11:21:20 -0400 Subject: cleaned up all library() calls to add icons. fixed import styles. fixed keyboard events for presentation views to trigger when no input box is the target. --- src/client/DocServer.ts | 2 +- src/client/apis/GoogleAuthenticationManager.tsx | 8 +- .../apis/google_docs/GooglePhotosClientUtils.ts | 2 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/GroupManager.tsx | 43 +++---- src/client/util/GroupMemberView.tsx | 22 ++-- .../util/Import & Export/DirectoryImportBox.tsx | 9 +- .../util/Import & Export/ImportMetadataEntry.tsx | 8 +- src/client/util/SettingsManager.tsx | 30 +++-- src/client/util/SharingManager.tsx | 53 ++++---- src/client/views/AntimodeMenu.tsx | 2 +- src/client/views/ContextMenu.tsx | 5 - src/client/views/ContextMenuItem.tsx | 7 +- src/client/views/DictationOverlay.tsx | 2 +- src/client/views/DocumentButtonBar.tsx | 32 ++--- src/client/views/DocumentDecorations.tsx | 43 ++----- src/client/views/EditableView.tsx | 10 +- src/client/views/GestureOverlay.tsx | 2 +- src/client/views/GlobalKeyHandler.ts | 14 +-- src/client/views/InkingStroke.tsx | 17 +-- src/client/views/MainView.tsx | 49 ++++---- src/client/views/MainViewModal.tsx | 2 +- src/client/views/PropertiesButtons.tsx | 45 +++---- src/client/views/ScriptingRepl.tsx | 17 +-- .../views/collections/CollectionDockingView.tsx | 2 +- src/client/views/collections/CollectionMenu.tsx | 8 +- .../views/collections/CollectionSchemaCells.tsx | 58 ++++----- .../CollectionSchemaMovableTableHOC.tsx | 6 +- .../views/collections/CollectionSchemaView.tsx | 15 +-- .../CollectionStackingViewFieldColumn.tsx | 14 +-- src/client/views/collections/CollectionView.tsx | 7 +- .../views/collections/ParentDocumentSelector.tsx | 24 ++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 22 ++-- .../collectionFreeForm/FormatShapePane.tsx | 4 +- .../collectionFreeForm/MarqueeOptionsMenu.tsx | 9 +- .../collections/collectionFreeForm/MarqueeView.tsx | 11 +- .../collectionFreeForm/PropertiesView.tsx | 52 ++++---- src/client/views/linking/LinkEditor.tsx | 5 - src/client/views/linking/LinkMenu.tsx | 16 +-- src/client/views/linking/LinkMenuItem.tsx | 26 ++-- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FaceRectangles.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 15 +-- src/client/views/nodes/PresBox.tsx | 33 +++-- src/client/views/nodes/RadialMenuItem.tsx | 8 +- src/client/views/nodes/ScreenshotBox.tsx | 6 +- src/client/views/nodes/SliderBox.tsx | 5 - src/client/views/nodes/WebBox.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 13 +- .../formattedText/ProsemirrorExampleTransfer.ts | 2 +- .../views/nodes/formattedText/RichTextMenu.tsx | 19 ++- .../views/nodes/formattedText/RichTextRules.ts | 2 +- src/client/views/pdf/Annotation.tsx | 4 +- src/client/views/pdf/PDFMenu.tsx | 14 +-- src/client/views/pdf/PDFViewer.tsx | 18 +-- src/client/views/search/IconBar.tsx | 25 +--- src/client/views/search/IconButton.tsx | 140 ++++++--------------- src/client/views/webcam/DashWebRTCVideo.tsx | 24 ++-- src/mobile/AudioUpload.tsx | 4 +- src/mobile/ImageUpload.tsx | 20 +-- src/mobile/MobileInterface.tsx | 43 +++---- 61 files changed, 423 insertions(+), 685 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index dde75497c..9da5b8632 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -5,7 +5,7 @@ import { Utils, emptyFunction } from '../Utils'; import { SerializationHelper } from './util/SerializationHelper'; import { RefField } from '../fields/RefField'; import { Id, HandleUpdate, Parent } from '../fields/FieldSymbols'; -import GestureOverlay from './views/GestureOverlay'; +import { GestureOverlay } from './views/GestureOverlay'; import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { runInAction } from 'mobx'; import { ObjectField } from '../fields/ObjectField'; diff --git a/src/client/apis/GoogleAuthenticationManager.tsx b/src/client/apis/GoogleAuthenticationManager.tsx index 117d1fa1e..cda108058 100644 --- a/src/client/apis/GoogleAuthenticationManager.tsx +++ b/src/client/apis/GoogleAuthenticationManager.tsx @@ -1,17 +1,17 @@ -import { observable, action, reaction, runInAction, IReactionDisposer } from "mobx"; +import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; -import MainViewModal from "../views/MainViewModal"; import { Opt } from "../../fields/Doc"; import { Networking } from "../Network"; -import "./GoogleAuthenticationManager.scss"; import { Scripting } from "../util/Scripting"; +import { MainViewModal } from "../views/MainViewModal"; +import "./GoogleAuthenticationManager.scss"; const AuthenticationUrl = "https://accounts.google.com/o/oauth2/v2/auth"; const prompt = "Paste authorization code here..."; @observer -export default class GoogleAuthenticationManager extends React.Component<{}> { +export class GoogleAuthenticationManager extends React.Component<{}> { public static Instance: GoogleAuthenticationManager; private authenticationLink: Opt = undefined; @observable private openState = false; diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index 92eaf2e73..899e65a16 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -11,7 +11,7 @@ import { Utils } from "../../../Utils"; import { Docs, DocumentOptions, DocUtils } from "../../documents/Documents"; import { Networking } from "../../Network"; import { FormattedTextBox } from "../../views/nodes/formattedText/FormattedTextBox"; -import GoogleAuthenticationManager from "../GoogleAuthenticationManager"; +import { GoogleAuthenticationManager } from "../GoogleAuthenticationManager"; import Photos = require('googlephotos'); export namespace GooglePhotos { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 3ee0c7003..be584c3cf 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -908,7 +908,7 @@ export class CurrentUserUtils { // Import sidebar is where shared documents are contained static setupImportSidebar(doc: Doc) { if (doc["sidebar-import-documents"] === undefined) { - doc["sidebar-import-documents"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Imported Documents", forceActive: true, _showTitle: "title", childDropAction: "alias", _yMargin: 30, lockedPosition: true, _chromeStatus: "disabled", system: true, _height: 500 })); + doc["sidebar-import-documents"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Imported Documents", forceActive: true, _showTitle: "title", childDropAction: "alias", _autoHeight: true, _yMargin: 30, lockedPosition: true, _chromeStatus: "disabled", system: true })); } if (doc["sidebar-import"] === undefined) { const uploads = Cast(doc["sidebar-import-documents"], Doc, null); diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index d03989675..612ca7be7 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -1,24 +1,19 @@ -import * as React from "react"; -import { observable, action, runInAction, computed } from "mobx"; -import { SelectionManager } from "./SelectionManager"; -import MainViewModal from "../views/MainViewModal"; -import { observer } from "mobx-react"; -import { Doc, DocListCast, Opt, DocListCastAsync } from "../../fields/Doc"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import * as fa from '@fortawesome/free-solid-svg-icons'; -import { library } from "@fortawesome/fontawesome-svg-core"; -import SharingManager, { User } from "./SharingManager"; -import { Utils } from "../../Utils"; -import * as RequestPromise from "request-promise"; +import { action, computed, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; import Select from 'react-select'; -import "./GroupManager.scss"; -import { StrCast, Cast } from "../../fields/Types"; -import GroupMemberView from "./GroupMemberView"; +import * as RequestPromise from "request-promise"; +import { Doc, DocListCast, DocListCastAsync, Opt } from "../../fields/Doc"; +import { Cast, StrCast } from "../../fields/Types"; import { setGroups } from "../../fields/util"; +import { Utils } from "../../Utils"; import { DocServer } from "../DocServer"; +import { MainViewModal } from "../views/MainViewModal"; import { TaskCompletionBox } from "../views/nodes/TaskCompletedBox"; - -library.add(fa.faPlus, fa.faTimes, fa.faInfoCircle, fa.faCaretUp, fa.faCaretRight, fa.faCaretDown); +import "./GroupManager.scss"; +import { GroupMemberView } from "./GroupMemberView"; +import { SharingManager, User } from "./SharingManager"; /** * Interface for options for the react-select component @@ -29,7 +24,7 @@ export interface UserOptions { } @observer -export default class GroupManager extends React.Component<{}> { +export class GroupManager extends React.Component<{}> { static Instance: GroupManager; @observable isOpen: boolean = false; // whether the GroupManager is to be displayed or not. @@ -314,7 +309,7 @@ export default class GroupManager extends React.Component<{}> {
{ this.createGroupModalOpen = false; TaskCompletionBox.taskCompleted = false; })}> - +
{

Manage Groups

- +
this.groupSort = this.groupSort === "ascending" ? "descending" : this.groupSort === "descending" ? "none" : "ascending")}> - Name {this.groupSort === "ascending" ? - : this.groupSort === "descending" ? - : + Name {this.groupSort === "ascending" ? + : this.groupSort === "descending" ? + : }
@@ -421,7 +416,7 @@ export default class GroupManager extends React.Component<{}> { >
{group.groupName}
this.currentGroup = group)}> - +
)} diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx index 531ef988a..4ead01e9f 100644 --- a/src/client/util/GroupMemberView.tsx +++ b/src/client/util/GroupMemberView.tsx @@ -1,25 +1,21 @@ -import * as React from "react"; -import MainViewModal from "../views/MainViewModal"; -import { observer } from "mobx-react"; -import GroupManager, { UserOptions } from "./GroupManager"; -import { library } from "@fortawesome/fontawesome-svg-core"; -import { StrCast } from "../../fields/Types"; -import { action, observable } from "mobx"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import * as fa from '@fortawesome/free-solid-svg-icons'; +import { action, observable } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; import Select from "react-select"; import { Doc } from "../../fields/Doc"; +import { StrCast } from "../../fields/Types"; +import { MainViewModal } from "../views/MainViewModal"; +import { GroupManager, UserOptions } from "./GroupManager"; import "./GroupMemberView.scss"; -library.add(fa.faTimes, fa.faTrashAlt); - interface GroupMemberViewProps { group: Doc; onCloseButtonClick: () => void; } @observer -export default class GroupMemberView extends React.Component { +export class GroupMemberView extends React.Component { @observable private memberSort: "ascending" | "descending" | "none" = "none"; @@ -43,7 +39,7 @@ export default class GroupMemberView extends React.Component
- +
{GroupManager.Instance.hasEditAccess(this.props.group) ?
@@ -88,7 +84,7 @@ export default class GroupMemberView extends React.Component {hasEditAccess ?
GroupManager.Instance.removeMemberFromGroup(this.props.group, member)}> - +
: null}
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 77f13e9f4..d04270afa 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -1,5 +1,3 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCloudUploadAlt, faPlus, faTag } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { BatchedArray } from "array-batcher"; import "fs"; @@ -47,7 +45,6 @@ export class DirectoryImportBox extends React.Component { constructor(props: FieldViewProps) { super(props); - library.add(faTag, faPlus); const doc = this.props.Document; this.editingMetadata = this.editingMetadata || false; this.persistent = this.persistent || false; @@ -301,7 +298,7 @@ export class DirectoryImportBox extends React.Component { opacity: uploading ? 0 : 1, transition: "0.4s opacity ease" }}> - +
{ opacity: uploading ? 0 : 1, transition: "0.4s opacity ease" }} - icon={isEditing ? faCloudUploadAlt : faTag} + icon={isEditing ? "cloud-upload-alt" : "tag"} color="#FFFFFF" size={"1x"} /> @@ -399,7 +396,7 @@ export class DirectoryImportBox extends React.Component { marginLeft: 6.4, marginTop: 5.2 }} - icon={faPlus} + icon={"plus"} size={"1x"} /> diff --git a/src/client/util/Import & Export/ImportMetadataEntry.tsx b/src/client/util/Import & Export/ImportMetadataEntry.tsx index dcb94e2e0..1870213b9 100644 --- a/src/client/util/Import & Export/ImportMetadataEntry.tsx +++ b/src/client/util/Import & Export/ImportMetadataEntry.tsx @@ -4,7 +4,6 @@ import { EditableView } from "../../views/EditableView"; import { action, computed } from "mobx"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; -import { library } from '@fortawesome/fontawesome-svg-core'; import { Doc } from "../../../fields/Doc"; import { StrCast, BoolCast } from "../../../fields/Types"; @@ -24,11 +23,6 @@ export default class ImportMetadataEntry extends React.Component private valueRef = React.createRef(); private checkRef = React.createRef(); - constructor(props: KeyValueProps) { - super(props); - library.add(faPlus); - } - @computed public get valid() { return (this.key.length > 0 && this.key !== keyPlaceholder) && (this.value.length > 0 && this.value !== valuePlaceholder); @@ -132,7 +126,7 @@ export default class ImportMetadataEntry extends React.Component
this.props.remove(this)} title={"Delete Entry"}> { +export class SettingsManager extends React.Component<{}> { public static Instance: SettingsManager; static _settingsStyle = addStyleSheet(); @observable private isOpen = false; @@ -166,7 +164,7 @@ export default class SettingsManager extends React.Component<{}> { {CurrentUserUtils.GuestDashboard ? "Exit" : "Log Out"}
- +
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index b9918e900..a73cb63d0 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -1,29 +1,24 @@ -import { observable, runInAction, action } from "mobx"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; import * as React from "react"; -import MainViewModal from "../views/MainViewModal"; -import { Doc, Opt, AclAdmin, AclPrivate, DocListCast, DataSym } from "../../fields/Doc"; -import { DocServer } from "../DocServer"; -import { Cast, StrCast } from "../../fields/Types"; +import Select from "react-select"; import * as RequestPromise from "request-promise"; +import { AclAdmin, AclPrivate, DataSym, Doc, DocListCast, Opt } from "../../fields/Doc"; +import { List } from "../../fields/List"; +import { Cast, StrCast } from "../../fields/Types"; +import { distributeAcls, GetEffectiveAcl, SharingPermissions } from "../../fields/util"; import { Utils } from "../../Utils"; -import "./SharingManager.scss"; -import { observer } from "mobx-react"; -import * as fa from '@fortawesome/free-solid-svg-icons'; -import { DocumentView } from "../views/nodes/DocumentView"; -import { SelectionManager } from "./SelectionManager"; -import { DocumentManager } from "./DocumentManager"; +import { DocServer } from "../DocServer"; import { CollectionView } from "../views/collections/CollectionView"; import { DictationOverlay } from "../views/DictationOverlay"; -import GroupManager, { UserOptions } from "./GroupManager"; -import GroupMemberView from "./GroupMemberView"; -import Select from "react-select"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { List } from "../../fields/List"; -import { distributeAcls, SharingPermissions, GetEffectiveAcl } from "../../fields/util"; +import { MainViewModal } from "../views/MainViewModal"; +import { DocumentView } from "../views/nodes/DocumentView"; import { TaskCompletionBox } from "../views/nodes/TaskCompletedBox"; -import { library } from "@fortawesome/fontawesome-svg-core"; - -library.add(fa.faInfoCircle, fa.faCaretUp, fa.faCaretRight, fa.faCaretDown); +import { DocumentManager } from "./DocumentManager"; +import { GroupManager, UserOptions } from "./GroupManager"; +import { GroupMemberView } from "./GroupMemberView"; +import "./SharingManager.scss"; export interface User { email: string; @@ -58,7 +53,7 @@ interface ValidatedUser { @observer -export default class SharingManager extends React.Component<{}> { +export class SharingManager extends React.Component<{}> { public static Instance: SharingManager; @observable private isOpen = false; // whether the SharingManager modal is open or not @observable private users: ValidatedUser[] = []; // the list of users with notificationDocs @@ -486,7 +481,7 @@ export default class SharingManager extends React.Component<{}> { >
{group.groupName}
GroupManager.Instance.currentGroup = group)}> - +
setter(e.target.value)} /> + onChange={e => { + setter(e.target.value); + }} + onKeyPress={e => { + e.stopPropagation(); + }} />
this.upDownButtons("up", key)))} > diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index ed64bde32..11a905fb6 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -1,5 +1,3 @@ -import { library } from "@fortawesome/fontawesome-svg-core"; -import { faArrowLeft, faCog, faEllipsisV, faExchangeAlt, faPlus, faTable, faTimes, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; import { action, computed, observable } from "mobx"; @@ -12,9 +10,6 @@ import { undoBatch } from "../../util/UndoManager"; import './LinkEditor.scss'; import React = require("react"); -library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus); - - interface GroupTypesDropdownProps { groupType: string; setGroupType: (group: string) => void; diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 519b78add..31d08edae 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -1,18 +1,14 @@ -import { action, observable, computed } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { DocumentView } from "../nodes/DocumentView"; -import { LinkEditor } from "./LinkEditor"; -import './LinkMenu.scss'; -import React = require("react"); import { Doc } from "../../../fields/Doc"; import { LinkManager } from "../../util/LinkManager"; -import { LinkMenuGroup } from "./LinkMenuGroup"; -import { faTrash } from '@fortawesome/free-solid-svg-icons'; -import { library } from "@fortawesome/fontawesome-svg-core"; import { DocumentLinksButton } from "../nodes/DocumentLinksButton"; +import { DocumentView } from "../nodes/DocumentView"; import { LinkDocPreview } from "../nodes/LinkDocPreview"; - -library.add(faTrash); +import { LinkEditor } from "./LinkEditor"; +import './LinkMenu.scss'; +import { LinkMenuGroup } from "./LinkMenuGroup"; +import React = require("react"); interface Props { docView: DocumentView; diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 21c666a4d..a77122456 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -1,27 +1,23 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowRight, faChevronDown, faChevronUp, faEdit, faEye, faTimes, faPencilAlt, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon, FontAwesomeIconProps } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; import { action, observable, runInAction } from 'mobx'; import { observer } from "mobx-react"; -import { Doc, DocListCast, Opt } from '../../../fields/Doc'; +import { Doc, DocListCast } from '../../../fields/Doc'; import { Cast, StrCast } from '../../../fields/Types'; +import { WebField } from '../../../fields/URLField'; +import { emptyFunction, setupMoveUpEvents } from '../../../Utils'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; +import { Hypothesis } from '../../util/HypothesisUtils'; import { LinkManager } from '../../util/LinkManager'; +import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; -import './LinkMenuItem.scss'; -import React = require("react"); -import { DocumentManager } from '../../util/DocumentManager'; -import { setupMoveUpEvents, emptyFunction, Utils, simulateMouseClick } from '../../../Utils'; -import { DocumentView } from '../nodes/DocumentView'; import { DocumentLinksButton } from '../nodes/DocumentLinksButton'; +import { DocumentView } from '../nodes/DocumentView'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; -import { Hypothesis } from '../../util/HypothesisUtils'; -import { Id } from '../../../fields/FieldSymbols'; -import { Tooltip } from '@material-ui/core'; -import { DocumentType } from '../../documents/DocumentTypes'; -import { undoBatch } from '../../util/UndoManager'; -import { WebField } from '../../../fields/URLField'; -library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash); +import './LinkMenuItem.scss'; +import React = require("react"); interface LinkMenuItemProps { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index db6d30aac..80d83c3cb 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -21,7 +21,7 @@ import { InteractionUtils } from '../../util/InteractionUtils'; import { LinkManager } from '../../util/LinkManager'; import { Scripting } from '../../util/Scripting'; import { SelectionManager } from "../../util/SelectionManager"; -import SharingManager from '../../util/SharingManager'; +import { SharingManager } from '../../util/SharingManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from "../../util/Transform"; import { undoBatch, UndoManager } from "../../util/UndoManager"; diff --git a/src/client/views/nodes/FaceRectangles.tsx b/src/client/views/nodes/FaceRectangles.tsx index 92ca276cb..0d1e063af 100644 --- a/src/client/views/nodes/FaceRectangles.tsx +++ b/src/client/views/nodes/FaceRectangles.tsx @@ -17,7 +17,7 @@ export interface RectangleTemplate { } @observer -export default class FaceRectangles extends React.Component { +export class FaceRectangles extends React.Component { render() { const faces = DocListCast(this.props.document.faces); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 5f31f8c8d..410033197 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,6 +1,3 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEye } from '@fortawesome/free-regular-svg-icons'; -import { faAsterisk, faBrain, faFileAudio, faImage, faPaintBrush } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, runInAction } from 'mobx'; import { observer } from "mobx-react"; @@ -14,7 +11,8 @@ import { ComputedField } from '../../../fields/ScriptField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { AudioField, ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnOne, Utils, returnZero } from '../../../Utils'; +import { emptyFunction, returnOne, returnZero, Utils } from '../../../Utils'; +import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { CognitiveServices, Confidence, Service, Tag } from '../../cognitive_services/CognitiveServices'; import { Docs } from '../../documents/Documents'; import { Networking } from '../../Network'; @@ -24,20 +22,15 @@ import { ContextMenu } from "../../views/ContextMenu"; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; -import FaceRectangles from './FaceRectangles'; +import { FaceRectangles } from './FaceRectangles'; import { FieldView, FieldViewProps } from './FieldView'; import "./ImageBox.scss"; import React = require("react"); -import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; const requestImageSize = require('../../util/request-image-size'); const path = require('path'); const { Howl } = require('howler'); -library.add(faImage, faEye as any, faPaintBrush, faBrain); -library.add(faFileAudio, faAsterisk); - - export const pageSchema = createSchema({ curPage: "number", fitWidth: "boolean", @@ -431,7 +424,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent + icon={!DocListCast(this.dataDoc[this.fieldKey + "-audioAnnotations"]).length ? "microphone" : "file-audio"} size="sm" />
} {this.considerDownloadIcon} {this.considerGooglePhotosLink()} diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 050ecfc49..1228a285e 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -87,14 +87,12 @@ export class PresBox extends ViewBoxBaseComponent } else { return undefined; } } @computed get isPres(): boolean { + document.removeEventListener("keydown", this.keyEvents, true); if (this.selectedDoc?.type === DocumentType.PRES) { - document.removeEventListener("keydown", this.keyEvents, true); document.addEventListener("keydown", this.keyEvents, true); return true; - } else { - document.removeEventListener("keydown", this.keyEvents, true); - return false; } + return false; } @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; } @@ -373,7 +371,7 @@ export class PresBox extends ViewBoxBaseComponent if (this.layoutDoc.presStatus === 'auto' && !this.layoutDoc.presLoop) this.layoutDoc.presStatus = "manual"; else if (this.layoutDoc.presLoop) this.startAutoPres(0); }, duration); - }; + } } }; this.layoutDoc.presStatus = "auto"; @@ -614,6 +612,7 @@ export class PresBox extends ViewBoxBaseComponent // Key for when the presentaiton is active @action keyEvents = (e: KeyboardEvent) => { + if (e.target instanceof HTMLInputElement) return; let handled = false; const anchorNode = document.activeElement as HTMLDivElement; if (anchorNode && anchorNode.className?.includes("lm_title")) return; @@ -629,10 +628,12 @@ export class PresBox extends ViewBoxBaseComponent handled = true; } } if (e.keyCode === 37 || e.keyCode === 38) { // left(37) / a(65) / up(38) to go back - this.back(); if (this._presTimer) clearTimeout(this._presTimer); + this.back(); + if (this._presTimer) clearTimeout(this._presTimer); handled = true; } if (e.keyCode === 39 || e.keyCode === 40) { // right (39) / d(68) / down(40) to go to next - this.next(); if (this._presTimer) clearTimeout(this._presTimer); + this.next(); + if (this._presTimer) clearTimeout(this._presTimer); handled = true; } if (e.keyCode === 32) { // spacebar to 'present' or autoplay if (this.layoutDoc.presStatus !== "edit") this.startAutoPres(0); @@ -640,9 +641,7 @@ export class PresBox extends ViewBoxBaseComponent handled = true; } if (e.keyCode === 8) { // delete selected items if (this.layoutDoc.presStatus === "edit") { - this._selectedArray.forEach((doc, i) => { - this.removeDocument(doc); - }); + this._selectedArray.forEach((doc, i) => this.removeDocument(doc)); this._selectedArray = []; this._eleArray = []; this._dragArray = []; @@ -815,7 +814,7 @@ export class PresBox extends ViewBoxBaseComponent
{ document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e) => this.setTransitionTime(e.target.value))} /> s
@@ -845,7 +844,7 @@ export class PresBox extends ViewBoxBaseComponent
{ document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e) => this.setDurationTime(e.target.value))} /> s
@@ -974,7 +973,7 @@ export class PresBox extends ViewBoxBaseComponent { document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e: React.ChangeEvent) => { const val = e.target.value; activeItem.presPinViewX = Number(val); })} />
@@ -984,7 +983,7 @@ export class PresBox extends ViewBoxBaseComponent { document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e: React.ChangeEvent) => { const val = e.target.value; activeItem.presPinViewY = Number(val); })} />
@@ -994,7 +993,7 @@ export class PresBox extends ViewBoxBaseComponent { document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e: React.ChangeEvent) => { const val = e.target.value; activeItem.presPinViewScale = Number(val); })} />
@@ -1044,9 +1043,7 @@ export class PresBox extends ViewBoxBaseComponent
Slide Title:

{ - document.removeEventListener("keydown", this.keyEvents, true); - }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={(e) => { e.stopPropagation(); e.preventDefault(); diff --git a/src/client/views/nodes/RadialMenuItem.tsx b/src/client/views/nodes/RadialMenuItem.tsx index bd5b3bff4..8876b4879 100644 --- a/src/client/views/nodes/RadialMenuItem.tsx +++ b/src/client/views/nodes/RadialMenuItem.tsx @@ -1,13 +1,9 @@ import React = require("react"); -import { observable, action } from "mobx"; -import { observer } from "mobx-react"; -import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { observer } from "mobx-react"; import { UndoManager } from "../../util/UndoManager"; -library.add(faAngleRight); - export interface RadialMenuProps { description: string; event: (stuff?: any) => void; diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 1cd29d795..866e41ee0 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -1,12 +1,11 @@ import React = require("react"); -import { library } from "@fortawesome/fontawesome-svg-core"; -import { faVideo } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, IReactionDisposer, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as rp from 'request-promise'; import { Doc } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; +import { InkTool } from "../../../fields/InkField"; import { listSpec, makeInterface } from "../../../fields/Schema"; import { Cast, NumCast } from "../../../fields/Types"; import { VideoField } from "../../../fields/URLField"; @@ -18,14 +17,11 @@ import { ContextMenuProps } from "../ContextMenuItem"; import { ViewBoxBaseComponent } from "../DocComponent"; import { FieldView, FieldViewProps } from './FieldView'; import "./ScreenshotBox.scss"; -import { InkTool } from "../../../fields/InkField"; const path = require('path'); type ScreenshotDocument = makeInterface<[typeof documentSchema]>; const ScreenshotDocument = makeInterface(documentSchema); -library.add(faVideo); - @observer export class ScreenshotBox extends ViewBoxBaseComponent(ScreenshotDocument) { private _reactionDisposer?: IReactionDisposer; diff --git a/src/client/views/nodes/SliderBox.tsx b/src/client/views/nodes/SliderBox.tsx index 45cdfc5ad..d13680046 100644 --- a/src/client/views/nodes/SliderBox.tsx +++ b/src/client/views/nodes/SliderBox.tsx @@ -1,5 +1,3 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit } from '@fortawesome/free-regular-svg-icons'; import { runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; @@ -16,9 +14,6 @@ import { FieldView, FieldViewProps } from './FieldView'; import { Handle, Tick, TooltipRail, Track } from './SliderBox-components'; import './SliderBox.scss'; - -library.add(faEdit as any); - const SliderSchema = createSchema({ _sliderMin: "number", _sliderMax: "number", diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 7d7426e31..f0e3a2b54 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -24,8 +24,8 @@ import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { DocumentDecorations } from "../DocumentDecorations"; -import Annotation from "../pdf/Annotation"; -import PDFMenu from "../pdf/PDFMenu"; +import { Annotation } from "../pdf/Annotation"; +import { PDFMenu } from "../pdf/PDFMenu"; import { PdfViewerMarquee } from "../pdf/PDFViewer"; import { FieldView, FieldViewProps } from './FieldView'; import "./WebBox.scss"; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 77483a179..063cdb0cc 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1,5 +1,3 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit, faSmile, faTextHeight, faUpload } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { isEqual } from "lodash"; import { action, computed, IReactionDisposer, Lambda, observable, reaction, runInAction, trace } from "mobx"; @@ -22,7 +20,7 @@ import { InkTool } from '../../../../fields/InkField'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { RichTextField } from "../../../../fields/RichTextField"; import { RichTextUtils } from '../../../../fields/RichTextUtils'; -import { createSchema, makeInterface } from "../../../../fields/Schema"; +import { makeInterface } from "../../../../fields/Schema"; import { Cast, DateCast, NumCast, StrCast, ScriptCast, BoolCast } from "../../../../fields/Types"; import { TraceMobx, OVERRIDE_ACL, GetEffectiveAcl } from '../../../../fields/util'; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, returnZero, Utils, setupMoveUpEvents } from '../../../../Utils'; @@ -33,8 +31,8 @@ import { DocumentType } from '../../../documents/DocumentTypes'; import { DictationManager } from '../../../util/DictationManager'; import { DragManager } from "../../../util/DragManager"; import { makeTemplate } from '../../../util/DropConverter'; -import buildKeymap, { updateBullets } from "./ProsemirrorExampleTransfer"; -import RichTextMenu, { RichTextMenuPlugin } from './RichTextMenu'; +import { buildKeymap, updateBullets } from "./ProsemirrorExampleTransfer"; +import { RichTextMenu, RichTextMenuPlugin } from './RichTextMenu'; import { RichTextRules } from "./RichTextRules"; //import { DashDocView } from "./DashDocView"; @@ -61,9 +59,6 @@ import { FormattedTextBoxComment, formattedTextBoxCommentPlugin, findLinkMark } import React = require("react"); import { DocumentManager } from '../../../util/DocumentManager'; -library.add(faEdit); -library.add(faSmile, faTextHeight, faUpload); - export interface FormattedTextBoxProps { makeLink?: () => Opt; // bcz: hack: notifies the text document when the container has made a link. allows the text doc to react and setup a hyeprlink for any selected text hideOnLeave?: boolean; // used by DocumentView for setting caption's hide on leave (bcz: would prefer to have caption-hideOnLeave field set or something similar) @@ -915,7 +910,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return linkIndex !== -1 && marks[linkIndex].attrs.allLinks.find((item: { href: string }) => scrollToLinkID === item.href.replace(/.*\/doc\//, "")) ? node : undefined; }; - let start = 0; + const start = 0; if (this._editorView && scrollToLinkID) { const editor = this._editorView; const ret = findLinkFrag(editor.state.doc.content, editor); diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts index 8faf752b4..0eb675b4e 100644 --- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts +++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts @@ -33,7 +33,7 @@ export let updateBullets = (tx2: Transaction, schema: Schema, assignedMapStyle?: return tx2; }; -export default function buildKeymap>(schema: S, props: any, mapKeys?: KeyMap): KeyMap { +export function buildKeymap>(schema: S, props: any, mapKeys?: KeyMap): KeyMap { const keys: { [key: string]: any } = {}; function bind(key: string, cmd: any) { diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 96628949a..a0e2d4351 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -1,8 +1,8 @@ import React = require("react"); -import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faBold, faCaretDown, faChevronLeft, faEyeDropper, faHighlighter, faOutdent, faIndent, faHandPointLeft, faHandPointRight, faItalic, faLink, faPaintRoller, faPalette, faStrikethrough, faSubscript, faSuperscript, faUnderline } from "@fortawesome/free-solid-svg-icons"; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, observable, IReactionDisposer, reaction } from "mobx"; +import { Tooltip } from "@material-ui/core"; +import { action, IReactionDisposer, observable, reaction } from "mobx"; import { observer } from "mobx-react"; import { lift, wrapIn } from "prosemirror-commands"; import { Mark, MarkType, Node as ProsNode, NodeType, ResolvedPos } from "prosemirror-model"; @@ -11,27 +11,24 @@ import { EditorState, NodeSelection, TextSelection } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc } from "../../../../fields/Doc"; import { DarkPastelSchemaPalette, PastelSchemaPalette } from '../../../../fields/SchemaHeaderField'; -import { Cast, StrCast, BoolCast, NumCast } from "../../../../fields/Types"; +import { Cast, StrCast } from "../../../../fields/Types"; +import { TraceMobx } from "../../../../fields/util"; import { unimplementedFunction, Utils } from "../../../../Utils"; import { DocServer } from "../../../DocServer"; import { LinkManager } from "../../../util/LinkManager"; import { SelectionManager } from "../../../util/SelectionManager"; -import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu"; +import { undoBatch, UndoManager } from "../../../util/UndoManager"; +import { AntimodeMenu, AntimodeMenuProps } from "../../AntimodeMenu"; import { FieldViewProps } from "../FieldView"; import { FormattedTextBox, FormattedTextBoxProps } from "./FormattedTextBox"; import { updateBullets } from "./ProsemirrorExampleTransfer"; import "./RichTextMenu.scss"; import { schema } from "./schema_rts"; -import { TraceMobx } from "../../../../fields/util"; -import { UndoManager, undoBatch } from "../../../util/UndoManager"; -import { Tooltip } from "@material-ui/core"; const { toggleMark } = require("prosemirror-commands"); -library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faOutdent, faIndent, faHandPointLeft, faHandPointRight, faEyeDropper, faCaretDown, faPalette, faHighlighter, faLink, faPaintRoller); - @observer -export default class RichTextMenu extends AntimodeMenu { +export class RichTextMenu extends AntimodeMenu { static Instance: RichTextMenu; public overMenu: boolean = false; // kind of hacky way to prevent selects not being selectable diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index a455516a3..7e632a0ee 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -9,7 +9,7 @@ import { DocServer } from "../../../DocServer"; import { Docs, DocUtils } from "../../../documents/Documents"; import { FormattedTextBox } from "./FormattedTextBox"; import { wrappingInputRule } from "./prosemirrorPatches"; -import RichTextMenu from "./RichTextMenu"; +import { RichTextMenu } from "./RichTextMenu"; import { schema } from "./schema_rts"; import { List } from "../../../../fields/List"; diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index d29b638e6..98638ecc2 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -6,7 +6,7 @@ import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; import { Cast, FieldValue, NumCast, StrCast } from "../../../fields/Types"; import { DocumentManager } from "../../util/DocumentManager"; -import PDFMenu from "./PDFMenu"; +import { PDFMenu } from "./PDFMenu"; import "./Annotation.scss"; interface IAnnotationProps { @@ -19,7 +19,7 @@ interface IAnnotationProps { } @observer -export default +export class Annotation extends React.Component { render() { return DocListCast(this.props.anno.annotations).map(a => ( diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index 0f7b0a688..32dd376ac 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -1,17 +1,17 @@ import React = require("react"); -import "./PDFMenu.scss"; -import { observable, action, computed, } from "mobx"; -import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { unimplementedFunction, returnFalse, Utils } from "../../../Utils"; -import AntimodeMenu, { AntimodeMenuProps } from "../AntimodeMenu"; -import { Doc, Opt } from "../../../fields/Doc"; +import { action, computed, observable } from "mobx"; +import { observer } from "mobx-react"; import { ColorState } from "react-color"; +import { Doc, Opt } from "../../../fields/Doc"; +import { returnFalse, unimplementedFunction, Utils } from "../../../Utils"; +import { AntimodeMenu, AntimodeMenuProps } from "../AntimodeMenu"; import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu"; +import "./PDFMenu.scss"; @observer -export default class PDFMenu extends AntimodeMenu { +export class PDFMenu extends AntimodeMenu { static Instance: PDFMenu; private _commentCont = React.createRef(); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 201333d95..c8f98e249 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -1,39 +1,39 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -const pdfjs = require('pdfjs-dist/es5/build/pdf.js'); import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; import { Dictionary } from "typescript-collections"; -import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym, AclAddonly, AclEdit, AclAdmin, DataSym } from "../../../fields/Doc"; +import { AclAddonly, AclAdmin, AclEdit, DataSym, Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; import { InkTool } from "../../../fields/InkField"; import { List } from "../../../fields/List"; -import { createSchema, makeInterface, listSpec } from "../../../fields/Schema"; -import { ScriptField, ComputedField } from "../../../fields/ScriptField"; +import { createSchema, makeInterface } from "../../../fields/Schema"; +import { ScriptField } from "../../../fields/ScriptField"; import { Cast, NumCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; -import { TraceMobx, GetEffectiveAcl } from "../../../fields/util"; +import { GetEffectiveAcl, TraceMobx } from "../../../fields/util"; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; +import { Networking } from "../../Network"; import { DragManager } from "../../util/DragManager"; import { CompiledScript, CompileScript } from "../../util/Scripting"; import { SelectionManager } from "../../util/SelectionManager"; +import { SnappingManager } from "../../util/SnappingManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; import { CollectionView } from "../collections/CollectionView"; import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { DocumentDecorations } from "../DocumentDecorations"; -import Annotation from "./Annotation"; -import PDFMenu from "./PDFMenu"; +import { Annotation } from "./Annotation"; +import { PDFMenu } from "./PDFMenu"; import "./PDFViewer.scss"; +const pdfjs = require('pdfjs-dist/es5/build/pdf.js'); import React = require("react"); -import { SnappingManager } from "../../util/SnappingManager"; const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer"); const pdfjsLib = require("pdfjs-dist"); -import { Networking } from "../../Network"; export const pageSchema = createSchema({ curPage: "number", diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx index 9b7cf2fc6..f1dd106a7 100644 --- a/src/client/views/search/IconBar.tsx +++ b/src/client/views/search/IconBar.tsx @@ -1,28 +1,11 @@ -import * as React from 'react'; +import { action, observable } from 'mobx'; import { observer } from 'mobx-react'; -import { observable, action } from 'mobx'; +import * as React from 'react'; +import { DocumentType } from "../../documents/DocumentTypes"; // import "./SearchBox.scss"; import "./IconBar.scss"; -import "./IconButton.scss"; -import { faSearch, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMusic, faLink, faChartBar, faGlobeAsia, faBan, faTimesCircle, faCheckCircle } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { library } from '@fortawesome/fontawesome-svg-core'; -import * as _ from "lodash"; import { IconButton } from './IconButton'; -import { DocumentType } from "../../documents/DocumentTypes"; - - -library.add(faSearch); -library.add(faObjectGroup); -library.add(faImage); -library.add(faStickyNote); -library.add(faFilePdf); -library.add(faFilm); -library.add(faMusic); -library.add(faLink); -library.add(faChartBar); -library.add(faGlobeAsia); -library.add(faBan); +import "./IconButton.scss"; export interface IconBarProps { setIcons: (icons: string[]) => void; diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index 52641c543..349690b20 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -1,30 +1,14 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { observable, action, runInAction, IReactionDisposer, reaction } from 'mobx'; -import "./SearchBox.scss"; -import "./IconButton.scss"; -import { faSearch, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMusic, faLink, faChartBar, faGlobeAsia, faBan, faVideo, faCaretDown } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { library, icon } from '@fortawesome/fontawesome-svg-core'; +import * as _ from "lodash"; +import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; import { DocumentType } from "../../documents/DocumentTypes"; import '../globalCssVariables.scss'; -import * as _ from "lodash"; import { IconBar } from './IconBar'; -import { props } from 'bluebird'; -import { Search } from '../../../server/Search'; -import { gravity } from 'sharp'; - -library.add(faSearch); -library.add(faObjectGroup); -library.add(faImage); -library.add(faStickyNote); -library.add(faFilePdf); -library.add(faFilm); -library.add(faMusic); -library.add(faLink); -library.add(faChartBar); -library.add(faGlobeAsia); -library.add(faBan); +import "./IconButton.scss"; +import "./SearchBox.scss"; +import { Font } from '@react-pdf/renderer'; interface IconButtonProps { type: string; @@ -47,59 +31,46 @@ export class IconButton extends React.Component{ componentDidMount = () => { this._resetReaction = reaction( () => IconBar.Instance._resetClicked, - () => { + action(() => { if (IconBar.Instance._resetClicked) { - runInAction(() => { - this.reset(); - IconBar.Instance._reset++; - if (IconBar.Instance._reset === 9) { - IconBar.Instance._reset = 0; - IconBar.Instance._resetClicked = false; - } - }); + this._isSelected = false; + IconBar.Instance._reset++; + if (IconBar.Instance._reset === 9) { + IconBar.Instance._reset = 0; + IconBar.Instance._resetClicked = false; + } } - }, + }), ); + this._selectAllReaction = reaction( () => IconBar.Instance._selectAllClicked, - () => { + action(() => { if (IconBar.Instance._selectAllClicked) { - runInAction(() => { - this.select(); - IconBar.Instance._select++; - if (IconBar.Instance._select === 9) { - IconBar.Instance._select = 0; - IconBar.Instance._selectAllClicked = false; - } - }); + this._isSelected = true; + IconBar.Instance._select++; + if (IconBar.Instance._select === 9) { + IconBar.Instance._select = 0; + IconBar.Instance._selectAllClicked = false; + } } - }, + }), ); } @action.bound getIcon() { switch (this.props.type) { - case (DocumentType.NONE): - return faBan; - case (DocumentType.AUDIO): - return faMusic; - case (DocumentType.COL): - return faObjectGroup; - case (DocumentType.IMG): - return faImage; - case (DocumentType.LINK): - return faLink; - case (DocumentType.PDF): - return faFilePdf; - case (DocumentType.RTF): - return faStickyNote; - case (DocumentType.VID): - return faVideo; - case (DocumentType.WEB): - return faGlobeAsia; - default: - return faCaretDown; + case (DocumentType.NONE): return "ban"; + case (DocumentType.AUDIO): return "music"; + case (DocumentType.COL): return "object-group"; + case (DocumentType.IMG): return "image"; + case (DocumentType.LINK): return "link"; + case (DocumentType.PDF): return "file-pdf"; + case (DocumentType.RTF): return "sticky-note"; + case (DocumentType.VID): return "video"; + case (DocumentType.WEB): return "globe-asia"; + default: return "caret-down"; } } @@ -136,53 +107,16 @@ export class IconButton extends React.Component{ //backgroundColor: "rgb(178, 206, 248)" //$darker-alt-accent }; - @action.bound - public reset() { this._isSelected = false; } - - @action.bound - public select() { this._isSelected = true; } - - @action - onMouseLeave = () => { this._hover = false; } - - @action - onMouseEnter = () => { this._hover = true; } - - getFA = () => { - switch (this.props.type) { - case (DocumentType.NONE): - return (); - case (DocumentType.AUDIO): - return (); - case (DocumentType.COL): - return (); - case (DocumentType.IMG): - return (); - case (DocumentType.LINK): - return (); - case (DocumentType.PDF): - return (); - case (DocumentType.RTF): - return (); - case (DocumentType.VID): - return (); - case (DocumentType.WEB): - return (); - default: - return (); - } - } - render() { return (
this._hover = true} + onMouseLeave={() => this._hover = false} onClick={this.onClick}>
- {this.getFA()} +
{/*
{this.props.type}
*/}
diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx index 647e1ce6f..82c0e19c8 100644 --- a/src/client/views/webcam/DashWebRTCVideo.tsx +++ b/src/client/views/webcam/DashWebRTCVideo.tsx @@ -1,20 +1,16 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { CollectionFreeFormDocumentViewProps } from "../nodes/CollectionFreeFormDocumentView"; -import { FieldViewProps, FieldView } from "../nodes/FieldView"; -import { observable, action } from "mobx"; -import { DocumentDecorations } from "../DocumentDecorations"; -import "../../views/nodes/WebBox.scss"; -import "./DashWebRTCVideo.scss"; -import { initialize, hangup, refreshVideos } from "./WebCamLogic"; +import { faPhoneSlash, faSync } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faSync, faPhoneSlash } from "@fortawesome/free-solid-svg-icons"; +import { action, observable } from "mobx"; +import { observer } from "mobx-react"; import { Doc } from "../../../fields/Doc"; import { InkTool } from "../../../fields/InkField"; - -library.add(faSync); -library.add(faPhoneSlash); +import "../../views/nodes/WebBox.scss"; +import { DocumentDecorations } from "../DocumentDecorations"; +import { CollectionFreeFormDocumentViewProps } from "../nodes/CollectionFreeFormDocumentView"; +import { FieldView, FieldViewProps } from "../nodes/FieldView"; +import "./DashWebRTCVideo.scss"; +import { hangup, initialize, refreshVideos } from "./WebCamLogic"; +import React = require("react"); /** diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx index 738de09c6..c412059dd 100644 --- a/src/mobile/AudioUpload.tsx +++ b/src/mobile/AudioUpload.tsx @@ -7,14 +7,14 @@ import { Utils, emptyPath, returnFalse, emptyFunction, returnOne, returnZero, re import { Doc, Opt } from '../fields/Doc'; import { Cast, FieldValue } from '../fields/Types'; import { listSpec } from '../fields/Schema'; -import MainViewModal from '../client/views/MainViewModal'; +import { MainViewModal } from '../client/views/MainViewModal'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { nullAudio } from '../fields/URLField'; import { Transform } from '../client/util/Transform'; import { DocumentView } from '../client/views/nodes/DocumentView'; import { MobileInterface } from './MobileInterface'; import { DictationOverlay } from '../client/views/DictationOverlay'; -import RichTextMenu from '../client/views/nodes/formattedText/RichTextMenu'; +import { RichTextMenu } from '../client/views/nodes/formattedText/RichTextMenu'; import { ContextMenu } from '../client/views/ContextMenu'; @observer diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index d21d326f6..0ae952304 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -1,19 +1,19 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, observable } from 'mobx'; +import { observer } from 'mobx-react'; import * as rp from 'request-promise'; -import { Docs } from '../client/documents/Documents'; -import "./ImageUpload.scss"; -import React = require('react'); import { DocServer } from '../client/DocServer'; -import { observer } from 'mobx-react'; -import { observable, action } from 'mobx'; -import { Utils } from '../Utils'; +import { Docs } from '../client/documents/Documents'; import { Networking } from '../client/Network'; +import { MainViewModal } from '../client/views/MainViewModal'; import { Doc, Opt } from '../fields/Doc'; -import { Cast } from '../fields/Types'; -import { listSpec } from '../fields/Schema'; import { List } from '../fields/List'; -import MainViewModal from '../client/views/MainViewModal'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { listSpec } from '../fields/Schema'; +import { Cast } from '../fields/Types'; +import { Utils } from '../Utils'; +import "./ImageUpload.scss"; import { MobileInterface } from './MobileInterface'; +import React = require('react'); export interface ImageUploadProps { Document: Doc; // Target document for upload (upload location) diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 05a695147..8ca67f9ee 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1,4 +1,4 @@ -import * as React from "react"; + import { library } from '@fortawesome/fontawesome-svg-core'; import { faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, @@ -10,34 +10,34 @@ import { faAlignRight, faAlignLeft } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, reaction, trace, runInAction } from 'mobx'; +import { action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { Doc, DocListCast } from '../fields/Doc'; -import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; -import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, returnEmptyFilter, returnEmptyDoclist } from '../Utils'; +import * as React from "react"; import { Docs, DocumentOptions } from '../client/documents/Documents'; +import { DocumentType } from "../client/documents/DocumentTypes"; +import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; import { Scripting } from '../client/util/Scripting'; -import { DocumentView } from '../client/views/nodes/DocumentView'; +import { SettingsManager } from '../client/util/SettingsManager'; import { Transform } from '../client/util/Transform'; -import "./MobileInterface.scss"; -import "./ImageUpload.scss"; -import "./AudioUpload.scss"; -import SettingsManager from '../client/util/SettingsManager'; -import { Uploader } from "./ImageUpload"; +import { UndoManager } from "../client/util/UndoManager"; import { DockedFrameRenderer } from '../client/views/collections/CollectionDockingView'; -import { InkTool } from '../fields/InkField'; -import GestureOverlay from "../client/views/GestureOverlay"; -import { ScriptField } from "../fields/ScriptField"; +import { CollectionViewType } from "../client/views/collections/CollectionView"; +import { GestureOverlay } from "../client/views/GestureOverlay"; +import { AudioBox } from "../client/views/nodes/AudioBox"; +import { DocumentView } from '../client/views/nodes/DocumentView'; +import { RichTextMenu } from "../client/views/nodes/formattedText/RichTextMenu"; import { RadialMenu } from "../client/views/nodes/RadialMenu"; -import { UndoManager } from "../client/util/UndoManager"; +import { Doc, DocListCast } from '../fields/Doc'; +import { InkTool } from '../fields/InkField'; import { List } from "../fields/List"; -import { AudioUpload } from "./AudioUpload"; +import { ScriptField } from "../fields/ScriptField"; import { Cast, FieldValue } from '../fields/Types'; -import RichTextMenu from "../client/views/nodes/formattedText/RichTextMenu"; -import { AudioBox } from "../client/views/nodes/AudioBox"; -import { CollectionViewType } from "../client/views/collections/CollectionView"; -import { DocumentType } from "../client/documents/DocumentTypes"; -import { CollectionFreeFormViewChrome } from "../client/views/collections/CollectionMenu"; +import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero } from '../Utils'; +import { AudioUpload } from "./AudioUpload"; +import { Uploader } from "./ImageUpload"; +import "./AudioUpload.scss"; +import "./ImageUpload.scss"; +import "./MobileInterface.scss"; library.add(faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, faTerminal, faToggleOn, fileSolid, faExternalLinkAlt, faLocationArrow, faSearch, faFileDownload, faStop, faCalculator, faWindowMaximize, faAddressCard, @@ -47,6 +47,7 @@ library.add(faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngl faThumbtack, faTree, faTv, faUndoAlt, faBook, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft, faAlignLeft, faAlignRight); + @observer export class MobileInterface extends React.Component { static Instance: MobileInterface; -- cgit v1.2.3-70-g09d2 From 7b8924d203c6367edbf7e6ffbe2e8f2e6f24b859 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 29 Aug 2020 00:53:11 -0400 Subject: added some link follow options to link Editor. Big overhaul of dockingView to make things undoable and cleaner --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 12 +- src/client/util/DragManager.ts | 3 +- src/client/views/GlobalKeyHandler.ts | 4 +- .../views/collections/CollectionDockingView.tsx | 487 ++++++++------------- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/linking/LinkEditor.tsx | 8 + src/client/views/search/SearchBox.tsx | 2 +- src/fields/Doc.ts | 4 - src/mobile/MobileInterface.tsx | 4 +- 10 files changed, 215 insertions(+), 313 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 18ff993fe..9186cea87 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -848,7 +848,7 @@ export namespace Docs { { type: type, content: [ - ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, config.initialWidth, config.path)) + ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, config.initialWidth)) ] } ] diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index c60403701..7937072da 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1025,7 +1025,7 @@ export class CurrentUserUtils { CurrentUserUtils.openDashboard(userDoc, copy); } - public static createNewDashboard = async (userDoc: Doc, id?: string) => { + public static createNewDashboard = (userDoc: Doc, id?: string) => { const myPresentations = userDoc.myPresentations as Doc; const presentation = Doc.MakeCopy(userDoc.emptyPresentation as Doc, true); const dashboards = Cast(userDoc.myDashboards, Doc) as Doc; @@ -1051,11 +1051,13 @@ export class CurrentUserUtils { dashboardDoc.contextMenuLabels = new List(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Create Dashboard"]); Doc.AddDocToList(dashboards, "data", dashboardDoc); - // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) - setTimeout(() => { - CurrentUserUtils.openDashboard(userDoc, dashboardDoc); - }, 0); + CurrentUserUtils.openDashboard(userDoc, dashboardDoc); } + + public static get ActivePresentation() { return Cast(Doc.UserDoc().activePresentation, Doc, null); } + public static get MyRecentlyClosed() { return Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc, null); } + public static get MyDashboards() { return Cast(Doc.UserDoc().myDashboards, Doc, null); } + public static get EmptyPane() { return Cast(Doc.UserDoc().emptyPane, Doc, null); } } Scripting.addGlobal(function openDragFactory(dragFactory: Doc) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 0cca61841..8bf6faf03 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -117,10 +117,11 @@ export namespace DragManager { } export class DocumentDragData { - constructor(dragDoc: Doc[]) { + constructor(dragDoc: Doc[], dropAction?: dropActionType) { this.draggedDocuments = dragDoc; this.droppedDocuments = []; this.offset = [0, 0]; + this.dropAction = dropAction; } draggedDocuments: Doc[]; droppedDocuments: Doc[]; diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 84b3d64fd..1cbbfd67b 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -99,7 +99,7 @@ export class KeyManager { if (main.isPointerDown) { DragManager.AbortDrag(); } else { - if (CollectionDockingView.Instance.HasFullScreen()) { + if (CollectionDockingView.Instance.HasFullScreen) { CollectionDockingView.Instance.CloseFullScreen(); } else { doDeselect = !ContextMenu.Instance.closeMenu(); @@ -253,7 +253,7 @@ export class KeyManager { break; case "o": const target = SelectionManager.SelectedDocuments()[0]; - target && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(target); + target && CollectionDockingView.OpenFullScreen(target.props.Document); break; case "r": preventDefault = false; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 816f784ff..201cada09 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -37,9 +37,8 @@ const _global = (window /* browser */ || global /* node */) as any; @observer export class CollectionDockingView extends CollectionSubView(doc => doc) { - @observable public static Instances: CollectionDockingView[] = []; - @computed public static get Instance() { return CollectionDockingView.Instances[0]; } - public static makeDocumentConfig(document: Doc, width?: number, libraryPath?: Doc[]) { + @observable public static Instance: CollectionDockingView; + public static makeDocumentConfig(document: Doc, width?: number) { return { type: 'react-component', component: 'DocumentFrameRenderer', @@ -47,79 +46,46 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { width: width, props: { documentId: document[Id], - libraryPath: libraryPath?.map(d => d[Id]) } }; } - @computed public get initialized() { - return this._goldenLayout !== null; - } - - @observable private _goldenLayout: any = null; + private _reactionDisposer?: IReactionDisposer; private _containerRef = React.createRef(); private _flush: UndoManager.Batch | undefined; private _ignoreStateChange = ""; - private _isPointerDown = false; - private _maximizedSrc: Opt; + public tabMap: Set = new Set(); + public get initialized() { return this._goldenLayout !== null; } + public get HasFullScreen() { return this._goldenLayout._maximisedItem !== null; } + @observable private _goldenLayout: any = null; constructor(props: SubCollectionViewProps) { super(props); - runInAction(() => !CollectionDockingView.Instances ? CollectionDockingView.Instances = [this] : CollectionDockingView.Instances.push(this)); + runInAction(() => CollectionDockingView.Instance = this); //Why is this here? (window as any).React = React; (window as any).ReactDOM = ReactDOM; DragManager.StartWindowDrag = this.StartOtherDrag; } + public StartOtherDrag = (e: any, dragDocs: Doc[]) => { - console.log("START drag batch"); !this._flush && (this._flush = UndoManager.StartBatch("golden layout drag")); const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) : - { - type: 'row', - content: dragDocs.map((doc, i) => CollectionDockingView.makeDocumentConfig(doc)) - }; + { type: 'row', content: dragDocs.map((doc, i) => CollectionDockingView.makeDocumentConfig(doc)) }; const dragSource = this._goldenLayout.createDragSource(document.createElement("div"), config); - dragSource._dragListener.on("dragStop", () => dragSource.destroy()); + dragSource._dragListener.on("dragStop", dragSource.destroy); dragSource._dragListener.onMouseDown(e); } - @undoBatch - @action - public OpenFullScreen(docView: DocumentView, libraryPath?: Doc[]) { - if (docView.props.Document._viewType === CollectionViewType.Docking && docView.props.Document.layoutKey === "layout") { - return CurrentUserUtils.openDashboard(Doc.UserDoc(), docView.props.Document); - } - const document = Doc.MakeAlias(docView.props.Document); - const newItemStackConfig = { - type: 'stack', - content: [CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath)] - }; - const docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout); - this._goldenLayout.root.contentItems[0].addChild(docconfig); - docconfig.callDownwards('_$init'); - this._goldenLayout._$maximiseItem(docconfig); - this._maximizedSrc = docView; - this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig()); - this.stateChanged(); - SelectionManager.DeselectAll(); - } - @undoBatch public CloseFullScreen = () => { const target = this._goldenLayout._maximisedItem; - if (target !== null && this._maximizedSrc) { - this._goldenLayout._maximisedItem.remove(); - SelectionManager.SelectDoc(this._maximizedSrc, false); - this._maximizedSrc = undefined; + if (target) { + target.remove(); this.stateChanged(); } } - public HasFullScreen = () => { - return this._goldenLayout._maximisedItem !== null; - } - @undoBatch @action public static CloseRightSplit(document: Opt): boolean { @@ -136,17 +102,29 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { const retVal = !CollectionDockingView.Instance?._goldenLayout.root.contentItems[0].isRow ? false : Array.from(CollectionDockingView.Instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => Array.from(child.contentItems).some(tryClose)); - retVal && CollectionDockingView.Instance.layoutChanged(document); + retVal && document && CollectionDockingView.Instance.layoutChanged(); return retVal; } @undoBatch @action - layoutChanged(removed?: Doc) { - this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]); - this._goldenLayout.emit('stateChanged'); - this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig()); - this.stateChanged(); + public static OpenFullScreen(doc: Doc, libraryPath?: Doc[]) { + const instance = CollectionDockingView.Instance; + if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") { + return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); + } + const newItemStackConfig = { + type: 'stack', + content: [CollectionDockingView.makeDocumentConfig(Doc.MakeAlias(doc), undefined)] + }; + const docconfig = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); + instance._goldenLayout.root.contentItems[0].addChild(docconfig); + docconfig.callDownwards('_$init'); + instance._goldenLayout._$maximiseItem(docconfig); + instance._goldenLayout.emit('stateChanged'); + instance._ignoreStateChange = JSON.stringify(instance._goldenLayout.toConfig()); + instance.stateChanged(); + return true; } public static ReplaceRightSplit(document: Doc, libraryPath?: Doc[], addToSplit?: boolean): boolean { @@ -156,14 +134,16 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => { if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" && DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)?.Document.isDisplayPanel) { - const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); + const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined); + runInAction(() => document.isDisplayPanel = true); child.addChild(newItemStackConfig, undefined); !addToSplit && child.contentItems[0].remove(); return true; } return Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { if (DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)?.Document.isDisplayPanel) { - const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); + const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined); + runInAction(() => document.isDisplayPanel = true); child.addChild(newItemStackConfig, undefined); !addToSplit && child.contentItems[j].remove(); return true; @@ -171,7 +151,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { return false; }); }); - retVal && instance.layoutChanged(document); + retVal && instance.layoutChanged(); return retVal; } @@ -183,9 +163,9 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { public static AddRightSplit(document: Doc, dontSelect: boolean = false, isDisplayPanel: Opt = undefined) { if (!CollectionDockingView.Instance) return false; - const ind = CollectionDockingView.Instance._tabMap.findIndex((val) => val.doc === document); + const ind = Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex((tab) => tab.DashDoc === document); if (ind !== -1) { - const tab = CollectionDockingView.Instance._tabMap[ind].tab; + const tab = Array.from(CollectionDockingView.Instance.tabMap.keys())[ind]; const activeContentItem = tab.header.parent.getActiveContentItem(); if (tab.contentItem !== activeContentItem) { tab.header.parent.setActiveContentItem(tab.contentItem); @@ -198,7 +178,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { const instance = CollectionDockingView.Instance; const newItemStackConfig = { type: 'stack', - content: [CollectionDockingView.makeDocumentConfig(document, undefined, [])] + content: [CollectionDockingView.makeDocumentConfig(document, undefined)] }; const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); @@ -238,7 +218,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { const instance = CollectionDockingView.Instance; const newItemStackConfig = { type: 'stack', - content: [CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath)] + content: [CollectionDockingView.makeDocumentConfig(document, undefined)] }; const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); @@ -299,16 +279,20 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { // // Creates a vertical split on the right side of the docking view, and then adds the Document to that split // + @undoBatch public static UseRightSplit(document: Doc, libraryPath?: Doc[], shiftKey?: boolean) { if (shiftKey || !CollectionDockingView.ReplaceRightSplit(document, libraryPath, shiftKey)) { - CollectionDockingView.AddRightSplit(document, false, true); + return CollectionDockingView.AddRightSplit(document, false, true); } + return false; } - public AddTab = (stack: any, document: Doc, libraryPath?: Doc[]) => { - const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); + @undoBatch + public static AddTab(stack: any, document: Doc, libraryPath?: Doc[]) { + const instance = CollectionDockingView.Instance; + const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined); if (stack === undefined) { - let stack: any = this._goldenLayout.root; + stack = instance._goldenLayout.root; while (!stack.isStack) { if (stack.contentItems.length) { stack = stack.contentItems[0]; @@ -318,41 +302,21 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { break; } } - if (stack) { - stack.addChild(docContentConfig); - } - } else { - stack.addChild(docContentConfig, undefined); } - this.layoutChanged(); + stack?.addChild(docContentConfig, undefined); + instance.layoutChanged(); return true; } - public ReplaceTab = (stack: any, document: Doc, libraryPath?: Doc[]) => { - const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); - if (stack === undefined) { - let stack: any = this._goldenLayout.root; - while (!stack.isStack) { - if (stack.contentItems.length) { - stack = stack.contentItems[0]; - } else { - stack.addChild({ type: 'stack', content: [docContentConfig] }); - stack = undefined; - break; - } - } - if (stack) { - stack.addChild(docContentConfig); - } - } else { - stack.addChild(docContentConfig, undefined); - } - this.layoutChanged(); - return true; + @undoBatch + @action + layoutChanged() { + this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]); + this._goldenLayout.emit('stateChanged'); + this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig()); + this.stateChanged(); } - _tabMap: { tab: any, doc: Doc }[] = []; - async setupGoldenLayout() { const config = StrCast(this.props.Document.dockingConfig); if (config) { @@ -360,27 +324,23 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) ?? []; await Promise.all(docids.map(id => DocServer.GetRefField(id))); - if (!this._goldenLayout) { - runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config))); - } - else { + if (this._goldenLayout) { if (config === JSON.stringify(this._goldenLayout.toConfig())) { return; + } else { + try { + this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed); + this._goldenLayout.unbind('stackCreated', this.stackCreated); + } catch (e) { } } - try { - this._goldenLayout.unbind('tabCreated', this.tabCreated); - this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed); - this._goldenLayout.unbind('stackCreated', this.stackCreated); - } catch (e) { } - this._goldenLayout.destroy(); - runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config))); } - this._goldenLayout.on('tabCreated', this.tabCreated); + this.tabMap.clear(); + this._goldenLayout?.destroy(); + runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config))); this._goldenLayout.on('tabDestroyed', this.tabDestroyed); this._goldenLayout.on('stackCreated', this.stackCreated); this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer); this._goldenLayout.container = this._containerRef.current; - //this._goldenLayout.on("stateChanged", () => console.log("STATE CHANGED")); if (this._goldenLayout.config.maximisedItemId === '__glMaximised') { try { this._goldenLayout.config.root.getItemsById(this._goldenLayout.config.maximisedItemId)[0].toggleMaximise(); @@ -391,17 +351,15 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { this._goldenLayout.init(); } } - reactionDisposer?: Lambda; + componentDidMount: () => void = () => { if (this._containerRef.current) { - const observer = new _global.ResizeObserver(this.onResize); - observer.observe(this._containerRef.current); - this.reactionDisposer = reaction( - () => StrCast(this.props.Document.dockingConfig), + new _global.ResizeObserver(this.onResize).observe(this._containerRef.current); + this._reactionDisposer = reaction(() => StrCast(this.props.Document.dockingConfig), config => { if (!this._goldenLayout || this._ignoreStateChange !== config) { this.setupGoldenLayout(); - DocListCast((Doc.UserDoc().myDashboards as Doc).data).map(d => d.dashboardBrush = false); + DocListCast(CurrentUserUtils.MyDashboards.data).map(d => d.dashboardBrush = false); this.props.Document.dashboardBrush = true; } this._ignoreStateChange = ""; @@ -410,24 +368,19 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window } } + componentWillUnmount: () => void = () => { try { this.props.Document.dashboardBrush = false; - this._goldenLayout.unbind('tabCreated', this.tabCreated); this._goldenLayout.unbind('stackCreated', this.stackCreated); this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed); - } catch (e) { - - } + } catch (e) { } this._goldenLayout?.destroy(); - runInAction(() => { - CollectionDockingView.Instances.splice(CollectionDockingView.Instances.indexOf(this), 1); - this._goldenLayout = null; - }); window.removeEventListener('resize', this.onResize); - this.reactionDisposer?.(); + this._reactionDisposer?.(); } + @action onResize = (event: any) => { const cur = this._containerRef.current; @@ -438,31 +391,29 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { @action onPointerUp = (e: MouseEvent): void => { window.removeEventListener("pointerup", this.onPointerUp); - this._isPointerDown = false; if (this._flush) { setTimeout(() => { CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig()); this.stateChanged(); - console.log("END BATCH Up"); this._flush!.end(); this._flush = undefined; }, 10); } } + @action onPointerDown = (e: React.PointerEvent): void => { window.addEventListener("mouseup", this.onPointerUp); if (!(e.target as HTMLElement).closest("*.lm_content") && ((e.target as HTMLElement).closest("*.lm_tab") || (e.target as HTMLElement).closest("*.lm_stack"))) { - console.log("START BATCH dwn"); this._flush = UndoManager.StartBatch("golden layout edit"); } - if (e.nativeEvent.cancelBubble || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) || InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || (Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) { - return; - } else { + if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) && + Doc.GetSelectedTool() !== InkTool.Highlighter && Doc.GetSelectedTool() !== InkTool.Pen) { e.stopPropagation(); } } + public static Copy(doc: Doc) { let json = StrCast(doc.dockingConfig); const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g); @@ -504,124 +455,18 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { Doc.GetProto(other).data = new List(Array.from(otherSet.values())); } - tabCreated = (tab: any) => { - tab.titleElement[0].Tab = tab; - if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") { - if (tab.contentItem.config.fixed) { - tab.contentItem.parent.config.fixed = true; - } - - const doc = DocServer.GetCachedRefField(tab.contentItem.config.props.documentId) as Doc; - if (doc instanceof Doc) { - this._tabMap.push({ tab: tab, doc: doc }); - tab.titleElement[0].onclick = (e: any) => { - if (Date.now() - tab.titleElement[0].lastClick < 1000) tab.titleElement[0].select(); - tab.titleElement[0].lastClick = Date.now(); - tab.titleElement[0].focus(); - }; - tab.titleElement[0].onchange = (e: any) => { - tab.titleElement[0].size = e.currentTarget.value.length + 1; - Doc.GetProto(doc).title = e.currentTarget.value, true; - }; - tab.titleElement[0].size = StrCast(doc.title).length + 1; - tab.titleElement[0].value = doc.title; - tab.titleElement[0].style["max-width"] = "100px"; - const gearSpan = document.createElement("span"); - gearSpan.className = "collectionDockingView-gear"; - gearSpan.style.position = "relative"; - gearSpan.style.paddingLeft = "0px"; - gearSpan.style.paddingRight = "12px"; - const stack = tab.contentItem.parent; - tab.element[0].onpointerdown = (e: any) => { - if (e.target.className !== "lm_close_tab") { - const view = DocumentManager.Instance.getDocumentView(doc); - view && SelectionManager.SelectDoc(view, false); - } - }; - // shifts the focus to this tab when another tab is dragged over it - tab.element[0].onmouseenter = (e: any) => { - if (!this._isPointerDown || !SnappingManager.GetIsDragging()) return; - const activeContentItem = tab.header.parent.getActiveContentItem(); - if (tab.contentItem !== activeContentItem) { - tab.header.parent.setActiveContentItem(tab.contentItem); - } - tab.setActive(true); - }; - const onDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, (e) => { - if (!(e as any).defaultPrevented) { - const dragData = new DragManager.DocumentDragData([doc]); - dragData.dropAction = doc.dropAction as dropActionType; - DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY); - return true; - } - return false; - }, returnFalse, emptyFunction); - }; - - tab.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments(), - (sel) => { - const selected = sel.some(v => v.props.Document === doc); - selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && tab.header.parent.setActiveContentItem(tab.contentItem); - } - ); - tab.buttonDisposer = reaction(() => ((view: Opt) => view ? [view] : [])(DocumentManager.Instance.getDocumentView(doc)), - (views) => { - if (views.length) { - ReactDOM.render( - views} Stack={stack} /> - , - gearSpan); - tab.buttonDisposer?.(); - } - }, { fireImmediately: true }); - - tab.reactComponents = [gearSpan]; - tab.element.append(gearSpan); - tab.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => { - tab.titleElement[0].value = title; - tab.titleElement[0].style.padding = degree ? 0 : 2; - tab.titleElement[0].style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`; - }, { fireImmediately: true }); - //TODO why can't this just be doc instead of the id? - tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId; - } - } - tab.closeElement.off('click') //unbind the current click handler - .click(function () { - tab.selectionDisposer?.(); - tab.reactionDisposer?.(); - tab.buttonDisposer?.(); - const doc = DocServer.GetCachedRefField(tab.contentItem.config.props.documentId); - if (doc instanceof Doc) { - const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc, null); - recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); - SelectionManager.DeselectAll(); - } - CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig()); - tab.contentItem.remove(); - CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig()); - }); - } - tabDestroyed = (tab: any) => { - const ind = this._tabMap.findIndex((val) => val.tab === tab); - ind !== -1 && this._tabMap.splice(ind, 1); - if (tab.reactComponents) { - for (const ele of tab.reactComponents) { - ReactDOM.unmountComponentAtNode(ele); - } - } + this.tabMap.delete(tab); + Object.values(tab._disposers).forEach((disposer: any) => disposer?.()); + tab.reactComponents && Array.from(tab.reactComponents).forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele)); } - stackCreated = (stack: any) => { - //stack.header.controlsContainer.find('.lm_popout').hide(); stack.header.element.on('mousedown', (e: any) => { if (e.target === stack.header.element[0] && e.button === 2) { - const emptyPane = Cast(Doc.UserDoc().emptyPane, Doc, null); + const emptyPane = CurrentUserUtils.EmptyPane; emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; - this.AddTab(stack, Docs.Create.FreeformDocument([], { + CollectionDockingView.AddTab(stack, Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}` })); } @@ -632,59 +477,125 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { .click(action(() => { //if (confirm('really close this?')) { stack.remove(); - stack.contentItems.forEach((contentItem: any) => { - const doc = Cast(DocServer.GetCachedRefField(contentItem.config.props.documentId), Doc, null); - if (doc instanceof Doc) { - const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc, null); - recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); - } - }); + stack.contentItems.forEach((contentItem: any) => Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", contentItem.tab.DashDoc, undefined, true, true)); })); stack.header.controlsContainer.find('.lm_popout') //get the close icon .off('click') //unbind the current click handler .click(action(() => { // stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size - const emptyPane = Cast(Doc.UserDoc().emptyPane, Doc, null); + const emptyPane = CurrentUserUtils.EmptyPane; emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; - this.AddTab(stack, Docs.Create.FreeformDocument([], { + CollectionDockingView.AddTab(stack, Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}` })); })); } render() { - if (this.props.renderDepth > 0) { - return
Nested dashboards can't be rendered
; - } - return
; + return
+ {this.props.renderDepth > 0 ? "Nested dashboards can't be rendered" : (null)} +
; } } interface DockedFrameProps { documentId: FieldId; glContainer: any; - libraryPath: (FieldId[]); - //collectionDockingView: CollectionDockingView } @observer export class DockedFrameRenderer extends React.Component { _mainCont: HTMLDivElement | null = null; + _tabReaction: IReactionDisposer | undefined; @observable private _panelWidth = 0; @observable private _panelHeight = 0; - @observable private _document: Opt; @observable private _isActive: boolean = false; - _tabReaction: IReactionDisposer | undefined; - get _stack(): any { - return (this.props as any).glContainer.parent.parent; - } - get _tab(): any { - const tab = (this.props as any).glContainer.tab?.element[0] as HTMLElement; - return tab?.getElementsByClassName("lm_title")?.[0]; - } + get stack(): any { return (this.props as any).glContainer.parent.parent; } + get tab() { return (this.props as any).glContainer.tab; } + get tabTitle(): any { return (this.tab?.element[0] as HTMLElement).getElementsByClassName("lm_title")?.[0]; } + get view() { return this._document && DocumentManager.Instance.getDocumentView(this._document); } + @observable _document: Doc | undefined; + constructor(props: any) { super(props); - this._document = Cast(DocServer.GetCachedRefField(this.props.documentId), Doc, null); + setTimeout(() => DocServer.GetRefField(this.tab.contentItem.config.props.documentId).then(doc => this.init(doc as Doc)), 0); + } + + @action + init = (doc: Doc) => { + const tab = this.tab; + tab._disposers = {} as { [name: string]: IReactionDisposer }; + tab.DashDoc = this._document = doc; + if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") { + tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true); + + CollectionDockingView.Instance.tabMap.add(tab); + tab.titleElement[0].onclick = (e: any) => { + if (Date.now() - tab.titleElement[0].lastClick < 1000) tab.titleElement[0].select(); + tab.titleElement[0].lastClick = Date.now(); + tab.titleElement[0].focus(); + }; + tab.titleElement[0].onchange = (e: any) => { + tab.titleElement[0].size = e.currentTarget.value.length + 1; + Doc.GetProto(doc).title = e.currentTarget.value; + }; + tab.titleElement[0].size = StrCast(this._document.title).length + 1; + tab.titleElement[0].value = this._document.title; + tab.titleElement[0].style["max-width"] = "100px"; + const gearSpan = document.createElement("span"); + gearSpan.className = "collectionDockingView-gear"; + gearSpan.style.position = "relative"; + gearSpan.style.paddingLeft = "0px"; + gearSpan.style.paddingRight = "12px"; + const stack = tab.contentItem.parent; + tab.element[0].onpointerdown = (e: any) => { + e.target.className !== "lm_close_tab" && this.view && SelectionManager.SelectDoc(this.view, false); + }; + // shifts the focus to this tab when another tab is dragged over it + tab.element[0].onmouseenter = (e: MouseEvent) => { + if (SnappingManager.GetIsDragging() && tab.contentItem !== tab.header.parent.getActiveContentItem()) { + tab.header.parent.setActiveContentItem(tab.contentItem); + } + tab.setActive(true); + }; + const onDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, (e) => { + !e.defaultPrevented && DragManager.StartDocumentDrag([gearSpan], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY); + return !e.defaultPrevented; + }, returnFalse, emptyFunction); + }; + + tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => v.props.Document === doc), + (selected) => { + selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && tab.header.parent.setActiveContentItem(tab.contentItem); + } + ); + tab._disposers.buttonDisposer = reaction(() => this.view, + (view) => { + if (view) { + ReactDOM.render( + [view]} Stack={stack} /> + , + gearSpan); + tab._disposers.buttonDisposer?.(); + } + }, { fireImmediately: true }); + + tab.reactComponents = [gearSpan]; + tab.element.append(gearSpan); + tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => { + tab.titleElement[0].value = title; + tab.titleElement[0].style.padding = degree ? 0 : 2; + tab.titleElement[0].style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`; + }, { fireImmediately: true }); + } + tab.closeElement.off('click') //unbind the current click handler + .click(function () { + Object.values(tab._disposers).forEach((disposer: any) => disposer?.()); + Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", doc, undefined, true, true); + SelectionManager.DeselectAll(); + tab.contentItem.remove(); + }); } /** * Adds a document to the presentation view @@ -695,7 +606,7 @@ export class DockedFrameRenderer extends React.Component { if (unpin) DockedFrameRenderer.UnpinDoc(doc); else { //add this new doc to props.Document - const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; + const curPres = CurrentUserUtils.ActivePresentation; if (curPres) { const pinDoc = Doc.MakeAlias(doc); pinDoc.presentationTargetDoc = doc; @@ -717,7 +628,7 @@ export class DockedFrameRenderer extends React.Component { @action public static UnpinDoc(doc: Doc) { //add this new doc to props.Document - const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; + const curPres = CurrentUserUtils.ActivePresentation; if (curPres) { const ind = DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)); ind !== -1 && Doc.RemoveDocFromList(curPres, "data", DocListCast(curPres.data)[ind]); @@ -727,7 +638,7 @@ export class DockedFrameRenderer extends React.Component { componentDidMount() { const color = () => StrCast(this._document?._backgroundColor, this._document && CollectionDockingView.Instance?.props.backgroundColor?.(this._document, 0) || "white"); const selected = () => SelectionManager.SelectedDocuments().some(v => v.props.Document === this._document); - const updateTabColor = () => this._tab && (this._tab.style.backgroundColor = selected() ? color() : ""); + const updateTabColor = () => this.tabTitle && (this.tabTitle.style.backgroundColor = selected() ? color() : ""); const observer = new _global.ResizeObserver(action((entries: any) => { for (const entry of entries) { this._panelWidth = entry.contentRect.width; @@ -750,10 +661,7 @@ export class DockedFrameRenderer extends React.Component { private onActiveContentItemChanged() { if (this.props.glContainer.tab && this._isActive !== this.props.glContainer.tab.isActive) { this._isActive = this.props.glContainer.tab.isActive; - this._isActive && setTimeout(() => { - const dv = this._document && DocumentManager.Instance.getFirstDocumentView(this._document); - dv && SelectionManager.SelectDoc(dv, false); - }); + this._isActive && setTimeout(() => this.view && SelectionManager.SelectDoc(this.view, false), 0); (CollectionDockingView.Instance as any)._goldenLayout.isInitialised && CollectionDockingView.Instance.stateChanged(); !this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one. } @@ -764,7 +672,6 @@ export class DockedFrameRenderer extends React.Component { panelWidth = () => this.layoutDoc?.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._nativeWidth)), this._panelWidth) : (this.nativeAspect() && this.nativeAspect() < this._panelWidth / this._panelHeight ? this._panelHeight * this.nativeAspect() : this._panelWidth) panelHeight = () => this.nativeAspect() && this.nativeAspect() > this._panelWidth / this._panelHeight ? this._panelWidth / this.nativeAspect() : this._panelHeight; - nativeWidth = () => !this.layoutDoc!._fitWidth ? NumCast(this.layoutDoc!._nativeWidth) || this._panelWidth : 0; nativeHeight = () => !this.layoutDoc!._fitWidth ? NumCast(this.layoutDoc!._nativeHeight) || this._panelHeight : 0; @@ -778,17 +685,9 @@ export class DockedFrameRenderer extends React.Component { this._panelHeight / NumCast(this.layoutDoc!._nativeHeight) > this._panelWidth / NumCast(this.layoutDoc!._nativeWidth))) { scaling = this._panelWidth / NumCast(this.layoutDoc!._nativeWidth); } else if (nativeW && nativeH) { - // if (this.layoutDoc!.type === DocumentType.PDF || this.layoutDoc!.type === DocumentType.WEB) { - // if ((this.layoutDoc?._fitWidth) || - // this._panelHeight / NumCast(this.layoutDoc!._nativeHeight) > this._panelWidth / NumCast(this.layoutDoc!._nativeWidth)) { - // return this._panelWidth / NumCast(this.layoutDoc!._nativeWidth); - // } else { - // return this._panelHeight / NumCast(this.layoutDoc!._nativeHeight); - // } - // } const wscale = this.panelWidth() / nativeW; scaling = wscale * nativeH > this._panelHeight ? this._panelHeight / nativeH : wscale; - } else scaling = 1; + } return scaling; } @@ -805,17 +704,14 @@ export class DockedFrameRenderer extends React.Component { addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => { SelectionManager.DeselectAll(); - if (doc._viewType === CollectionViewType.Docking) { - return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); - } else if (location === "onRight") { - return CollectionDockingView.AddRightSplit(doc); - } else if (location === "close") { - return CollectionDockingView.CloseRightSplit(doc); - } else if (location === "replace") { - CollectionDockingView.UseRightSplit(doc); - return true; - } else {// if (location === "inPlace") { - return CollectionDockingView.Instance.AddTab(this._stack, doc, libraryPath); + if (doc._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); + switch (location) { + case "onRight": return CollectionDockingView.AddRightSplit(doc); + case "close": return CollectionDockingView.CloseRightSplit(doc); + case "replace": return CollectionDockingView.UseRightSplit(doc); + case "fullScreen": return CollectionDockingView.OpenFullScreen(doc); + case "inPlace": + default: return CollectionDockingView.AddTab(this.stack, doc); } } @@ -833,7 +729,7 @@ export class DockedFrameRenderer extends React.Component { childLayoutTemplate = () => Cast(this._document?.childLayoutTemplate, Doc, null); returnMiniSize = () => NumCast(this._document?._miniMapSize, 150); miniDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => { + this._document && setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => { this._document!._panX = clamp(NumCast(this._document!._panX) + delta[0] / this.returnMiniSize() * this.renderContentBounds.dim, this.renderContentBounds.l, this.renderContentBounds.l + this.renderContentBounds.dim); this._document!._panY = clamp(NumCast(this._document!._panY) + delta[1] / this.returnMiniSize() * this.renderContentBounds.dim, this.renderContentBounds.t, this.renderContentBounds.t + this.renderContentBounds.dim); return false; @@ -899,12 +795,11 @@ export class DockedFrameRenderer extends React.Component { @computed get docView() { TraceMobx(); if (!this._document) return (null); - const document = this._document; const resolvedDataDoc = !Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined; return <> - { searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} /> - {document._viewType === CollectionViewType.Freeform && !this._document?.hideMinimap ? this.renderMiniMap() : (null)} + {this._document._viewType === CollectionViewType.Freeform && !this._document?.hideMinimap ? this.renderMiniMap() : (null)} ; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index cdfa67769..fffbe65a3 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -738,7 +738,7 @@ export class CollectionTreeView extends CollectionSubView { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout - if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myDashboards) { + if (!e.isPropagationStopped() && this.doc === CurrentUserUtils.MyDashboards) { ContextMenu.Instance.addItem({ description: "Create Dashboard", event: () => CurrentUserUtils.createNewDashboard(Doc.UserDoc()), icon: "plus" }); ContextMenu.Instance.addItem({ description: "Delete Dashboard", event: () => this.remove(this.doc), icon: "minus" }); e.stopPropagation(); diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 11a905fb6..8e391f995 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -379,6 +379,14 @@ export class LinkEditor extends React.Component { onPointerDown={() => this.changeFollowBehavior("onRight")}> Always open in a new pane
+
this.changeFollowBehavior("replace")}> + Always replace right tab +
+
this.changeFollowBehavior("fullScreen")}> + Always open full screen +
this.changeFollowBehavior("inTab")}> Always open in a new tab diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index a24761195..d7a8ed404 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -492,7 +492,7 @@ export class SearchBox extends ViewBoxBaseComponent
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index cb4ca9a25..1401dd6a1 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -939,19 +939,16 @@ export namespace Doc { } export function IsBrushed(doc: Doc) { - return false; return computedFn(function IsBrushed(doc: Doc) { return brushManager.BrushedDoc.has(doc) || brushManager.BrushedDoc.has(Doc.GetProto(doc)); })(doc); } // don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message) export function IsBrushedDegreeUnmemoized(doc: Doc) { - return 0; if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return 0; return brushManager.BrushedDoc.has(doc) ? 2 : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? 1 : 0; } export function IsBrushedDegree(doc: Doc) { - return 0; return computedFn(function IsBrushDegree(doc: Doc) { return Doc.IsBrushedDegreeUnmemoized(doc); })(doc); @@ -980,7 +977,6 @@ export namespace Doc { let _lastDate = 0; export function linkFollowHighlight(destDoc: Doc, dataAndDisplayDocs = true) { - return; linkFollowUnhighlight(); Doc.HighlightDoc(destDoc, dataAndDisplayDocs); document.removeEventListener("pointerdown", linkFollowUnhighlight); diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 841862f49..d4eb76ecd 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -324,7 +324,7 @@ export class MobileInterface extends React.Component { ); } // stores dashboards documents as 'dashboards' variable - let dashboards = Cast(Doc.UserDoc().myDashboards, Doc) as Doc; + let dashboards = CurrentUserUtils.MyDashboards; if (this.dashboards) { dashboards = this.dashboards; } @@ -394,7 +394,7 @@ export class MobileInterface extends React.Component { */ @action createNewDashboard = async (id?: string) => { - const scens = Cast(Doc.UserDoc().myDashboards, Doc) as Doc; + const scens = CurrentUserUtils.MyDashboards; const dashboardCount = DocListCast(scens.data).length + 1; const freeformOptions: DocumentOptions = { x: 0, -- cgit v1.2.3-70-g09d2 From 4f3c8cfab12f1c5fff27faa0998a286d210148d2 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 29 Aug 2020 16:39:17 -0400 Subject: major restructure of how addDocTabs works. now you can add/replace with options for left/right/top/bottom and specific panel names --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/DictationManager.ts | 4 +- src/client/util/DocumentManager.ts | 4 +- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/GlobalKeyHandler.ts | 4 +- src/client/views/MainView.tsx | 8 +- src/client/views/PropertiesButtons.tsx | 4 +- src/client/views/PropertiesDocContextSelector.tsx | 2 +- src/client/views/PropertiesView.tsx | 2 +- src/client/views/animationtimeline/Keyframe.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 298 ++++++++------------- .../views/collections/CollectionSchemaCells.tsx | 2 +- .../CollectionSchemaMovableTableHOC.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 8 +- src/client/views/collections/SchemaTable.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 4 +- src/client/views/linking/LinkEditor.tsx | 20 +- src/client/views/linking/LinkMenuItem.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 16 +- src/client/views/nodes/FontIconBox.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 2 +- src/client/views/nodes/LinkAnchorBox.tsx | 6 +- src/client/views/nodes/LinkDocPreview.tsx | 6 +- src/client/views/nodes/PresBox.tsx | 6 +- src/client/views/nodes/VideoBox.tsx | 2 +- .../views/nodes/formattedText/DashFieldView.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 12 +- .../formattedText/FormattedTextBoxComment.tsx | 16 +- .../formattedText/ProsemirrorExampleTransfer.ts | 2 +- .../views/nodes/formattedText/RichTextMenu.tsx | 4 +- .../views/nodes/formattedText/RichTextRules.ts | 2 +- src/client/views/nodes/formattedText/nodes_rts.ts | 4 +- src/client/views/pdf/Annotation.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 2 +- src/fields/RichTextUtils.ts | 2 +- 39 files changed, 202 insertions(+), 268 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2ca1b95d7..262086735 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -847,7 +847,7 @@ export namespace Docs { { type: type, content: [ - ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, false, config.initialWidth)) + ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth)) ] } ] diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 7937072da..20f8fe9c1 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1063,7 +1063,7 @@ export class CurrentUserUtils { Scripting.addGlobal(function openDragFactory(dragFactory: Doc) { const copy = Doc.copyDragFactory(dragFactory); if (copy) { - CollectionDockingView.AddRightSplit(copy); + CollectionDockingView.AddSplit(copy, "right"); const view = DocumentManager.Instance.getFirstDocumentView(copy); view && SelectionManager.SelectDoc(view, false); } diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index e66c15fcb..231e1fa8d 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -323,7 +323,7 @@ export namespace DictationManager { ["open fields", { action: (target: DocumentView) => { const kvp = Docs.Create.KVPDocument(target.props.Document, { _width: 300, _height: 300 }); - target.props.addDocTab(kvp, "onRight"); + target.props.addDocTab(kvp, "add:right"); } }], @@ -337,7 +337,7 @@ export namespace DictationManager { const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"ordered_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`; proto.data = new RichTextField(proseMirrorState); proto.backgroundColor = "#eeffff"; - target.props.addDocTab(newBox, "onRight"); + target.props.addDocTab(newBox, "add:right"); } }] diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index fb54fbefc..93c37dbd1 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -124,7 +124,7 @@ export class DocumentManager { } static addRightSplit = (doc: Doc, finished?: () => void) => { - CollectionDockingView.AddRightSplit(doc); + CollectionDockingView.AddSplit(doc, "right"); finished?.(); } public jumpToDocument = async ( @@ -231,7 +231,7 @@ export class DocumentManager { containerDoc._currentTimecode = targetTimecode; const targetContext = await target?.context as Doc; const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; - DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "onRight"), finished), targetNavContext, linkDoc, undefined, doc, finished); + DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, doc, finished); } else { finished?.(); } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index dd223390a..764a2547c 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -156,7 +156,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV googleDoc = Docs.Create.WebDocument(googleDocUrl, options); dataDoc.googleDoc = googleDoc; } - CollectionDockingView.AddRightSplit(googleDoc); + CollectionDockingView.AddSplit(googleDoc, "right"); } else if (e.altKey) { e.preventDefault(); window.open(googleDocUrl); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 6c64a3714..c7a24133c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -188,7 +188,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> const alias = Doc.MakeAlias(selectedDocs[0].props.Document); alias.context = undefined; //CollectionDockingView.Instance?.OpenFullScreen(selectedDocs[0]); - CollectionDockingView.AddRightSplit(alias); + CollectionDockingView.AddSplit(alias, "right"); } } SelectionManager.DeselectAll(); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 2794a9f4e..db3e3d0dd 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -210,7 +210,7 @@ export class KeyManager { return { stopPropagation: false, preventDefault: false }; } } - MainView.Instance.mainFreeform && CollectionDockingView.AddRightSplit(MainView.Instance.mainFreeform); + MainView.Instance.mainFreeform && CollectionDockingView.AddSplit(MainView.Instance.mainFreeform, "right"); break; case "arrowleft": if (document.activeElement) { @@ -218,7 +218,7 @@ export class KeyManager { return { stopPropagation: false, preventDefault: false }; } } - MainView.Instance.mainFreeform && CollectionDockingView.CloseRightSplit(MainView.Instance.mainFreeform); + MainView.Instance.mainFreeform && CollectionDockingView.CloseSplit(MainView.Instance.mainFreeform); break; case "backspace": if (document.activeElement) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 6a960f4d5..7b0c6fa9f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -236,7 +236,7 @@ export class MainView extends React.Component { reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized, initialized => initialized && received && DocServer.GetRefField(received).then(docField => { if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) { - CollectionDockingView.AddRightSplit(docField); + CollectionDockingView.AddSplit(docField, "right"); } }), ); @@ -260,7 +260,7 @@ export class MainView extends React.Component { } const pres = Docs.Create.PresDocument(new List(), { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true }); - CollectionDockingView.AddRightSplit(pres); + CollectionDockingView.AddSplit(pres, "right"); Doc.UserDoc().activePresentation = pres; const myPresentations = Doc.UserDoc().myPresentations as Doc; Doc.AddDocToList(myPresentations, "data", pres); @@ -382,9 +382,9 @@ export class MainView extends React.Component { @computed get topOffset() { return (CollectionMenu.Instance?.Pinned ? 35 : 0) + Number(SEARCH_PANEL_HEIGHT.replace("px", "")); } flyoutWidthFunc = () => this.flyoutWidth; addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => { - return where === "close" ? CollectionDockingView.CloseRightSplit(doc) : + return where === "close" ? CollectionDockingView.CloseSplit(doc) : doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : - CollectionDockingView.AddRightSplit(doc); + CollectionDockingView.AddSplit(doc, "right"); } sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0) - Number(SEARCH_PANEL_HEIGHT.replace("px", "")), 1); mainContainerXf = () => this.sidebarScreenToLocal().translate(-58, 0); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index e95b28d6c..6ac6571d3 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -160,7 +160,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { googleDoc = Docs.Create.WebDocument(googleDocUrl, options); dataDoc.googleDoc = googleDoc; } - CollectionDockingView.AddRightSplit(googleDoc); + CollectionDockingView.AddRight(googleDoc, "right"); } else if (e.altKey) { e.preventDefault(); window.open(googleDocUrl); @@ -343,7 +343,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { dv.toggleFollowLink("inPlace", true, false); } else if (value === "linkOnRight") { dv.noOnClick(); - dv.toggleFollowLink("onRight", false, false); + dv.toggleFollowLink("add:right", false, false); } }); } diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index b382298f3..427748fe7 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -44,7 +44,7 @@ export class PropertiesDocContextSelector extends React.Component { } @computed get contexts() { - return !this.selectedDoc ? (null) : CollectionDockingView.AddRightSplit(doc)} />; + return !this.selectedDoc ? (null) : CollectionDockingView.AddSplit(doc, "right")} />; } previewBackground = () => "lightgrey"; diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index 4fb362ab1..e84022366 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -331,7 +331,7 @@ export class Keyframe extends React.Component { }), TimelineMenu.Instance.addItem("button", "Show Data", action(() => { const kvp = Docs.Create.KVPDocument(kf, { _width: 300, _height: 300 }); - CollectionDockingView.AddRightSplit(kvp); + CollectionDockingView.AddSplit(kvp, "right"); })), TimelineMenu.Instance.addItem("button", "Delete", action(() => { (this.regiondata.keyframes as List).splice(this.keyframes.indexOf(kf), 1); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 8301d3df8..62c865436 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -1,6 +1,6 @@ import 'golden-layout/src/css/goldenlayout-base.css'; import 'golden-layout/src/css/goldenlayout-dark-theme.css'; -import { clamp } from 'lodash'; +import { clamp, pull } from 'lodash'; import { action, computed, IReactionDisposer, Lambda, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as ReactDOM from 'react-dom'; @@ -38,7 +38,7 @@ const _global = (window /* browser */ || global /* node */) as any; @observer export class CollectionDockingView extends CollectionSubView(doc => doc) { @observable public static Instance: CollectionDockingView; - public static makeDocumentConfig(document: Doc, isDisplayPanel?: boolean, width?: number) { + public static makeDocumentConfig(document: Doc, panelName?: string, width?: number) { return { type: 'react-component', component: 'DocumentFrameRenderer', @@ -46,7 +46,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { width: width, props: { documentId: document[Id], - isDisplayPanel // flag for whether a tab should be considered a placeholder that has its contents replaced with new content + panelName // name of tab that can be used to close or replace its contents } }; } @@ -85,26 +85,20 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { } @undoBatch - @action - public static CloseRightSplit(document: Opt): boolean { - const tryClose = (childItem: any) => { - if (childItem.config?.component === "DocumentFrameRenderer") { - if ((!document && childItem.config.props.isDisplayPanel) || (document && childItem.config.props.documentId === document[Id])) { - childItem.remove(); - return true; - } + public static CloseSplit(document: Opt, panelName?: string): boolean { + const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => panelName ? tab.contentItem.config.props.panelName === panelName : tab.DashDoc === document); + if (tab) { + const j = tab.header.parent.contentItems.indexOf(tab.contentItem); + if (j !== -1) { + tab.header.parent.contentItems[j].remove(); + return CollectionDockingView.Instance.layoutChanged(); } - return false; - }; - const retVal = !CollectionDockingView.Instance?._goldenLayout.root.contentItems[0].isRow ? false : - Array.from(CollectionDockingView.Instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => Array.from(child.contentItems).some(tryClose)); + } - retVal && document && CollectionDockingView.Instance.layoutChanged(); - return retVal; + return false; } @undoBatch - @action public static OpenFullScreen(doc: Doc, libraryPath?: Doc[]) { const instance = CollectionDockingView.Instance; if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") { @@ -124,176 +118,94 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { return true; } - public static ReplaceRightSplit(document: Doc, libraryPath?: Doc[], addToSplit?: boolean): boolean { - if (!CollectionDockingView.Instance) return false; - const instance = CollectionDockingView.Instance; - const retVal = !instance._goldenLayout.root.contentItems[0].isRow ? false : - Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => { - if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" && - child.contentItems[0].config.isDisplayPanel) { - const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, true); - child.addChild(newItemStackConfig, undefined); - !addToSplit && child.contentItems[0].remove(); - return true; - } - return Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { - if (tab.config.props.isDisplayPanel) { - const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, true); - child.addChild(newItemStackConfig, undefined); - !addToSplit && child.contentItems[j].remove(); - return true; - } - return false; - }); - }); - retVal && instance.layoutChanged(); - return retVal; - } - - // - // Creates a vertical split on the right side of the docking view, and then adds the Document to the right of that split - // @undoBatch - @action - public static AddRightSplit(document: Doc, isDisplayPanel: Opt = undefined) { - if (!CollectionDockingView.Instance) return false; - - const ind = Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex((tab) => tab.DashDoc === document); - if (ind !== -1) { - const tab = Array.from(CollectionDockingView.Instance.tabMap.keys())[ind]; - const activeContentItem = tab.header.parent.getActiveContentItem(); - if (tab.contentItem !== activeContentItem) { - tab.header.parent.setActiveContentItem(tab.contentItem); - } - tab.setActive(true); - } else { - if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document); - const instance = CollectionDockingView.Instance; - const newItemStackConfig = { - type: 'stack', - content: [CollectionDockingView.makeDocumentConfig(document, isDisplayPanel)] - }; - - const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); - - if (instance._goldenLayout.root.contentItems.length === 0) { - instance._goldenLayout.root.addChild(newContentItem); - } else if (instance._goldenLayout.root.contentItems[0].isRow) { - instance._goldenLayout.root.contentItems[0].addChild(newContentItem); - } else { - const collayout = instance._goldenLayout.root.contentItems[0]; - const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout); - collayout.parent.replaceChild(collayout, newRow); - - newRow.addChild(newContentItem, undefined, true); - newRow.addChild(collayout, 0, true); - - collayout.config.width = 50; - newContentItem.config.width = 50; - } - newContentItem.callDownwards('_$init'); - instance.layoutChanged(); + public static ReplaceTab(document: Doc, panelName: string, stack: any, addToSplit?: boolean): boolean { + const instance = CollectionDockingView.Instance; + if (!instance) return false; + const newConfig = CollectionDockingView.makeDocumentConfig(document, panelName); + if (!panelName && stack) { + const activeContentItemIndex = stack.contentItems.findIndex((item: any) => item.config === stack._activeContentItem.config); + const newContentItem = stack.layoutManager.createContentItem(newConfig, instance._goldenLayout); + stack.addChild(newContentItem.contentItems[0], undefined); + stack.contentItems[activeContentItemIndex].remove(); + return CollectionDockingView.Instance.layoutChanged(); } - return true; + const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => tab.contentItem.config.props.panelName === panelName); + if (tab) { + tab.header.parent.addChild(newConfig, undefined); + const j = tab.header.parent.contentItems.indexOf(tab.contentItem); + !addToSplit && j !== -1 && tab.header.parent.contentItems[j].remove(); + return CollectionDockingView.Instance.layoutChanged(); + } + return CollectionDockingView.AddSplit(document, panelName, stack, panelName); } - // // Creates a split on any side of the docking view based on the passed input pullSide and then adds the Document to the requested side // - @action - public static AddSplit(document: Doc, pullSide: string, libraryPath?: Doc[]) { - if (!CollectionDockingView.Instance) return false; + @undoBatch + public static AddSplit(document: Doc, pullSide: string, stack?: any, panelName?: string) { const instance = CollectionDockingView.Instance; - const newItemStackConfig = { - type: 'stack', - content: [CollectionDockingView.makeDocumentConfig(document, undefined)] - }; + if (!instance) return false; + const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName); - const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); - - if (instance._goldenLayout.root.contentItems.length === 0) { // if no rows / columns - instance._goldenLayout.root.addChild(newContentItem); - } else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row - if (pullSide === "left") { - instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); - } else if (pullSide === "right") { - instance._goldenLayout.root.contentItems[0].addChild(newContentItem); - } else if (pullSide === "top" || pullSide === "bottom") { - // if not going in a row layout, must add already existing content into column - const rowlayout = instance._goldenLayout.root.contentItems[0]; - const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout); - rowlayout.parent.replaceChild(rowlayout, newColumn); - if (pullSide === "top") { - newColumn.addChild(rowlayout, undefined, true); - newColumn.addChild(newContentItem, 0, true); - } else if (pullSide === "bottom") { - newColumn.addChild(newContentItem, undefined, true); - newColumn.addChild(rowlayout, 0, true); + if (!pullSide && stack) { + stack.addChild(docContentConfig, undefined); + } else { + const newItemStackConfig = { type: 'stack', content: [docContentConfig] }; + const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); + if (instance._goldenLayout.root.contentItems.length === 0) { // if no rows / columns + instance._goldenLayout.root.addChild(newContentItem); + } else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row + switch (pullSide) { + default: + case "right": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break; + case "left": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break; + case "top": + case "bottom": + // if not going in a row layout, must add already existing content into column + const rowlayout = instance._goldenLayout.root.contentItems[0]; + const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout); + rowlayout.parent.replaceChild(rowlayout, newColumn); + if (pullSide === "top") { + newColumn.addChild(rowlayout, undefined, true); + newColumn.addChild(newContentItem, 0, true); + } else if (pullSide === "bottom") { + newColumn.addChild(newContentItem, undefined, true); + newColumn.addChild(rowlayout, 0, true); + } + + rowlayout.config.height = 50; + newContentItem.config.height = 50; } - - rowlayout.config.height = 50; - newContentItem.config.height = 50; - } - } else if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column - if (pullSide === "top") { - instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); - } else if (pullSide === "bottom") { - instance._goldenLayout.root.contentItems[0].addChild(newContentItem); - } else if (pullSide === "left" || pullSide === "right") { - // if not going in a row layout, must add already existing content into column - const collayout = instance._goldenLayout.root.contentItems[0]; - const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout); - collayout.parent.replaceChild(collayout, newRow); - - if (pullSide === "left") { - newRow.addChild(collayout, undefined, true); - newRow.addChild(newContentItem, 0, true); - } else if (pullSide === "right") { - newRow.addChild(newContentItem, undefined, true); - newRow.addChild(collayout, 0, true); + } else if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column + switch (pullSide) { + case "top": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break; + case "bottom": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break; + case "left": + case "right": + default: + // if not going in a row layout, must add already existing content into column + const collayout = instance._goldenLayout.root.contentItems[0]; + const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout); + collayout.parent.replaceChild(collayout, newRow); + + if (pullSide === "left") { + newRow.addChild(collayout, undefined, true); + newRow.addChild(newContentItem, 0, true); + } else { + newRow.addChild(newContentItem, undefined, true); + newRow.addChild(collayout, 0, true); + } + + collayout.config.width = 50; + newContentItem.config.width = 50; } - - collayout.config.width = 50; - newContentItem.config.width = 50; } + newContentItem.callDownwards('_$init'); } - newContentItem.callDownwards('_$init'); - instance.layoutChanged(); - return true; - } - - // - // Creates a vertical split on the right side of the docking view, and then adds the Document to that split - // - @undoBatch - public static UseRightSplit(document: Doc, libraryPath?: Doc[], shiftKey?: boolean) { - if (shiftKey || !CollectionDockingView.ReplaceRightSplit(document, libraryPath, shiftKey)) { - return CollectionDockingView.AddRightSplit(document, true); - } - return false; - } - - @undoBatch - public static AddTab(stack: any, document: Doc, libraryPath?: Doc[]) { - const instance = CollectionDockingView.Instance; - const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined); - if (stack === undefined) { - stack = instance._goldenLayout.root; - while (!stack.isStack) { - if (stack.contentItems.length) { - stack = stack.contentItems[0]; - } else { - stack.addChild({ type: 'stack', content: [docContentConfig] }); - stack = undefined; - break; - } - } - } - stack?.addChild(docContentConfig, undefined); - instance.layoutChanged(); - return true; + return instance.layoutChanged(); } @undoBatch @@ -303,6 +215,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { this._goldenLayout.emit('stateChanged'); this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig()); this.stateChanged(); + return true; } async setupGoldenLayout() { @@ -450,7 +363,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele)); } tabCreated = (tab: any) => { - tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab(tab); // have to explicitly initialize tabs that reuse contents from previous abs (ie, when dragging a tab around a new tab is created for the old content) + tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous abs (ie, when dragging a tab around a new tab is created for the old content) } stackCreated = (stack: any) => { @@ -458,9 +371,9 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { if (e.target === stack.header.element[0] && e.button === 2) { const emptyPane = CurrentUserUtils.EmptyPane; emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; - CollectionDockingView.AddTab(stack, Docs.Create.FreeformDocument([], { + CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}` - })); + }), "", stack); } }); @@ -477,9 +390,9 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { // stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size const emptyPane = CurrentUserUtils.EmptyPane; emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; - CollectionDockingView.AddTab(stack, Docs.Create.FreeformDocument([], { + CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}` - })); + }), "", stack); })); } @@ -601,7 +514,7 @@ export class DockedFrameRenderer extends React.Component { Doc.AddDocToList(curPres, "data", pinDoc); if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true; if (!DocumentManager.Instance.getDocumentView(curPres)) { - CollectionDockingView.AddRightSplit(curPres); + CollectionDockingView.AddSplit(curPres, "right"); } DocumentManager.Instance.jumpToDocument(doc, false, undefined, Cast(doc.context, Doc, null)); } @@ -688,17 +601,26 @@ export class DockedFrameRenderer extends React.Component { get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; } get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this._panelWidth * 100}% ` : undefined; } + // adds a tab to the layout based on the locaiton parameter which can be: + // close[:{left,right,top,bottom}] - e.g., "close" will close the tab, "close:left" will close the left tab, + // add[:{left,right,top,bottom}] - e.g., "add" will add a tab to the current stack, "add:right" will add a tab on the right + // replace[:{left,right,top,bottom,}] - e.g., "replace" will replace the current stack contents, + // "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name, + // "replace:monkeys" - will replace any tab that has the label 'monkeys', or a tab with that label will be created by default on the right + // inPlace - will add the document to any collection along the path from the document to the docking view that has a field isInPlaceContainer. if none is found, inPlace adds a tab to current stack addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => { SelectionManager.DeselectAll(); if (doc._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); - switch (location) { - case "onRight": return Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex((tab) => tab.DashDoc === doc) !== -1 ? - CollectionDockingView.CloseRightSplit(doc) : CollectionDockingView.AddRightSplit(doc); - case "close": return CollectionDockingView.CloseRightSplit(doc); - case "replace": return CollectionDockingView.UseRightSplit(doc); + const locationFields = location.split(":"); + const locationParams = locationFields.length > 1 ? locationFields[1] : ""; + switch (locationFields[0]) { + case "close": return CollectionDockingView.CloseSplit(doc, locationParams); case "fullScreen": return CollectionDockingView.OpenFullScreen(doc); + case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack); case "inPlace": - default: return CollectionDockingView.AddTab(this.stack, doc); + case "add": + default: return Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex((tab) => tab.DashDoc === doc) !== -1 ? + CollectionDockingView.CloseSplit(doc) : CollectionDockingView.AddSplit(doc, locationParams, this.stack); } } @@ -830,6 +752,6 @@ export class DockedFrameRenderer extends React.Component {
); } } -Scripting.addGlobal(function openOnRight(doc: any) { CollectionDockingView.AddRightSplit(doc); }, +Scripting.addGlobal(function openOnRight(doc: any) { CollectionDockingView.AddSplit(doc, "right"); }, "opens up the inputted document on the right side of the screen", "(doc: any)"); -Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.UseRightSplit(doc, undefined, shiftKey); }); +Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.ReplaceTab(doc, "right", undefined, shiftKey); }); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 18ca29aaa..0d3a951cf 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -370,7 +370,7 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell { })} />
-
this._doc && this.props.addDocTab(this._doc, "onRight")} className="collectionSchemaView-cellContents-docButton"> +
this._doc && this.props.addDocTab(this._doc, "add:right")} className="collectionSchemaView-cellContents-docButton">
; diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index a3475b481..383a9312f 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -246,7 +246,7 @@ export class MovableRow extends React.Component {
this.props.removeDoc(this.props.rowInfo.original))}>
-
this.props.addDocTab(this.props.rowInfo.original, "onRight")}>
+
this.props.addDocTab(this.props.rowInfo.original, "add:right")}>
{children} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index fffbe65a3..80a6afba7 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -117,7 +117,7 @@ class TreeView extends React.Component { Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey])); } - @undoBatch openRight = () => this.props.addDocTab(this.doc, "onRight"); + @undoBatch openRight = () => this.props.addDocTab(this.doc, "add:right"); @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { return this.doc !== target && this.props.removeDoc?.(doc) === true && addDoc(doc); } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 1da0e601a..64ad3abbf 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -305,7 +305,7 @@ export class CollectionView extends Touchable { const newRendition = Doc.MakeAlias(this.props.Document); newRendition._viewType = vtype; - this.props.addDocTab(newRendition, "onRight"); + this.props.addDocTab(newRendition, "add:right"); return newRendition; }, false); @@ -313,10 +313,10 @@ export class CollectionView extends Touchable this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }) : null; if (this.props.Document.childLayout instanceof Doc) { - optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" }); + optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "add:right"), icon: "project-diagram" }); } if (this.props.Document.childClickedOpenTemplateView instanceof Doc) { - optionItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childClickedOpenTemplateView as Doc, "onRight"), icon: "project-diagram" }); + optionItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childClickedOpenTemplateView as Doc, "add:right"), icon: "project-diagram" }); } !Doc.UserDoc().noviceMode && optionItems.push({ description: `${this.props.Document.isInPlaceContainer ? "Unset" : "Set"} inPlace Container`, event: () => this.props.Document.isInPlaceContainer = !this.props.Document.isInPlaceContainer, icon: "project-diagram" }); @@ -331,7 +331,7 @@ export class CollectionView extends Touchable { const alias = Doc.MakeAlias(this.props.Document); DocUtils.makeCustomViewClicked(alias, undefined, func.key); - this.props.addDocTab(alias, "onRight"); + this.props.addDocTab(alias, "add:right"); } })); DocListCast(Cast(Doc.UserDoc()["clickFuncs-child"], Doc, null).data).forEach(childClick => diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index 2fe00a245..1fb7aa04a 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -545,7 +545,7 @@ export class SchemaTable extends React.Component { } onOpenClick = () => { - this._showDoc && this.props.addDocTab(this._showDoc, "onRight"); + this._showDoc && this.props.addDocTab(this._showDoc, "add:right"); } getPreviewTransform = (): Transform => { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 759d142ea..1aa30fc02 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -76,7 +76,7 @@ export class MarqueeView extends React.Component this.props.addDocTab( - Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 850, isAnnotating: false, title: "bing", UseCors: true }), "onRight")); + Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 850, isAnnotating: false, title: "bing", UseCors: true }), "add:right")); cm.displayMenu(this._downX, this._downY); e.stopPropagation(); @@ -400,7 +400,7 @@ export class MarqueeView extends React.Component { Default
this.changeFollowBehavior("onRight")}> - Always open in a new pane + onPointerDown={() => this.changeFollowBehavior("add:left")}> + Always open in new left pane
this.changeFollowBehavior("replace")}> + onPointerDown={() => this.changeFollowBehavior("add:right")}> + Always open in new right pane +
+
this.changeFollowBehavior("replace:right")}> Always replace right tab
+
this.changeFollowBehavior("replace:left")}> + Always replace left tab +
this.changeFollowBehavior("fullScreen")}> Always open full screen
this.changeFollowBehavior("inTab")}> + onPointerDown={() => this.changeFollowBehavior("add")}> Always open in a new tab
+
this.changeFollowBehavior("replace")}> + Replace Tab +
{this.props.linkDoc.linksToAnnotation ?
this.changeFollowBehavior("openExternal")}> diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index a77122456..05b6b584d 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -167,7 +167,7 @@ export class LinkMenuItem extends React.Component { }); } } else { - DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false); + DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "add:right"), false); } linkDoc.linksToAnnotation && Hypothesis.scrollToAnnotation(StrCast(this.props.linkDoc.annotationId), this.props.destinationDoc); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 2d03c5154..48a1688a6 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -180,10 +180,10 @@ export class DocumentView extends DocComponent(Docu const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1]; RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15); - // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "map-pin", selected: -1 }); + // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "map-pin", selected: -1 }); const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]); (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 }); - // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "trash", selected: -1 }); + // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "add:right"), icon: "trash", selected: -1 }); RadialMenu.Instance.addItem({ description: "Pin", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin", selected: -1 }); RadialMenu.Instance.addItem({ description: "Open", event: () => MobileInterface.Instance.handleClick(this.props.Document), icon: "trash", selected: -1 }); @@ -323,7 +323,7 @@ export class DocumentView extends DocComponent(Docu fullScreenDoc = Doc.MakeAlias(this.props.Document); fullScreenDoc.layoutKey = "layout_fullScreen"; } - this.props.addDocTab(fullScreenDoc, "inTab"); + this.props.addDocTab(fullScreenDoc, "add"); }, "double tap"); SelectionManager.DeselectAll(); } @@ -351,7 +351,7 @@ export class DocumentView extends DocComponent(Docu this._timeout = setTimeout(() => { this._timeout = undefined; clickFunc(); }, 500); } else clickFunc(); } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself - this.props.addDocTab(DocUtils.makeCustomViewClicked(Doc.MakeAlias(this.props.Document), undefined, "onClick"), "onRight"); + this.props.addDocTab(DocUtils.makeCustomViewClicked(Doc.MakeAlias(this.props.Document), undefined, "onClick"), "add:right"); } else if (this.allLinks && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) { this.allLinks.length && this.followLinkClick(e.altKey, e.ctrlKey, e.shiftKey); } else { @@ -748,7 +748,7 @@ export class DocumentView extends DocComponent(Docu const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); const appearance = cm.findByDescription("UI Controls..."); const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : []; - templateDoc && appearanceItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" }); + templateDoc && appearanceItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" }); //DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" }); !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" }); @@ -766,7 +766,7 @@ export class DocumentView extends DocComponent(Docu onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" }); - !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("onRight", false, false), icon: "link" }); + !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("add:right", false, false), icon: "link" }); onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" }); onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" }); onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" }); @@ -810,8 +810,8 @@ export class DocumentView extends DocComponent(Docu const help = cm.findByDescription("Help..."); const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : []; - !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); - helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "onRight"), icon: "keyboard" }); + !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" }); + helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" }); helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" }); cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" }); diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index bc5abb0a4..87142babd 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -39,7 +39,7 @@ export class FontIconBox extends DocComponent( showTemplate = (): void => { const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null); - dragFactory && this.props.addDocTab(dragFactory, "onRight"); + dragFactory && this.props.addDocTab(dragFactory, "add:right"); } dragAsTemplate = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index b732f5f83..c5ff42a1a 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -230,7 +230,7 @@ export class KeyValueBox extends React.Component { openItems.push({ description: "Default Perspective", event: () => { this.props.addDocTab(this.props.Document, "close"); - this.props.addDocTab(this.fieldDocToLayout, "onRight"); + this.props.addDocTab(this.fieldDocToLayout, "add:right"); }, icon: "image" }); !open && cm.addItem({ description: "Change Perspective...", subitems: openItems, icon: "external-link-alt" }); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 6dd85b7f5..74d10d087 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -46,7 +46,7 @@ export class KeyValuePair extends React.Component { if (value instanceof Doc) { e.stopPropagation(); e.preventDefault(); - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" }); ContextMenu.Instance.displayMenu(e.clientX, e.clientY); } } diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 8e5ee09ff..10b6aa02e 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -73,7 +73,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent { - DocumentManager.Instance.FollowLink(this.rootDoc, anchorContainerDoc, document => this.props.addDocTab(document, StrCast(this.layoutDoc.linkOpenLocation, e.altKey ? "inTab" : "onRight")), false); + DocumentManager.Instance.FollowLink(this.rootDoc, anchorContainerDoc, document => this.props.addDocTab(document, StrCast(this.layoutDoc.linkOpenLocation, "add:right")), false); this._editing = false; }), 300 - (Date.now() - this._lastTap)); } @@ -87,14 +87,14 @@ export class LinkAnchorBox extends ViewBoxBaseComponent { - this.props.addDocTab(this.rootDoc, "onRight"); + this.props.addDocTab(this.rootDoc, "add:right"); } openLinkTargetOnRight = (e: React.MouseEvent) => { const alias = Doc.MakeAlias(Cast(this.layoutDoc[this.fieldKey], Doc, null)); alias.isLinkButton = undefined; alias._isBackground = undefined; alias.layoutKey = "layout"; - this.props.addDocTab(alias, "onRight"); + this.props.addDocTab(alias, "add:right"); } @action openLinkEditor = action((e: React.MouseEvent) => { diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index f154c5f56..e174a95af 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -40,7 +40,7 @@ export class LinkDocPreview extends React.Component { async followDefault() { DocumentLinksButton.EditLink = undefined; LinkDocPreview.LinkInfo = undefined; - this._targetDoc ? DocumentManager.Instance.FollowLink(this.props.linkDoc, this._targetDoc, doc => this.props.addDocTab(doc, "onRight"), false) : null; + this._targetDoc ? DocumentManager.Instance.FollowLink(this.props.linkDoc, this._targetDoc, doc => this.props.addDocTab(doc, "add:right"), false) : null; } componentDidUpdate() { this.updatePreview(); } @@ -69,9 +69,9 @@ export class LinkDocPreview extends React.Component { pointerDown = (e: React.PointerEvent) => { if (this.props.linkDoc && this.props.linkSrc) { DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.linkSrc, - (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation)); + (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation)); } else if (this.props.href) { - this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, UseCors: true }), "onRight"); + this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, UseCors: true }), "add:right"); } } width = () => Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225)); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index f60c521ad..a03c45a53 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -238,7 +238,7 @@ export class PresBox extends ViewBoxBaseComponent // If openDocument is selected then it should open the document for the user if (activeItem.openDocument) { - this.props.addDocTab(activeItem, "replace"); + this.props.addDocTab(activeItem, "replace:right"); } else //docToJump stayed same meaning, it was not in the group or was the last element in the group if (activeItem.zoomProgressivize && this.rootDoc.presStatus !== 'edit') { @@ -443,7 +443,7 @@ export class PresBox extends ViewBoxBaseComponent if (this.layoutDoc.inOverlay) { this.layoutDoc.presStatus = 'edit'; Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc); - CollectionDockingView.AddRightSplit(this.rootDoc); + CollectionDockingView.AddSplit(this.rootDoc, "right"); this.layoutDoc.inOverlay = false; } else if (this.layoutDoc.context && docView) { this.layoutDoc.presStatus = 'manual'; @@ -1115,7 +1115,7 @@ export class PresBox extends ViewBoxBaseComponent DockedFrameRenderer.PinDoc(doc, false); this.gotoDocument(this.childDocs.length, this.itemIndex); } else { - this.props.addDocTab(doc, "onRight"); + this.props.addDocTab(doc, "add:right"); } } } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 578061344..d50a10bdd 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -82,7 +82,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { e.stopPropagation(); const collview = await DocUtils.addFieldEnumerations(this._textBoxDoc, this._fieldKey, [{ title: this._fieldKey }]); - collview instanceof Doc && this.props.tbox.props.addDocTab(collview, "onRight"); + collview instanceof Doc && this.props.tbox.props.addDocTab(collview, "add:right"); } @@ -191,7 +191,7 @@ export class DashFieldViewInternal extends React.Component c.heading).indexOf(this._fieldKey) === -1 && list.push(new SchemaHeaderField(this._fieldKey, "#f1efeb")); list.map(c => c.heading).indexOf("text") === -1 && list.push(new SchemaHeaderField("text", "#f1efeb")); alias._pivotField = this._fieldKey.startsWith("#") ? "#" : this._fieldKey; - this.props.tbox.props.addDocTab(alias, "onRight"); + this.props.tbox.props.addDocTab(alias, "add:right"); } } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 356e36b76..c49e38f72 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -222,7 +222,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const id = Utils.GenerateDeterministicGuid(this.dataDoc[Id] + key); const allLinks = [{ href: Utils.prepend("/doc/" + id), title: value, targetId: id }]; - const link = this._editorView.state.schema.marks.linkAnchor.create({ allLinks, location: "onRight", title: value }); + const link = this._editorView.state.schema.marks.linkAnchor.create({ allLinks, location: "add:right", title: value }); const mval = this._editorView.state.schema.marks.metadataVal.create(); const offset = (tx.selection.to === range!.end - 1 ? -1 : 0); tx = tx.addMark(textEndSelection - value.length + offset, textEndSelection, link).addMark(textEndSelection - value.length + offset, textEndSelection, mval); @@ -465,7 +465,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const linkDoc = data.linkDocument!; const anchor1Title = linkDoc.anchor1 instanceof Doc ? StrCast(linkDoc.anchor1.title) : "-untitled-"; const anchor1Id = linkDoc.anchor1 instanceof Doc ? linkDoc.anchor1[Id] : ""; - this.makeLinkToSelection(linkDoc[Id], anchor1Title, "onRight", anchor1Id); + this.makeLinkToSelection(linkDoc[Id], anchor1Title, "add:right", anchor1Id); } getNodeEndpoints(context: Node, node: Node): { from: number, to: number } | null { @@ -811,7 +811,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (linkDoc) { const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-"; const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : ""; - this.makeLinkToSelection(linkDoc[Id], anchor2Title, "onRight", anchor2Id); + this.makeLinkToSelection(linkDoc[Id], anchor2Title, "add:right", anchor2Id); } }, { fireImmediately: true } @@ -1096,7 +1096,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const marks = [...node.marks]; const linkIndex = marks.findIndex(mark => mark.type.name === "link"); const allLinks = [{ href: Utils.prepend(`/doc/${linkId}`), title, linkId }]; - const link = view.state.schema.mark(view.state.schema.marks.linkAnchor, { allLinks, location: "onRight", title, docref: true }); + const link = view.state.schema.mark(view.state.schema.marks.linkAnchor, { allLinks, location: "add:right", title, docref: true }); marks.splice(linkIndex === -1 ? 0 : linkIndex, 1, link); return node.mark(marks); } @@ -1243,10 +1243,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp FormattedTextBoxComment.Hide(); if (FormattedTextBoxComment.linkDoc) { if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) { - this.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "inTab" : "onRight"); + this.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "add" : "add:right"); } else { DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, this.props.Document, - (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation)); + (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation)); } } diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 55d225adc..f41f03620 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -103,7 +103,7 @@ export class FormattedTextBoxComment { this.deleteLink(); } else if (FormattedTextBoxComment._followRef && FormattedTextBoxComment._followRef.contains(e.target as any)) { if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) { - textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "inTab" : "onRight"); + textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "add" : "add:right"); } else { const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(FormattedTextBoxComment.linkDoc.anchor1, Doc)), textBox.dataDoc) ? Cast(FormattedTextBoxComment.linkDoc.anchor2, Doc) : (Cast(FormattedTextBoxComment.linkDoc.anchor1, Doc)) @@ -112,28 +112,28 @@ export class FormattedTextBoxComment { if (FormattedTextBoxComment.linkDoc.follow) { if (FormattedTextBoxComment.linkDoc.follow === "Default") { - DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "onRight"), false); + DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "add:right"), false); } else if (FormattedTextBoxComment.linkDoc.follow === "Always open in right tab") { - if (target) { textBox.props.addDocTab(target, "onRight"); } + if (target) { textBox.props.addDocTab(target, "add:right"); } } else if (FormattedTextBoxComment.linkDoc.follow === "Always open in new tab") { - if (target) { textBox.props.addDocTab(target, "inTab"); } + if (target) { textBox.props.addDocTab(target, "add"); } } } else { - DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "onRight"), false); + DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "add:right"), false); } } } else { if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) { - textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "inTab" : "onRight"); + textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "add" : "add:right"); } else { DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, - (doc: Doc, followLinkLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation)); + (doc: Doc, followLinkLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation)); } } } } else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) { - textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400, UseCors: true }), "onRight"); + textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400, UseCors: true }), "add:right"); } keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation( FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark); diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts index a65eea50f..c6bacc1a8 100644 --- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts +++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts @@ -104,7 +104,7 @@ export function buildKeymap>(schema: S, props: any, mapKey //Command to create a new Tab with a PDF of all the command shortcuts bind("Mod-/", (state: EditorState, dispatch: (tx: Transaction) => void) => { const newDoc = Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _fitWidth: true, _width: 300, _height: 300 }); - props.addDocTab(newDoc, "onRight"); + props.addDocTab(newDoc, "add:right"); }); //Commands to modify BlockType diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 399f72608..307238ea1 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -810,7 +810,7 @@ export class RichTextMenu extends AntimodeMenu {

Linked to:

- +
; @@ -857,7 +857,7 @@ export class RichTextMenu extends AntimodeMenu { // TODO: should check for valid URL @undoBatch makeLinkToURL = (target: string, lcoation: string) => { - ((this.view as any)?.TextView as FormattedTextBox).makeLinkToSelection("", target, "onRight", "", target); + ((this.view as any)?.TextView as FormattedTextBox).makeLinkToSelection("", target, "onRadd:rightight", "", target); } @undoBatch diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index 7e632a0ee..3fadfe842 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -279,7 +279,7 @@ export class RichTextRules { DocUtils.Publish(target, docid, returnFalse, returnFalse); DocUtils.MakeLink({ doc: this.Document }, { doc: target }, "portal to"); }); - const link = state.schema.marks.linkAnchor.create({ href: Utils.prepend("/doc/" + docid), location: "onRight", title: docid, targetId: docid }); + const link = state.schema.marks.linkAnchor.create({ href: Utils.prepend("/doc/" + docid), location: "add:right", title: docid, targetId: docid }); return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 2).addMark(start, end - 3, link); } return state.tr; diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts index 1616500f6..64f7d27e5 100644 --- a/src/client/views/nodes/formattedText/nodes_rts.ts +++ b/src/client/views/nodes/formattedText/nodes_rts.ts @@ -148,7 +148,7 @@ export const nodes: { [index: string]: NodeSpec } = { alt: { default: null }, title: { default: null }, float: { default: "left" }, - location: { default: "onRight" }, + location: { default: "add:right" }, docid: { default: "" } }, group: "inline", @@ -177,7 +177,7 @@ export const nodes: { [index: string]: NodeSpec } = { height: { default: 100 }, title: { default: null }, float: { default: "right" }, - location: { default: "onRight" }, + location: { default: "add:right" }, hidden: { default: false }, fieldKey: { default: "" }, docid: { default: "" }, diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 98638ecc2..a33068a18 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -99,7 +99,7 @@ class RegionAnnotation extends React.Component { else if (e.button === 0) { const annoGroup = await Cast(this.props.document.group, Doc); if (annoGroup) { - DocumentManager.Instance.FollowLink(undefined, annoGroup, (doc, followLinkLocation) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation), false, undefined); + DocumentManager.Instance.FollowLink(undefined, annoGroup, (doc, followLinkLocation) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation), false, undefined); e.stopPropagation(); } } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index ed33ac822..d89e66ec5 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -604,7 +604,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { -- cgit v1.2.3-70-g09d2 From fe4a45d0f63683c0f917b6e923e6d48b006e2701 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 31 Aug 2020 23:18:09 -0400 Subject: fixed addDocTab to not re-create the golden layout. fixed clicking tabs to register as an undo event. fixed color of links made in PDFs to be lightBlue. fixed default link behavior to be 'default' --- src/client/views/collections/CollectionDockingView.tsx | 3 ++- src/client/views/collections/TabDocView.tsx | 15 ++++----------- src/client/views/linking/LinkEditor.tsx | 4 ++-- src/client/views/linking/LinkMenuItem.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBoxComment.tsx | 2 +- src/client/views/pdf/Annotation.tsx | 14 +++++++------- src/client/views/pdf/PDFViewer.tsx | 4 ++-- 7 files changed, 19 insertions(+), 25 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 5f05b1193..d39ef5e80 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -197,6 +197,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { newContentItem.config.width = 50; } } + instance._ignoreStateChange = JSON.stringify(instance._goldenLayout.toConfig()); newContentItem.callDownwards('_$init'); } @@ -255,7 +256,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { new _global.ResizeObserver(this.onResize).observe(this._containerRef.current); this._reactionDisposer = reaction(() => StrCast(this.props.Document.dockingConfig), config => { - if (!this._goldenLayout || this._ignoreStateChange !== config) { + if (!this._goldenLayout || this._ignoreStateChange !== config) { // bcz: TODO! really need to diff config with ignoreStateChange and modify the current goldenLayout instead of building a new one. this.setupGoldenLayout(); } this._ignoreStateChange = ""; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index fb3de3b68..31e3fbed6 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -18,7 +18,7 @@ import { DragManager, dropActionType } from "../../util/DragManager"; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoBatch } from "../../util/UndoManager"; +import { undoBatch, UndoManager } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import { PresBox } from '../nodes/PresBox'; import { CollectionDockingView } from './CollectionDockingView'; @@ -55,11 +55,6 @@ export class TabDocView extends React.Component { tab.DashDoc = doc; CollectionDockingView.Instance.tabMap.add(tab); - tab.titleElement[0].onclick = (e: any) => { - if (Date.now() - tab.titleElement[0].lastClick < 1000) tab.titleElement[0].select(); - tab.titleElement[0].lastClick = Date.now(); - tab.titleElement[0].focus(); - }; tab.titleElement[0].onchange = (e: any) => { tab.titleElement[0].size = e.currentTarget.value.length + 1; Doc.GetProto(doc).title = e.currentTarget.value; @@ -73,9 +68,7 @@ export class TabDocView extends React.Component { gearSpan.style.paddingLeft = "0px"; gearSpan.style.paddingRight = "12px"; const stack = tab.contentItem.parent; - tab.element[0].onpointerdown = (e: any) => { - e.target.className !== "lm_close_tab" && this.view && SelectionManager.SelectDoc(this.view, false); - }; + tab.element[0].onclick = (e: any) => e.target.className !== "lm_close_tab" && this.view && SelectionManager.SelectDoc(this.view!, false); // shifts the focus to this tab when another tab is dragged over it tab.element[0].onmouseenter = (e: MouseEvent) => { if (SnappingManager.GetIsDragging() && tab.contentItem !== tab.header.parent.getActiveContentItem()) { @@ -92,7 +85,7 @@ export class TabDocView extends React.Component { tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => v.props.Document === doc), (selected) => { - selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && tab.header.parent.setActiveContentItem(tab.contentItem); + selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), "tab switch"); } ); tab._disposers.buttonDisposer = reaction(() => this.view, @@ -245,7 +238,7 @@ export class TabDocView extends React.Component { case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack); case "inPlace": case "add": - default: return CollectionDockingView.ToggleSplit(doc, locationParams, this.stack); + default: return CollectionDockingView.AddSplit(doc, locationParams, this.stack); } } diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index c9c2e657b..d6c3702d1 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -364,7 +364,7 @@ export class LinkEditor extends React.Component {
- {StrCast(this.props.linkDoc.followLinkLocation, "Default")} + {StrCast(this.props.linkDoc.followLinkLocation, "default")} @@ -372,7 +372,7 @@ export class LinkEditor extends React.Component {
this.changeFollowBehavior("Default")}> + onPointerDown={() => this.changeFollowBehavior("default")}> Default
{ return; } - if (linkDoc.followLinkLocation && linkDoc.followLinkLocation !== "Default") { + if (linkDoc.followLinkLocation && linkDoc.followLinkLocation !== "default") { const annotationOn = this.props.destinationDoc.annotationOn as Doc; this.props.addDocTab(annotationOn instanceof Doc ? annotationOn : this.props.destinationDoc, StrCast(linkDoc.followLinkLocation)); if (annotationOn) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index f41f03620..ef0222a4c 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -111,7 +111,7 @@ export class FormattedTextBoxComment { const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor; if (FormattedTextBoxComment.linkDoc.follow) { - if (FormattedTextBoxComment.linkDoc.follow === "Default") { + if (FormattedTextBoxComment.linkDoc.follow === "default") { DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "add:right"), false); } else if (FormattedTextBoxComment.linkDoc.follow === "Always open in right tab") { if (target) { textBox.props.addDocTab(target, "add:right"); } diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index a33068a18..222a6cb0f 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -4,7 +4,7 @@ import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, WidthSym } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; -import { Cast, FieldValue, NumCast, StrCast } from "../../../fields/Types"; +import { Cast, FieldValue, NumCast, StrCast, PromiseValue } from "../../../fields/Types"; import { DocumentManager } from "../../util/DocumentManager"; import { PDFMenu } from "./PDFMenu"; import "./Annotation.scss"; @@ -86,7 +86,7 @@ class RegionAnnotation extends React.Component { } @action - onPointerDown = async (e: React.PointerEvent) => { + onPointerDown = (e: React.PointerEvent) => { if (e.button === 2 || e.ctrlKey) { PDFMenu.Instance.Status = "annotation"; PDFMenu.Instance.Delete = this.deleteAnnotation.bind(this); @@ -97,11 +97,11 @@ class RegionAnnotation extends React.Component { e.stopPropagation(); } else if (e.button === 0) { - const annoGroup = await Cast(this.props.document.group, Doc); - if (annoGroup) { - DocumentManager.Instance.FollowLink(undefined, annoGroup, (doc, followLinkLocation) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation), false, undefined); - e.stopPropagation(); - } + e.persist(); + e.stopPropagation(); + PromiseValue(this.props.document.group).then(annoGroup => annoGroup instanceof Doc && + DocumentManager.Instance.FollowLink(undefined, annoGroup, (doc, followLinkLocation) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation), false, undefined) + ); } } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d89e66ec5..8edb0e178 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -597,14 +597,14 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { if (!e.aborted && e.annoDragData && !e.annoDragData.linkedToDoc) { const link = DocUtils.MakeLink({ doc: annotationDoc }, { doc: e.annoDragData.dropDocument }, "Annotation"); annotationDoc.isLinkButton = true; - if (link) link.followLinkLocation = "add:right"; + if (link) Doc.GetProto(link).followLinkLocation = "default"; } } }); -- cgit v1.2.3-70-g09d2 From a4555fb8d5cd64482dd8431aad03878cb173f688 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 1 Sep 2020 03:58:41 -0400 Subject: fixed following link to a doc that is in a hidden tab to show that tab. fixed linear view to hit content bounds accurately. fixed editing of text in tabs somewhat. fixed place ment of link anchor boxes for topMost views. --- src/client/util/DocumentManager.ts | 2 ++ src/client/views/GlobalKeyHandler.ts | 1 - src/client/views/MainView.scss | 1 + src/client/views/MainView.tsx | 4 ++-- .../views/collections/CollectionLinearView.scss | 2 ++ .../views/collections/CollectionLinearView.tsx | 12 +++--------- src/client/views/collections/TabDocView.scss | 4 +++- src/client/views/collections/TabDocView.tsx | 22 +++++++++++++++------- src/client/views/linking/LinkMenu.scss | 2 -- src/client/views/linking/LinkMenu.tsx | 4 ++-- src/client/views/nodes/DocumentLinksButton.tsx | 7 +++++-- src/client/views/nodes/DocumentView.tsx | 5 +++-- src/client/views/search/SearchBox.tsx | 6 +++--- 13 files changed, 41 insertions(+), 31 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index f085f615c..9e55c5a44 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -160,6 +160,8 @@ export class DocumentManager { docView.props.Document.hidden = !docView.props.Document.hidden; } else { + const contView = docContext && getFirstDocView(docContext, originatingDoc); + contView && contView.topMost && contView.select(false); docView.select(false); docView.props.Document.hidden && (docView.props.Document.hidden = undefined); docView.props.focus(docView.props.Document, willZoom, undefined, focusAndFinish); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 076be3ad6..a52eb649d 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -196,7 +196,6 @@ export class KeyManager { break; case "f": SearchBox.Instance._searchFullDB = "My Stuff"; - SearchBox.Instance.newsearchstring = ""; SearchBox.Instance.enter(undefined); break; case "o": diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 93cc47215..9ca8f348d 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -31,6 +31,7 @@ bottom: 10px; left: calc(100% + 5px); z-index: 1; + pointer-events: none; } .mainView-snapLines { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4eccbaeb1..01df10aa0 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -370,6 +370,7 @@ export class MainView extends React.Component { @action selectMenu = (button: Doc) => { const title = StrCast(Doc.GetProto(button).title); + const closed = !this._flyoutWidth; this.closeFlyout(); if (this._panelContent !== title || !this._flyoutWidth) { switch (this._panelContent = title) { @@ -378,12 +379,11 @@ export class MainView extends React.Component { break; case "Catalog": SearchBox.Instance._searchFullDB = "My Stuff"; - SearchBox.Instance.newsearchstring = ""; SearchBox.Instance.enter(undefined); break; default: this._sidebarContent.proto = button.target as any; - this.expandFlyout(); + closed && this.expandFlyout(); button._backgroundColor = "lightgrey"; button.color = "black"; this._lastButton = button; diff --git a/src/client/views/collections/CollectionLinearView.scss b/src/client/views/collections/CollectionLinearView.scss index f5c4299a9..ca72b98a5 100644 --- a/src/client/views/collections/CollectionLinearView.scss +++ b/src/client/views/collections/CollectionLinearView.scss @@ -4,10 +4,12 @@ .collectionLinearView-outer { overflow: visible; height: 100%; + pointer-events: none; .collectionLinearView { display: flex; height: 100%; + align-items: center; >span { background: $dark-color; diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index 866d7245a..9eaa02bf8 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -17,6 +17,7 @@ import { DocumentLinksButton } from '../nodes/DocumentLinksButton'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { LinkDescriptionPopup } from '../nodes/LinkDescriptionPopup'; import { Tooltip } from '@material-ui/core'; +import { all } from 'bluebird'; type LinearDocument = makeInterface<[typeof documentSchema,]>; @@ -113,12 +114,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { const backgroundColor = StrCast(this.props.Document.backgroundColor, "black"); const color = StrCast(this.props.Document.color, "white"); - const menuOpener = ; @@ -140,6 +136,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { const scalable = pair.layout.onClick || pair.layout.onDragStart; return
@@ -194,9 +191,6 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { - {/* */} - : null}
; diff --git a/src/client/views/collections/TabDocView.scss b/src/client/views/collections/TabDocView.scss index 9a4b5cbd1..fdb801e03 100644 --- a/src/client/views/collections/TabDocView.scss +++ b/src/client/views/collections/TabDocView.scss @@ -1,4 +1,6 @@ - +input.lm_title:focus { + max-width: max-content !important; +} .miniMap { position: absolute; overflow: hidden; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 31e3fbed6..3cb57f086 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -54,21 +54,29 @@ export class TabDocView extends React.Component { tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true); tab.DashDoc = doc; + const titleEle = tab.titleElement[0]; CollectionDockingView.Instance.tabMap.add(tab); - tab.titleElement[0].onchange = (e: any) => { - tab.titleElement[0].size = e.currentTarget.value.length + 1; + titleEle.onchange = (e: any) => { + titleEle.size = e.currentTarget.value.length + 3; Doc.GetProto(doc).title = e.currentTarget.value; }; - tab.titleElement[0].size = StrCast(doc.title).length + 1; - tab.titleElement[0].value = doc.title; - tab.titleElement[0].style["max-width"] = "100px"; + titleEle.size = StrCast(doc.title).length + 3; + titleEle.value = doc.title; + titleEle.style["max-width"] = "100px"; const gearSpan = document.createElement("span"); gearSpan.className = "collectionDockingView-gear"; gearSpan.style.position = "relative"; gearSpan.style.paddingLeft = "0px"; gearSpan.style.paddingRight = "12px"; const stack = tab.contentItem.parent; - tab.element[0].onclick = (e: any) => e.target.className !== "lm_close_tab" && this.view && SelectionManager.SelectDoc(this.view!, false); + tab.element[0].onclick = (e: any) => { + if (e.target.className !== "lm_close_tab" && this.view) { + SelectionManager.SelectDoc(this.view, false); + if (Date.now() - titleEle.lastClick < 1000) titleEle.select(); + titleEle.lastClick = Date.now(); + (document.activeElement !== titleEle) && titleEle.focus(); + } + }; // shifts the focus to this tab when another tab is dragged over it tab.element[0].onmouseenter = (e: MouseEvent) => { if (SnappingManager.GetIsDragging() && tab.contentItem !== tab.header.parent.getActiveContentItem()) { @@ -83,7 +91,7 @@ export class TabDocView extends React.Component { }, returnFalse, emptyFunction); }; - tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => v.props.Document === doc), + tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => v.topMost && v.props.Document === doc), (selected) => { selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), "tab switch"); } diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index 4dc25031d..0e03b46db 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -4,8 +4,6 @@ width: auto; height: auto; position: absolute; - top: 0; - left: 0; z-index: 999; .linkMenu-list { diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 31d08edae..f5a1ae8e7 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -91,9 +91,9 @@ export class LinkMenu extends React.Component { render() { const sourceDoc = this.props.docView.props.Document; const groups: Map = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); - return
+ return
{!this._editingLink ? -
+
{this.renderAllGroups(groups)}
:
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 318f7b7e9..1d346894c 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -25,7 +25,7 @@ export const Flyout = higflyout.default; interface DocumentLinksButtonProps { View: DocumentView; - Offset?: number[]; + Offset?: (number | undefined)[]; AlwaysOn?: boolean; InMenu?: boolean; StartLink?: boolean; @@ -242,7 +242,10 @@ export class DocumentLinksButton extends React.Component; - const linkButton =
+ const linkButton =
(Docu if ((this.layoutDoc.onDragStart || this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0)) { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part stopPropagate = false; // don't stop propagation for field templates -- want the selection to propagate up to the root document of the template } else { - SelectionManager.SelectDoc(this, e.ctrlKey || e.shiftKey); + this.select(e.ctrlKey || e.shiftKey); + //SelectionManager.SelectDoc(this, e.ctrlKey || e.shiftKey); } preventDefault = false; } @@ -855,7 +856,7 @@ export class DocumentView extends DocComponent(Docu return this.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; } childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); - @computed.struct get linkOffset() { return [-15, 0]; } + @computed.struct get linkOffset() { return this.topMost ? [0, undefined, undefined, 10] : [-15, undefined, undefined, undefined]; } @computed get contents() { const pos = this.props.relative ? "relative " : "absolute"; TraceMobx(); diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index d08cc7f5b..c04b1da10 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -102,7 +102,7 @@ export class SearchBox extends ViewBoxBaseComponent { if (!e || e.key === "Enter") { @@ -378,7 +378,7 @@ export class SearchBox extends ViewBoxBaseComponent(docsForFilter) : undefined; collectionView.props.Document._docFilters = docsForFilter?.length && docFilters?.length ? new List(docFilters) : undefined; } - }) + }); render() { const myDashboards = DocListCast(CurrentUserUtils.MyDashboards.data); -- cgit v1.2.3-70-g09d2 From 7f6f5acc59e772cb828b8e532e16d4c40465de65 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 3 Sep 2020 17:13:11 -0400 Subject: changed linkMenuItem follow behavior to work when one link is an annotation -- now it will follow to the link endpoint that is not an annotation --- src/client/util/DocumentManager.ts | 8 ++++---- src/client/views/linking/LinkMenuGroup.tsx | 3 ++- src/client/views/nodes/DocumentLinksButton.tsx | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 2c7dcf49b..420b29559 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -215,8 +215,8 @@ export class DocumentManager { public async FollowLink(link: Opt, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { const linkDocs = link ? [link] : DocListCast(doc.links); SelectionManager.DeselectAll(); - const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc)); // link docs where 'doc' is anchor1 - const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc)); // link docs where 'doc' is anchor2 + const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor1 + const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor2 const fwdLinkWithoutTargetView = firstDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0); const backLinkWithoutTargetView = secondDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor1 as Doc).length === 0); const linkWithoutTargetDoc = traverseBacklink === undefined ? fwdLinkWithoutTargetView || backLinkWithoutTargetView : traverseBacklink ? backLinkWithoutTargetView : fwdLinkWithoutTargetView; @@ -225,10 +225,10 @@ export class DocumentManager { followLinks.forEach(async linkDoc => { if (linkDoc) { const target = (doc === linkDoc.anchor1 ? linkDoc.anchor2 : doc === linkDoc.anchor2 ? linkDoc.anchor1 : - (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) ? linkDoc.anchor2 : linkDoc.anchor1)) as Doc; + (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc) ? linkDoc.anchor2 : linkDoc.anchor1)) as Doc; const targetTimecode = (doc === linkDoc.anchor1 ? Cast(linkDoc.anchor2_timecode, "number") : doc === linkDoc.anchor2 ? Cast(linkDoc.anchor1_timecode, "number") : - (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) ? Cast(linkDoc.anchor2_timecode, "number") : Cast(linkDoc.anchor1_timecode, "number"))); + (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc) ? Cast(linkDoc.anchor2_timecode, "number") : Cast(linkDoc.anchor1_timecode, "number"))); if (target) { const containerDoc = (await Cast(target.annotationOn, Doc)) || target; containerDoc._currentTimecode = targetTimecode; diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 2ae87ac13..8e09052a3 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -66,7 +66,8 @@ export class LinkMenuGroup extends React.Component { } render() { - const groupItems = this.props.group.map(linkDoc => { + const set = new Set(this.props.group); + const groupItems = Array.from(set.keys()).map(linkDoc => { const destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc) || LinkManager.Instance.getOppositeAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, null).annotationOn === this.props.sourceDoc ? Cast(linkDoc.anchor2, Doc, null) : Cast(linkDoc.anchor1, Doc, null)); if (destination && this.props.sourceDoc) { diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 1d346894c..ab6cae0ad 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -220,7 +220,7 @@ export class DocumentLinksButton extends React.Component(this.props.links); const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link"; const buttonTitle = "Tap to view links"; @@ -265,7 +265,7 @@ export class DocumentLinksButton extends React.Component : links.length} */} {this.props.InMenu ? this.props.StartLink ? : - link : links.length} + link : Array.from(links).length}
{this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? @@ -287,7 +287,7 @@ export class DocumentLinksButton extends React.Component; - return (!links.length) && !this.props.AlwaysOn ? (null) : + return (!Array.from(links).length) && !this.props.AlwaysOn ? (null) : this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink) ?
{title}
}> {linkButton} -- cgit v1.2.3-70-g09d2