diff options
Diffstat (limited to 'src')
66 files changed, 767 insertions, 881 deletions
diff --git a/src/.DS_Store b/src/.DS_Store Binary files differindex 299b902c6..02618014e 100644 --- a/src/.DS_Store +++ b/src/.DS_Store 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<string> = 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 6af05f45f..be584c3cf 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -394,7 +394,7 @@ export class CurrentUserUtils { }[] { if (doc.emptyPresentation === undefined) { doc.emptyPresentation = Docs.Create.PresDocument(new List<Doc>(), - { title: "Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true }); + { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true }); ((doc.emptyPresentation as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptyCollection === undefined) { @@ -448,7 +448,7 @@ export class CurrentUserUtils { { toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true }, { toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc, noviceMode: true }, - { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Present", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory))', drag: `Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true }, + { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true }, { toolTip: "Tap to create a search box in a new pane, drag for a search box", title: "Query", icon: "search", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySearch as Doc }, { toolTip: "Tap to create a scripting box in a new pane, drag for a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScript as Doc }, // { title: "Drag an import folder", title: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, @@ -522,6 +522,7 @@ export class CurrentUserUtils { { title: "Import", target: Cast(doc["sidebar-import"], Doc, null), icon: "upload", click: 'selectMainMenu(self)' }, { title: "Sharing", target: Cast(doc["sidebar-sharing"], Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc["sidebar-sharing"] as Doc }, { title: "Tools", target: Cast(doc["sidebar-tools"], Doc, null), icon: "wrench", click: 'selectMainMenu(self)' }, + { title: "Pres. Trails", target: Cast(doc["sidebar-presentations"], Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' }, { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' }, { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' }, { title: "User Doc", target: Cast(doc["sidebar-userDoc"], Doc, null), icon: "address-card", click: 'selectMainMenu(self)' }, @@ -698,8 +699,8 @@ export class CurrentUserUtils { return CurrentUserUtils.setupDashboards(userDoc); } - // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. - // when clicked, this panel will be displayed in the target container (ie, sidebarContainer) + // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. + // when clicked, this panel will be displayed in the target container (ie, sidebarContainer) static async setupToolsBtnPanel(doc: Doc) { // setup a masonry view of all he creators const creatorBtns = await CurrentUserUtils.setupCreatorButtons(doc); @@ -755,6 +756,29 @@ export class CurrentUserUtils { return doc.myDashboards as any as Doc; } + static async setupPresentations(doc: Doc) { + await doc.myPresentations; + if (doc.myPresentations === undefined) { + doc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], { + title: "PRESENTATION TRAILS", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true, system: true + })); + } + + if (doc["sidebar-presentations"] === undefined) { + const newPresentations = ScriptField.MakeScript(`createNewPresentation()`); + (doc.myPresentations as Doc).contextMenuScripts = new List<ScriptField>([newPresentations!]); + (doc.myPresentations as Doc).contextMenuLabels = new List<string>(["Create New Presentation"]); + const presentations = doc.myPresentations as Doc; + + doc["sidebar-presentations"] = new PrefetchProxy(Docs.Create.TreeDocument([presentations], { + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", + treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true, + lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + })) as any as Doc; + } + return doc.myPresentations as any as Doc; + } + static setupCatalog(doc: Doc) { doc.myCatalog === undefined; if (doc.myCatalog === undefined) { @@ -831,6 +855,7 @@ export class CurrentUserUtils { await CurrentUserUtils.setupToolsBtnPanel(doc); CurrentUserUtils.setupDashboards(doc); CurrentUserUtils.setupCatalog(doc); + CurrentUserUtils.setupPresentations(doc); CurrentUserUtils.setupInactiveDocs(doc); CurrentUserUtils.setupUserDoc(doc); } @@ -895,7 +920,7 @@ export class CurrentUserUtils { static setupClickEditorTemplates(doc: Doc) { if (doc["clickFuncs-child"] === undefined) { - // to use this function, select it from the context menu of a collection. then edit the onChildClick script. Add two Doc variables: 'target' and 'thisContainer', then assign 'target' to some target collection. After that, clicking on any document in the initial collection will open it in the target + // to use this function, select it from the context menu of a collection. then edit the onChildClick script. Add two Doc variables: 'target' and 'thisContainer', then assign 'target' to some target collection. After that, clicking on any document in the initial collection will open it in the target const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript( "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self]))) ", { thisContainer: Doc.name }), { @@ -1012,7 +1037,8 @@ export class CurrentUserUtils { Scripting.addGlobal(function createNewDashboard() { return MainView.Instance.createNewDashboard(); }, "creates a new dashboard when called"); - +Scripting.addGlobal(function createNewPresentation() { return MainView.Instance.createNewPresentation(); }, + "creates a new presentation when called"); Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, "returns all the links to the document or its annotations", "(doc: any)"); Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); }, 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<{}> { <div className={"close-button"} onClick={action(() => { this.createGroupModalOpen = false; TaskCompletionBox.taskCompleted = false; })}> - <FontAwesomeIcon icon={fa.faTimes} color={"black"} size={"lg"} /> + <FontAwesomeIcon icon={"times"} color={"black"} size={"lg"} /> </div> </div> <input @@ -398,19 +393,19 @@ export default class GroupManager extends React.Component<{}> { <div className="group-heading"> <p><b>Manage Groups</b></p> <button onClick={action(() => this.createGroupModalOpen = true)}> - <FontAwesomeIcon icon={fa.faPlus} size={"sm"} /> Create Group + <FontAwesomeIcon icon={"plus-hexagon"} size={"sm"} /> Create Group </button> <div className={"close-button"} onClick={this.close}> - <FontAwesomeIcon icon={fa.faTimes} color={"black"} size={"lg"} /> + <FontAwesomeIcon icon={"times"} color={"black"} size={"lg"} /> </div> </div> <div className="main-container"> <div className="sort-groups" onClick={action(() => this.groupSort = this.groupSort === "ascending" ? "descending" : this.groupSort === "descending" ? "none" : "ascending")}> - Name {this.groupSort === "ascending" ? <FontAwesomeIcon icon={fa.faCaretUp} size={"xs"} /> - : this.groupSort === "descending" ? <FontAwesomeIcon icon={fa.faCaretDown} size={"xs"} /> - : <FontAwesomeIcon icon={fa.faCaretRight} size={"xs"} /> + Name {this.groupSort === "ascending" ? <FontAwesomeIcon icon={"caret-up"} size={"xs"} /> + : this.groupSort === "descending" ? <FontAwesomeIcon icon={"caret-down"} size={"xs"} /> + : <FontAwesomeIcon icon={"caret-right"} size={"xs"} /> } </div> <div className="group-body"> @@ -421,7 +416,7 @@ export default class GroupManager extends React.Component<{}> { > <div className="group-name" >{group.groupName}</div> <div className="group-info" onClick={action(() => this.currentGroup = group)}> - <FontAwesomeIcon icon={fa.faInfoCircle} color={"#e8e8e8"} size={"sm"} style={{ backgroundColor: "#1e89d7", borderRadius: "100%", border: "1px solid #1e89d7" }} /> + <FontAwesomeIcon icon={"info-circle"} color={"#e8e8e8"} size={"sm"} style={{ backgroundColor: "#1e89d7", borderRadius: "100%", border: "1px solid #1e89d7" }} /> </div> </div> )} 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<GroupMemberViewProps> { +export class GroupMemberView extends React.Component<GroupMemberViewProps> { @observable private memberSort: "ascending" | "descending" | "none" = "none"; @@ -43,7 +39,7 @@ export default class GroupMemberView extends React.Component<GroupMemberViewProp > </input> <div className={"memberView-closeButton"} onClick={action(this.props.onCloseButtonClick)}> - <FontAwesomeIcon icon={fa.faTimes} color={"black"} size={"lg"} /> + <FontAwesomeIcon icon={"times"} color={"black"} size={"lg"} /> </div> {GroupManager.Instance.hasEditAccess(this.props.group) ? <div className="group-buttons"> @@ -88,7 +84,7 @@ export default class GroupMemberView extends React.Component<GroupMemberViewProp </div> {hasEditAccess ? <div className={"remove-button"} onClick={() => GroupManager.Instance.removeMemberFromGroup(this.props.group, member)}> - <FontAwesomeIcon icon={fa.faTrashAlt} size={"sm"} /> + <FontAwesomeIcon icon={"trash-alt"} size={"sm"} /> </div> : null} </div> 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<FieldViewProps> { 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<FieldViewProps> { opacity: uploading ? 0 : 1, transition: "0.4s opacity ease" }}> - <FontAwesomeIcon icon={faCloudUploadAlt} color="#FFFFFF" size={"2x"} /> + <FontAwesomeIcon icon={"cloud-upload-alt"} color="#FFFFFF" size={"2x"} /> </div> <img style={{ @@ -366,7 +363,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> { 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<FieldViewProps> { marginLeft: 6.4, marginTop: 5.2 }} - icon={faPlus} + icon={"plus"} size={"1x"} /> </div> 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<KeyValueProps> private valueRef = React.createRef<EditableView>(); private checkRef = React.createRef<HTMLInputElement>(); - 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<KeyValueProps> </div> <div onClick={() => this.props.remove(this)} title={"Delete Entry"}> <FontAwesomeIcon - icon={faPlus} + icon={"plus"} color={"red"} size={"1x"} style={{ diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index bc5e1e9d3..e9befc465 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -1,27 +1,25 @@ -import { observable, runInAction, action, computed } from "mobx"; -import * as React from "react"; -import MainViewModal from "../views/MainViewModal"; -import { observer } from "mobx-react"; -import * as fa from '@fortawesome/free-solid-svg-icons'; -import { SelectionManager } from "./SelectionManager"; -import "./SettingsManager.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Networking } from "../Network"; -import { CurrentUserUtils } from "./CurrentUserUtils"; -import { Utils, addStyleSheet, addStyleSheetRule, removeStyleSheetRule } from "../../Utils"; +import { action, computed, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; +import { ColorState, SketchPicker } from "react-color"; import { Doc } from "../../fields/Doc"; -import GroupManager from "./GroupManager"; -import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; +import { BoolCast, StrCast } from "../../fields/Types"; +import { addStyleSheet, addStyleSheetRule, Utils } from "../../Utils"; +import { GoogleAuthenticationManager } from "../apis/GoogleAuthenticationManager"; import { DocServer } from "../DocServer"; -import { BoolCast, StrCast, NumCast } from "../../fields/Types"; +import { Networking } from "../Network"; +import { MainViewModal } from "../views/MainViewModal"; +import { CurrentUserUtils } from "./CurrentUserUtils"; +import { GroupManager } from "./GroupManager"; +import "./SettingsManager.scss"; import { undoBatch } from "./UndoManager"; -import { ColorState, SketchPicker } from "react-color"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @observer -export default class SettingsManager extends React.Component<{}> { +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"} </button> <div className="close-button" onClick={this.close}> - <FontAwesomeIcon icon={fa.faTimes} color="black" size={"lg"} /> + <FontAwesomeIcon icon={"times"} color="black" size={"lg"} /> </div> </div> <div className="settings-content"> 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<{}> { > <div className={"padding"}>{group.groupName}</div> <div className="group-info" onClick={action(() => GroupManager.Instance.currentGroup = group)}> - <FontAwesomeIcon icon={fa.faInfoCircle} color={"#e8e8e8"} size={"sm"} style={{ backgroundColor: "#1e89d7", borderRadius: "100%", border: "1px solid #1e89d7" }} /> + <FontAwesomeIcon icon={"info-circle"} color={"#e8e8e8"} size={"sm"} style={{ backgroundColor: "#1e89d7", borderRadius: "100%", border: "1px solid #1e89d7" }} /> </div> <div className="edit-actions"> <select @@ -522,7 +517,7 @@ export default class SharingManager extends React.Component<{}> { style={{ backgroundColor: this.copied ? "lawngreen" : "gainsboro" }} onClick={this.copy} > - <FontAwesomeIcon icon={fa.faCopy} /> + <FontAwesomeIcon icon={"copy"} /> </div> </div> } @@ -584,9 +579,9 @@ export default class SharingManager extends React.Component<{}> { <div className="user-sort" onClick={action(() => this.individualSort = this.individualSort === "ascending" ? "descending" : this.individualSort === "descending" ? "none" : "ascending")}> - Individuals {this.individualSort === "ascending" ? <FontAwesomeIcon icon={fa.faCaretUp} size={"xs"} /> - : this.individualSort === "descending" ? <FontAwesomeIcon icon={fa.faCaretDown} size={"xs"} /> - : <FontAwesomeIcon icon={fa.faCaretRight} size={"xs"} />} + Individuals {this.individualSort === "ascending" ? <FontAwesomeIcon icon={"caret-up"} size={"xs"} /> + : this.individualSort === "descending" ? <FontAwesomeIcon icon={"caret-down"} size={"xs"} /> + : <FontAwesomeIcon icon={"caret-right"} size={"xs"} />} </div> <div className={"users-list"} style={{ display: "block" }}>{/*200*/} {userListContents} @@ -596,9 +591,9 @@ export default class SharingManager extends React.Component<{}> { <div className="user-sort" onClick={action(() => this.groupSort = this.groupSort === "ascending" ? "descending" : this.groupSort === "descending" ? "none" : "ascending")}> - Groups {this.groupSort === "ascending" ? <FontAwesomeIcon icon={fa.faCaretUp} size={"xs"} /> - : this.groupSort === "descending" ? <FontAwesomeIcon icon={fa.faCaretDown} size={"xs"} /> - : <FontAwesomeIcon icon={fa.faCaretRight} size={"xs"} />} + Groups {this.groupSort === "ascending" ? <FontAwesomeIcon icon={"caret-up"} size={"xs"} /> + : this.groupSort === "descending" ? <FontAwesomeIcon icon={"caret-down"} size={"xs"} /> + : <FontAwesomeIcon icon={"caret-right"} size={"xs"} />} </div> <div className={"groups-list"} style={{ display: !displayGroupList ? "flex" : "block" }}>{/*200*/} diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx index ccc54058d..32fb24b32 100644 --- a/src/client/views/AntimodeMenu.tsx +++ b/src/client/views/AntimodeMenu.tsx @@ -8,7 +8,7 @@ export interface AntimodeMenuProps { * This is an abstract class that serves as the base for a PDF-style or Marquee-style * menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example. */ -export default abstract class AntimodeMenu<T extends AntimodeMenuProps> extends React.Component<T, {}> { +export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends React.Component<T, {}> { protected _offsetY: number = 0; protected _offsetX: number = 0; protected _mainCont: React.RefObject<HTMLDivElement> = React.createRef(); diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 07f7b8e6d..cb34b8873 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -3,14 +3,9 @@ import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from "./ContextM import { observable, action, computed, runInAction, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import "./ContextMenu.scss"; -import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faSearch, faCircle } from '@fortawesome/free-solid-svg-icons'; import Measure from "react-measure"; -library.add(faSearch); -library.add(faCircle); - @observer export class ContextMenu extends React.Component { static Instance: ContextMenu; diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 7e233ec04..22bfbe217 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -1,13 +1,10 @@ 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 { UndoManager } from "../util/UndoManager"; -library.add(faAngleRight); - export interface OriginalMenuProps { description: string; event: (stuff?: any) => void; @@ -115,7 +112,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select <div className="contextMenu-description" onMouseEnter={this.onPointerEnter} style={{ alignItems: "center" }} > {this.props.description} - <FontAwesomeIcon icon={faAngleRight} size="lg" style={{ position: "absolute", right: "10px" }} /> + <FontAwesomeIcon icon={"angle-right"} size="lg" style={{ position: "absolute", right: "10px" }} /> </div> {submenu} </div> diff --git a/src/client/views/DictationOverlay.tsx b/src/client/views/DictationOverlay.tsx index 9ed14509f..f4f96da8a 100644 --- a/src/client/views/DictationOverlay.tsx +++ b/src/client/views/DictationOverlay.tsx @@ -4,7 +4,7 @@ import "normalize.css"; import * as React from 'react'; import { DictationManager } from '../util/DictationManager'; import "./Main.scss"; -import MainViewModal from './MainViewModal'; +import { MainViewModal } from './MainViewModal'; @observer export class DictationOverlay extends React.Component { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 6e452e52d..659adebbc 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -1,47 +1,34 @@ -import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faPhotoVideo, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Tooltip } from '@material-ui/core'; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast } from "../../fields/Doc"; +import { Doc } from "../../fields/Doc"; import { RichTextField } from '../../fields/RichTextField'; import { Cast, NumCast } from "../../fields/Types"; import { emptyFunction, setupMoveUpEvents } from "../../Utils"; -import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; +import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; -import { Docs, DocUtils } from '../documents/Documents'; +import { Docs } from '../documents/Documents'; +import { CurrentUserUtils } from '../util/CurrentUserUtils'; import { DragManager } from '../util/DragManager'; +import { SelectionManager } from '../util/SelectionManager'; +import { SharingManager } from '../util/SharingManager'; import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView'; import { ParentDocSelector } from './collections/ParentDocumentSelector'; import './collections/ParentDocumentSelector.scss'; import './DocumentButtonBar.scss'; import { MetadataEntryMenu } from './MetadataEntryMenu'; +import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { DocumentView } from './nodes/DocumentView'; import { GoogleRef } from "./nodes/formattedText/FormattedTextBox"; import { TemplateMenu } from "./TemplateMenu"; import { Template, Templates } from "./Templates"; import React = require("react"); -import { DocumentLinksButton } from './nodes/DocumentLinksButton'; -import { Tooltip } from '@material-ui/core'; -import SharingManager from '../util/SharingManager'; -import { CurrentUserUtils } from '../util/CurrentUserUtils'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; -library.add(faLink); -library.add(faTag); -library.add(faTimes); -library.add(faArrowAltCircleDown); -library.add(faArrowAltCircleUp); -library.add(faArrowAltCircleRight); -library.add(faStopCircle); -library.add(faCheckCircle); -library.add(faCloudUploadAlt); -library.add(faSyncAlt); -library.add(faShare); -library.add(faPhotoVideo); - const cloud: IconProp = "cloud-upload-alt"; const fetch: IconProp = "sync-alt"; @@ -197,7 +184,14 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV @computed get pinButton() { const targetDoc = this.view0?.props.Document; - const isPinned = targetDoc && Doc.isDocPinned(targetDoc); + let isPinned = targetDoc && Doc.isDocPinned(targetDoc); + // More than 1 document selected then all must be in presentation for isPinned to be true (then it will unpin all) + if (SelectionManager.SelectedDocuments().length > 1) { + SelectionManager.SelectedDocuments().forEach((docView: DocumentView) => { + if (Doc.isDocPinned(docView.props.Document)) isPinned = true; + else isPinned = false; + }); + } return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}> <div className="documentButtonBar-linker" style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white", border: isPinned ? "black 1px solid " : "" }} diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8e44bcf8f..7b665ccd3 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,5 +1,4 @@ -import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faAngleDoubleLeft, faAngleDoubleRight, faAngleLeft, faAngleRight, faArrowAltCircleDown, faArrowAltCircleUp, faCaretUp, faCheckCircle, faCloudUploadAlt, faExternalLinkAlt, faFilePdf, faFilm, faImage, faLink, faObjectGroup, faPause, faShare, faStickyNote, faStopCircle, faSyncAlt, faTag, faTextHeight, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from '@material-ui/core'; import { action, computed, observable, reaction, runInAction } from "mobx"; @@ -19,35 +18,13 @@ import { SelectionManager } from "../util/SelectionManager"; import { SnappingManager } from '../util/SnappingManager'; import { undoBatch, UndoManager } from "../util/UndoManager"; import { CollectionDockingView } from './collections/CollectionDockingView'; -import FormatShapePane from './collections/collectionFreeForm/FormatShapePane'; +import { FormatShapePane } from './collections/collectionFreeForm/FormatShapePane'; import { DocumentButtonBar } from './DocumentButtonBar'; import './DocumentDecorations.scss'; import { DocumentView } from "./nodes/DocumentView"; import React = require("react"); import e = require('express'); -library.add(faCaretUp); -library.add(faObjectGroup); -library.add(faStickyNote); -library.add(faFilePdf); -library.add(faFilm, faTextHeight); -library.add(faLink); -library.add(faTag); -library.add(faTimes); -library.add(faArrowAltCircleDown); -library.add(faArrowAltCircleUp); -library.add(faStopCircle); -library.add(faCheckCircle); -library.add(faCloudUploadAlt); -library.add(faSyncAlt); -library.add(faShare); -library.add(faAngleDoubleLeft); -library.add(faAngleDoubleRight); -library.add(faAngleLeft); -library.add(faAngleRight); -library.add(faPause); -library.add(faExternalLinkAlt); - @observer export class DocumentDecorations extends React.Component<{}, { value: string }> { static Instance: DocumentDecorations; @@ -587,12 +564,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } } public static DocumentIcon(layout: string) { - const button = layout.indexOf("PDFBox") !== -1 ? faFilePdf : - layout.indexOf("ImageBox") !== -1 ? faImage : - layout.indexOf("Formatted") !== -1 ? faStickyNote : - layout.indexOf("Video") !== -1 ? faFilm : - layout.indexOf("Collection") !== -1 ? faObjectGroup : - faCaretUp; + const button = layout.indexOf("PDFBox") !== -1 ? "file-pdf" : + layout.indexOf("ImageBox") !== -1 ? "image" : + layout.indexOf("Formatted") !== -1 ? "sticky-note" : + layout.indexOf("Video") !== -1 ? "film" : + layout.indexOf("Collection") !== -1 ? "object-group" : + "caret-up"; return <FontAwesomeIcon icon={button} className="documentView-minimizedIcon" />; } render() { @@ -615,7 +592,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> <Tooltip title={<><div className="dash-tooltip">Close</div></>} placement="top"> <div className="documentDecorations-closeButton" onClick={this.onCloseClick}> {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} - <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" /> + <FontAwesomeIcon className="documentdecorations-times" icon={"times"} size="lg" /> </div></Tooltip>) : (null); const titleArea = this._edtingTitle ? @@ -705,7 +682,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> <Tooltip title={<><div className="dash-tooltip">tap to select containing document</div></>} placement="top"> <div id="documentDecorations-levelSelector" className="documentDecorations-selector" onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}> - <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" /> + <FontAwesomeIcon className="documentdecorations-times" icon={"arrow-alt-circle-up"} size="lg" /> </div></Tooltip>} <div id={`documentDecorations-${useRotation ? "rotation" : "borderRadius"}`} onPointerDown={useRotation ? this.onRotateDown : this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}>{useRotation && "⟲"}</div> diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index b96802f06..d0e6ed463 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -4,10 +4,8 @@ import { observer } from 'mobx-react'; import * as Autosuggest from 'react-autosuggest'; import { ObjectField } from '../../fields/ObjectField'; import { SchemaHeaderField } from '../../fields/SchemaHeaderField'; -import "./EditableView.scss"; import { DragManager } from '../util/DragManager'; -import { ComputedField } from '../../fields/ScriptField'; -import { FieldValue } from '../../fields/Types'; +import "./EditableView.scss"; export interface EditableProps { /** @@ -171,6 +169,7 @@ export class EditableView extends React.Component<EditableProps> { onPointerDown: this.stopPropagation, onClick: this.stopPropagation, onPointerUp: this.stopPropagation, + onKeyPress: this.stopPropagation, value: this.props.autosuggestProps.value, onChange: this.props.autosuggestProps.onChange }} @@ -179,6 +178,10 @@ export class EditableView extends React.Component<EditableProps> { defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus={true} + onKeyPress={e => { + e.stopPropagation(); + (e.nativeEvent as any).Aaaa = 3; + }} onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true)} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} style={{ display: this.props.display, fontSize: this.props.fontSize, minWidth: 20 }} diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 260cffc90..63711a3cb 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -26,7 +26,7 @@ import * as fitCurve from 'fit-curve'; import { CollectionFreeFormViewChrome } from "./collections/CollectionMenu"; @observer -export default class GestureOverlay extends Touchable { +export class GestureOverlay extends Touchable { static Instance: GestureOverlay; @observable public InkShape: string = ""; diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 9e7f525b7..b29a04ea7 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -6,22 +6,22 @@ import { InkTool } from "../../fields/InkField"; import { List } from "../../fields/List"; import { ScriptField } from "../../fields/ScriptField"; import { Cast, PromiseValue } from "../../fields/Types"; -import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; +import { GoogleAuthenticationManager } from "../apis/GoogleAuthenticationManager"; import { DocServer } from "../DocServer"; import { DocumentType } from "../documents/DocumentTypes"; import { DictationManager } from "../util/DictationManager"; import { DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; -import SharingManager from "../util/SharingManager"; +import { SharingManager } from "../util/SharingManager"; import { undoBatch, UndoManager } from "../util/UndoManager"; import { CollectionDockingView } from "./collections/CollectionDockingView"; import { DocumentDecorations } from "./DocumentDecorations"; import { MainView } from "./MainView"; import { DocumentView } from "./nodes/DocumentView"; import { DocumentLinksButton } from "./nodes/DocumentLinksButton"; -import PDFMenu from "./pdf/PDFMenu"; +import { PDFMenu } from "./pdf/PDFMenu"; import { ContextMenu } from "./ContextMenu"; -import GroupManager from "../util/GroupManager"; +import { GroupManager } from "../util/GroupManager"; import { CollectionFreeFormViewChrome } from "./collections/CollectionMenu"; const modifiers = ["control", "meta", "shift", "alt"]; @@ -31,7 +31,7 @@ type KeyControlInfo = { stopPropagation: boolean }; -export default class KeyManager { +export class KeyManager { public static Instance: KeyManager = new KeyManager(); private router = new Map<string, KeyHandler>(); @@ -121,9 +121,7 @@ export default class KeyManager { } const selected = SelectionManager.SelectedDocuments().slice(); - UndoManager.RunInBatch(() => { - selected.map(dv => dv.props.removeDocument?.(dv.props.Document)); - }, "delete"); + UndoManager.RunInBatch(() => selected.map(dv => dv.props.removeDocument?.(dv.props.Document)), "delete"); SelectionManager.DeselectAll(); break; case "arrowleft": diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 3376fcd97..b972d4e41 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -1,27 +1,22 @@ -import { library } from "@fortawesome/fontawesome-svg-core"; -import { faPaintBrush } from "@fortawesome/free-solid-svg-icons"; +import { action } from "mobx"; import { observer } from "mobx-react"; +import { Doc } from "../../fields/Doc"; import { documentSchema } from "../../fields/documentSchemas"; import { InkData, InkField, InkTool } from "../../fields/InkField"; import { makeInterface } from "../../fields/Schema"; import { Cast, StrCast } from "../../fields/Types"; import { TraceMobx } from "../../fields/util"; +import { setupMoveUpEvents } from "../../Utils"; import { CognitiveServices } from "../cognitive_services/CognitiveServices"; import { InteractionUtils } from "../util/InteractionUtils"; +import { Scripting } from "../util/Scripting"; +import { UndoManager } from "../util/UndoManager"; +import { FormatShapePane } from "./collections/collectionFreeForm/FormatShapePane"; import { ContextMenu } from "./ContextMenu"; import { ViewBoxBaseComponent } from "./DocComponent"; import "./InkingStroke.scss"; import { FieldView, FieldViewProps } from "./nodes/FieldView"; import React = require("react"); -import { Scripting } from "../util/Scripting"; -import { Doc } from "../../fields/Doc"; -import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane"; -import { action } from "mobx"; -import { setupMoveUpEvents } from "../../Utils"; -import { undoBatch, UndoManager } from "../util/UndoManager"; - - -library.add(faPaintBrush); type InkDocument = makeInterface<[typeof documentSchema]>; const InkDocument = makeInterface(documentSchema); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f8be58f8d..3958b2a8c 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -12,45 +12,45 @@ import * as rp from 'request-promise'; import { Doc, DocListCast, Field, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; +import { PrefetchProxy } from '../../fields/Proxy'; import { listSpec } from '../../fields/Schema'; import { ScriptField } from '../../fields/ScriptField'; -import { BoolCast, Cast, FieldValue, StrCast, NumCast } from '../../fields/Types'; +import { BoolCast, Cast, FieldValue, NumCast, StrCast } from '../../fields/Types'; import { TraceMobx } from '../../fields/util'; -import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils, returnEmptyDoclist } from '../../Utils'; -import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; +import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils'; +import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { Networking } from '../Network'; import { CurrentUserUtils } from '../util/CurrentUserUtils'; import { DocumentManager } from '../util/DocumentManager'; -import GroupManager from '../util/GroupManager'; +import { GroupManager } from '../util/GroupManager'; import { HistoryUtil } from '../util/History'; import { Hypothesis } from '../util/HypothesisUtils'; import { LinkManager } from '../util/LinkManager'; import { Scripting } from '../util/Scripting'; import { SearchUtil } from '../util/SearchUtil'; import { SelectionManager } from '../util/SelectionManager'; -import SettingsManager from '../util/SettingsManager'; -import SharingManager from '../util/SharingManager'; +import { SettingsManager } from '../util/SettingsManager'; +import { SharingManager } from '../util/SharingManager'; import { SnappingManager } from '../util/SnappingManager'; import { Transform } from '../util/Transform'; import { TimelineMenu } from './animationtimeline/TimelineMenu'; import { CollectionDockingView } from './collections/CollectionDockingView'; -import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane"; -import MarqueeOptionsMenu from './collections/collectionFreeForm/MarqueeOptionsMenu'; +import { FormatShapePane } from "./collections/collectionFreeForm/FormatShapePane"; +import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; import { PropertiesView } from './collections/collectionFreeForm/PropertiesView'; import { CollectionLinearView } from './collections/CollectionLinearView'; -import CollectionMenu from './collections/CollectionMenu'; +import { CollectionMenu } from './collections/CollectionMenu'; import { CollectionView, CollectionViewType } from './collections/CollectionView'; import { ContextMenu } from './ContextMenu'; import { DictationOverlay } from './DictationOverlay'; import { DocumentDecorations } from './DocumentDecorations'; -import GestureOverlay from './GestureOverlay'; +import { GestureOverlay } from './GestureOverlay'; import { ANTIMODEMENU_HEIGHT, SEARCH_PANEL_HEIGHT } from './globalCssVariables.scss'; -import KeyManager from './GlobalKeyHandler'; +import { KeyManager } from './GlobalKeyHandler'; import { LinkMenu } from './linking/LinkMenu'; -import "./MainView.scss"; import { AudioBox } from './nodes/AudioBox'; import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { DocumentView } from './nodes/DocumentView'; @@ -61,9 +61,10 @@ import { RadialMenu } from './nodes/RadialMenu'; import { TaskCompletionBox } from './nodes/TaskCompletedBox'; import { WebBox } from './nodes/WebBox'; import { OverlayView } from './OverlayView'; -import PDFMenu from './pdf/PDFMenu'; +import { PDFMenu } from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; import { SearchBox } from './search/SearchBox'; +import "./MainView.scss"; @observer export class MainView extends React.Component { @@ -167,13 +168,13 @@ export class MainView extends React.Component { library.add(fa.faEdit, fa.faTrash, fa.faTrashAlt, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faCalendar, fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, - fa.faLock, fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone, fa.faKeyboard, - fa.faQuestion, fa.faTasks, fa.faPalette, fa.faAngleRight, fa.faBell, fa.faCamera, fa.faExpand, fa.faCaretDown, fa.faCaretLeft, fa.faCaretRight, + fa.faLock, fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointLeft, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone, fa.faKeyboard, + fa.faQuestion, fa.faTasks, fa.faPalette, fa.faAngleLeft, fa.faAngleRight, fa.faBell, fa.faCamera, fa.faExpand, fa.faCaretDown, fa.faCaretLeft, fa.faCaretRight, fa.faCaretSquareDown, fa.faCaretSquareRight, fa.faArrowsAltH, fa.faPlus, fa.faMinus, fa.faTerminal, fa.faToggleOn, fa.faFile, fa.faLocationArrow, - fa.faSearch, fa.faFileDownload, fa.faStop, fa.faCalculator, fa.faWindowMaximize, fa.faAddressCard, fa.faQuestionCircle, fa.faArrowLeft, + fa.faSearch, fa.faFileDownload, fa.faFileUpload, fa.faStop, fa.faCalculator, fa.faWindowMaximize, fa.faAddressCard, fa.faQuestionCircle, fa.faArrowLeft, fa.faArrowRight, fa.faArrowDown, fa.faArrowUp, fa.faBolt, fa.faBullseye, fa.faCaretUp, fa.faCat, fa.faCheck, fa.faChevronRight, fa.faClipboard, fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt, - fa.faFileAudio, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer, + fa.faFileAudio, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAmericas, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer, fa.faMusic, fa.faObjectGroup, fa.faPause, fa.faPen, fa.faPenNib, fa.faPhone, fa.faPlay, fa.faPortrait, fa.faRedoAlt, fa.faStamp, fa.faStickyNote, fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes, fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined, @@ -182,7 +183,10 @@ export class MainView extends React.Component { fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp, fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, faBuffer, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl, - fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faClosedCaptioning); + fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faTextHeight, fa.faClosedCaptioning, fa.faInfoCircle, fa.faTag, fa.faSyncAlt, fa.faPhotoVideo, + fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical, + fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, + fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash); this.initEventListeners(); this.initAuthenticationRouters(); } @@ -252,8 +256,25 @@ export class MainView extends React.Component { } @action + createNewPresentation = async () => { + await this.userDoc.myPresentations; + if (this.userDoc.myPresentations === undefined) { + this.userDoc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], { + title: "PRESENTATION TRAILS", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true, system: true + })); + } + const pres = Docs.Create.PresDocument(new List<Doc>(), + { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true }); + CollectionDockingView.AddRightSplit(pres); + Doc.UserDoc().activePresentation = pres; + const myPresentations = Doc.UserDoc().myPresentations as Doc; + Doc.AddDocToList(myPresentations, "data", pres); + } + + @action createNewDashboard = async (id?: string) => { const myCatalog = Doc.UserDoc().myCatalog as Doc; + const myPresentations = Doc.UserDoc().myPresentations as Doc; const presentation = Doc.MakeCopy(Doc.UserDoc().emptyPresentation as Doc, true); const dashboards = Cast(this.userDoc.myDashboards, Doc) as Doc; const dashboardCount = DocListCast(dashboards.data).length + 1; @@ -270,6 +291,7 @@ export class MainView extends React.Component { const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [myCatalog] }], { title: `Dashboard ${dashboardCount}` }, id, "row"); Doc.AddDocToList(myCatalog, "data", freeformDoc); Doc.AddDocToList(myCatalog, "data", presentation); + Doc.AddDocToList(myPresentations, "data", presentation); Doc.UserDoc().activePresentation = presentation; const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); @@ -898,7 +920,7 @@ export class MainView extends React.Component { document.removeEventListener("editSuccess", onSuccess); }; - // For some reason, Hypothes.is annotations don't load until a click is registered on the page, + // For some reason, Hypothes.is annotations don't load until a click is registered on the page, // so we keep simulating clicks until annotations have loaded and editing is successful const interval = setInterval(() => { !success && simulateMouseClick(ele, 50, 50, 50, 50); diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx index 19387f619..34e0ff126 100644 --- a/src/client/views/MainViewModal.tsx +++ b/src/client/views/MainViewModal.tsx @@ -14,7 +14,7 @@ export interface MainViewOverlayProps { } @observer -export default class MainViewModal extends React.Component<MainViewOverlayProps> { +export class MainViewModal extends React.Component<MainViewOverlayProps> { render() { const p = this.props; diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index ecd0ee37e..4abb2cb7a 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -1,52 +1,39 @@ -import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faPhotoVideo, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Tooltip } from '@material-ui/core'; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DataSym, AclEdit, AclAdmin } from "../../fields/Doc"; +import { AclAdmin, AclEdit, DataSym, Doc } from "../../fields/Doc"; +import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; -import { Cast, NumCast, BoolCast } from "../../fields/Types"; -import { emptyFunction, setupMoveUpEvents, Utils } from "../../Utils"; -import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; +import { Cast, NumCast } from "../../fields/Types"; +import { ImageField } from '../../fields/URLField'; +import { GetEffectiveAcl } from '../../fields/util'; +import { emptyFunction, setupMoveUpEvents } from "../../Utils"; +import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; +import { GooglePhotos } from '../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocUtils } from '../documents/Documents'; +import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; +import { SelectionManager } from '../util/SelectionManager'; +import { SharingManager } from '../util/SharingManager'; +import { undoBatch } from '../util/UndoManager'; import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView'; import { ParentDocSelector } from './collections/ParentDocumentSelector'; import './collections/ParentDocumentSelector.scss'; -import './PropertiesButtons.scss'; import { MetadataEntryMenu } from './MetadataEntryMenu'; import { DocumentView } from './nodes/DocumentView'; import { GoogleRef } from "./nodes/formattedText/FormattedTextBox"; +import { PresBox } from './nodes/PresBox'; +import './PropertiesButtons.scss'; import { TemplateMenu } from "./TemplateMenu"; import { Template, Templates } from "./Templates"; import React = require("react"); -import { Tooltip } from '@material-ui/core'; -import { SelectionManager } from '../util/SelectionManager'; -import SharingManager from '../util/SharingManager'; -import { GooglePhotos } from '../apis/google_docs/GooglePhotosClientUtils'; -import { ImageField } from '../../fields/URLField'; -import { undoBatch, UndoManager } from '../util/UndoManager'; -import { DocumentType } from '../documents/DocumentTypes'; -import { InkField } from '../../fields/InkField'; -import { PresBox } from './nodes/PresBox'; -import { GetEffectiveAcl } from '../../fields/util'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; -library.add(faLink); -library.add(faTag); -library.add(faTimes); -library.add(faArrowAltCircleDown); -library.add(faArrowAltCircleUp); -library.add(faArrowAltCircleRight); -library.add(faStopCircle); -library.add(faCheckCircle); -library.add(faCloudUploadAlt); -library.add(faSyncAlt); -library.add(faShare); -library.add(faPhotoVideo); const cloud: IconProp = "cloud-upload-alt"; const fetch: IconProp = "sync-alt"; @@ -236,7 +223,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { const y = targetDoc._panY; const scale = targetDoc._viewScale; } - return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin with this view"}</div></>} placement="top"> + return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation with current view"}</div></>} placement="top"> <div> <div className="propertiesButtons-linker" onClick={e => { diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index db087fb23..c598b2861 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -1,17 +1,12 @@ -import * as React from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, observable } from 'mobx'; import { observer } from 'mobx-react'; -import { observable, action } from 'mobx'; -import './ScriptingRepl.scss'; -import { Scripting, CompileScript, ts, Transformer } from '../util/Scripting'; +import * as React from 'react'; import { DocumentManager } from '../util/DocumentManager'; -import { OverlayView } from './OverlayView'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCaretDown, faCaretRight } from '@fortawesome/free-solid-svg-icons'; +import { CompileScript, Scripting, Transformer, ts } from '../util/Scripting'; import { DocumentIconContainer } from './nodes/DocumentIcon'; - -library.add(faCaretDown); -library.add(faCaretRight); +import { OverlayView } from './OverlayView'; +import './ScriptingRepl.scss'; @observer export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: () => void, value: { [key: string]: any }, name?: string }> { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 27e613c03..4d4bc2a97 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -788,7 +788,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { observer.observe(this.props.glContainer._element[0]); this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged); this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged(); - this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: color() }), () => updateTabColor(), { fireImmediately: true }); + this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: color() }), updateTabColor, { fireImmediately: true }); } componentWillUnmount() { diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 00415dab1..d086c8b1f 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -22,18 +22,18 @@ import { DragManager } from "../../util/DragManager"; import { Scripting } from "../../util/Scripting"; import { SelectionManager } from "../../util/SelectionManager"; import { undoBatch } from "../../util/UndoManager"; -import AntimodeMenu, { AntimodeMenuProps } from "../AntimodeMenu"; +import { AntimodeMenu, AntimodeMenuProps } from "../AntimodeMenu"; import { EditableView } from "../EditableView"; -import GestureOverlay from "../GestureOverlay"; +import { GestureOverlay } from "../GestureOverlay"; import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart, SetActiveBezierApprox, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from "../InkingStroke"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DocumentView } from "../nodes/DocumentView"; -import RichTextMenu from "../nodes/formattedText/RichTextMenu"; +import { RichTextMenu } from "../nodes/formattedText/RichTextMenu"; import "./CollectionMenu.scss"; import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView"; @observer -export default class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> { +export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> { static Instance: CollectionMenu; @observable SelectedCollection: DocumentView | undefined; diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index e37644f2f..ac789ab48 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -1,45 +1,41 @@ import React = require("react"); -import { action, observable, trace, computed, runInAction } from "mobx"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; +import DatePicker from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; import { CellInfo } from "react-table"; import "react-table/react-table.css"; -import { emptyFunction, returnFalse, returnZero, returnOne, returnEmptyFilter, Utils, emptyPath, returnEmptyDoclist } from "../../../Utils"; +import { DateField } from "../../../fields/DateField"; import { Doc, DocListCast, Field, Opt } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; +import { List } from "../../../fields/List"; +import { RichTextField } from "../../../fields/RichTextField"; +import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; +import { ComputedField } from "../../../fields/ScriptField"; +import { BoolCast, Cast, DateCast, FieldValue, NumCast, StrCast } from "../../../fields/Types"; +import { ImageField } from "../../../fields/URLField"; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnZero, Utils } from "../../../Utils"; +import { Docs } from "../../documents/Documents"; +import { DocumentType } from "../../documents/DocumentTypes"; +import { DocumentManager } from "../../util/DocumentManager"; +import { DragManager, SetupDrag } from "../../util/DragManager"; import { KeyCodes } from "../../util/KeyCodes"; -import { SetupDrag, DragManager } from "../../util/DragManager"; import { CompileScript } from "../../util/Scripting"; +import { SearchUtil } from "../../util/SearchUtil"; +import { SnappingManager } from "../../util/SnappingManager"; import { Transform } from "../../util/Transform"; -import { MAX_ROW_HEIGHT, COLLECTION_BORDER_WIDTH } from '../globalCssVariables.scss'; +import { undoBatch } from "../../util/UndoManager"; import '../DocumentDecorations.scss'; import { EditableView } from "../EditableView"; -import { FieldView, FieldViewProps } from "../nodes/FieldView"; -import "./CollectionSchemaView.scss"; -import { CollectionView, Flyout } from "./CollectionView"; -import { NumCast, StrCast, BoolCast, FieldValue, Cast, DateCast } from "../../../fields/Types"; -import { Docs } from "../../documents/Documents"; -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faExpand } from '@fortawesome/free-solid-svg-icons'; -import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { undoBatch } from "../../util/UndoManager"; -import { SnappingManager } from "../../util/SnappingManager"; -import { ComputedField } from "../../../fields/ScriptField"; -import { ImageField } from "../../../fields/URLField"; -import { List } from "../../../fields/List"; -import { OverlayView } from "../OverlayView"; +import { COLLECTION_BORDER_WIDTH, MAX_ROW_HEIGHT } from '../globalCssVariables.scss'; import { DocumentIconContainer } from "../nodes/DocumentIcon"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import DatePicker from "react-datepicker"; -import "react-datepicker/dist/react-datepicker.css"; -import { DateField } from "../../../fields/DateField"; -import { RichTextField } from "../../../fields/RichTextField"; -import { DocumentManager } from "../../util/DocumentManager"; -import { SearchUtil } from "../../util/SearchUtil"; -import { DocumentType } from "../../documents/DocumentTypes"; +import { FieldViewProps } from "../nodes/FieldView"; +import { OverlayView } from "../OverlayView"; +import "./CollectionSchemaView.scss"; +import { CollectionView } from "./CollectionView"; const path = require('path'); -library.add(faExpand); - export interface CellProps { row: number; col: number; @@ -287,12 +283,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> { if (this.props.isFocused && this.props.isEditable) className += " focused"; if (this.props.isFocused && !this.props.isEditable) className += " inactive"; - - // let docExpander = ( - // <div className="collectionSchemaView-cellContents-docExpander" onPointerDown={this.expandDoc} > - // <FontAwesomeIcon icon="expand" size="sm" /> - // </div> - // ); const positions = []; let cfield = props.Document[props.fieldKey]; this.type = props.fieldKey; diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 4754adc90..a3475b481 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -1,6 +1,5 @@ import React = require("react"); -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action } from "mobx"; import { ReactTableDefaults, RowInfo, TableCellRenderer } from "react-table"; import { Doc } from "../../../fields/Doc"; @@ -13,9 +12,6 @@ import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { ContextMenu } from "../ContextMenu"; import "./CollectionSchemaView.scss"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -library.add(faGripVertical, faTrash); export interface MovableColumnProps { columnRenderer: TableCellRenderer; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index a78061da6..10c33fc4d 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -1,6 +1,4 @@ import React = require("react"); -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCog, faPlus, faSortDown, faSortUp, faTable } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, untracked } from "mobx"; import { observer } from "mobx-react"; @@ -9,26 +7,23 @@ import { Resize } from "react-table"; import "react-table/react-table.css"; import { Doc, Opt } from "../../../fields/Doc"; import { List } from "../../../fields/List"; -import { listSpec, makeInterface, emptySchema } from "../../../fields/Schema"; +import { listSpec } from "../../../fields/Schema"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { Cast, NumCast, BoolCast } from "../../../fields/Types"; +import { Cast, NumCast } from "../../../fields/Types"; import { TraceMobx } from "../../../fields/util"; import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents } from "../../../Utils"; +import { SelectionManager } from "../../util/SelectionManager"; import { SnappingManager } from "../../util/SnappingManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { COLLECTION_BORDER_WIDTH } from '../../views/globalCssVariables.scss'; +import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from "../ContextMenuItem"; import '../DocumentDecorations.scss'; import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; import { SchemaTable } from "./SchemaTable"; -import { SelectionManager } from "../../util/SelectionManager"; -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; - -library.add(faCog, faPlus, faSortUp, faSortDown); -library.add(faTable); // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 export enum ColumnType { diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 0a206a6c6..12b7d742b 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -1,35 +1,31 @@ import React = require("react"); -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faPalette } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, observable, runInAction, computed } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../../fields/Doc"; import { RichTextField } from "../../../fields/RichTextField"; +import { listSpec } from "../../../fields/Schema"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField"; import { ScriptField } from "../../../fields/ScriptField"; -import { NumCast, StrCast, Cast } from "../../../fields/Types"; +import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { ImageField } from "../../../fields/URLField"; import { TraceMobx } from "../../../fields/util"; +import { emptyFunction, setupMoveUpEvents } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; import { DragManager } from "../../util/DragManager"; +import { SnappingManager } from "../../util/SnappingManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { EditableView } from "../EditableView"; import { CollectionStackingView } from "./CollectionStackingView"; -import { setupMoveUpEvents, emptyFunction } from "../../../Utils"; import "./CollectionStackingView.scss"; -import { listSpec } from "../../../fields/Schema"; -import { SnappingManager } from "../../util/SnappingManager"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; -library.add(faPalette); - interface CSVFieldColumnProps { cols: () => number; headings: () => object[]; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 9460095e4..c43349059 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -736,8 +736,8 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll e.stopPropagation(); e.preventDefault(); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - } else if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myRecentlyClosed) { - ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.UserDoc().myRecentlyClosed = new List<Doc>(), icon: "plus" }); + } else if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myInactiveDocs) { + ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.UserDoc().myInactiveDocs = new List<Doc>(), icon: "plus" }); e.stopPropagation(); e.preventDefault(); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5230fb533..1ad63c34e 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,6 +1,3 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit, faEye } from '@fortawesome/free-regular-svg-icons'; -import { faColumns, faCopy, faEllipsisV, faFingerprint, faGlobeAmericas, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable } from 'mobx'; import { observer } from "mobx-react"; @@ -53,8 +50,6 @@ export const Flyout = higflyout.default; export const COLLECTION_BORDER_WIDTH = 2; const path = require('path'); -library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faGlobeAmericas, faEllipsisV, faImage, faEye as any, faCopy); - export enum CollectionViewType { Invalid = "invalid", Freeform = "freeform", @@ -184,7 +179,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus doc.context = this.props.Document; }); added.map(add => Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); - // targetDataDoc[this.props.fieldKey] = new List<Doc>([...docList, ...added]); (targetDataDoc[this.props.fieldKey] as List<Doc>).push(...added); targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); const lastModified = "lastModified"; @@ -524,7 +518,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus <div className="collectionTimeView-addFacet" style={{ width: `${this.facetWidth()}px` }} onPointerDown={e => e.stopPropagation()}> <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout}> <div className="collectionTimeView-button"> - <FontAwesomeIcon icon={faEdit} size={"lg"} /> + <FontAwesomeIcon icon={"edit"} size={"lg"} /> <span className="collectionTimeView-span">Facet Filters</span> </div> </Flyout> diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 149d4927b..a6de32145 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -1,27 +1,21 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Tooltip } from "@material-ui/core"; +import { computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; +import { observer } from "mobx-react"; import * as React from "react"; -import './ParentDocumentSelector.scss'; import { Doc } from "../../../fields/Doc"; -import { observer } from "mobx-react"; -import { observable, action, runInAction, trace, computed, reaction, IReactionDisposer } from "mobx"; import { Id } from "../../../fields/FieldSymbols"; +import { NumCast } from "../../../fields/Types"; import { SearchUtil } from "../../util/SearchUtil"; -import { CollectionDockingView } from "./CollectionDockingView"; -import { NumCast, StrCast } from "../../../fields/Types"; -import { CollectionViewType } from "./CollectionView"; import { DocumentButtonBar } from "../DocumentButtonBar"; -import { DocumentManager } from "../../util/DocumentManager"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faCog, faChevronCircleUp } from "@fortawesome/free-solid-svg-icons"; -import { library } from "@fortawesome/fontawesome-svg-core"; import { DocumentView } from "../nodes/DocumentView"; -import { SelectionManager } from "../../util/SelectionManager"; -import { Tooltip } from "@material-ui/core"; +import { CollectionDockingView } from "./CollectionDockingView"; +import { CollectionViewType } from "./CollectionView"; +import './ParentDocumentSelector.scss'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; -library.add(faCog); - type SelectorProps = { Document: Doc, Stack?: any, @@ -93,7 +87,7 @@ export class ParentDocSelector extends React.Component<SelectorProps> { return <div title="Show Contexts" onPointerDown={e => e.stopPropagation()} className="parentDocumentSelector-linkFlyout"> <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout}> <span className="parentDocumentSelector-button" > - <FontAwesomeIcon icon={faChevronCircleUp} size={"lg"} /> + <FontAwesomeIcon icon={"chevron-circle-up"} size={"lg"} /> </span> </Flyout> </div>; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1cf06be3e..d64b49c4d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,7 +1,4 @@ -import { library } from "@fortawesome/fontawesome-svg-core"; -import { faEye } from "@fortawesome/free-regular-svg-icons"; -import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faFileUpload, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons"; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { computedFn } from "mobx-utils"; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../../fields/Doc"; @@ -15,7 +12,7 @@ import { ScriptField } from "../../../../fields/ScriptField"; import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types"; import { TraceMobx } from "../../../../fields/util"; import { GestureUtils } from "../../../../pen-gestures/GestureUtils"; -import { aggregateBounds, intersectRect, returnFalse, returnOne, returnZero, Utils, setupMoveUpEvents } from "../../../../Utils"; +import { aggregateBounds, intersectRect, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from "../../../../Utils"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { DocServer } from "../../../DocServer"; import { Docs, DocUtils } from "../../../documents/Documents"; @@ -24,10 +21,12 @@ import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager, dropActionType } from "../../../util/DragManager"; import { HistoryUtil } from "../../../util/History"; import { InteractionUtils } from "../../../util/InteractionUtils"; +import { LinkManager } from "../../../util/LinkManager"; +import { SearchUtil } from "../../../util/SearchUtil"; import { SelectionManager } from "../../../util/SelectionManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { Transform } from "../../../util/Transform"; -import { undoBatch, UndoManager } from "../../../util/UndoManager"; +import { undoBatch } from "../../../util/UndoManager"; import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss"; import { Timeline } from "../../animationtimeline/Timeline"; import { ContextMenu } from "../../ContextMenu"; @@ -37,20 +36,16 @@ import { DocumentLinksButton } from "../../nodes/DocumentLinksButton"; import { DocumentViewProps } from "../../nodes/DocumentView"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; import { pageSchema } from "../../nodes/ImageBox"; +import { PresBox } from "../../nodes/PresBox"; import { CollectionDockingView } from "../CollectionDockingView"; import { CollectionSubView } from "../CollectionSubView"; import { CollectionViewType } from "../CollectionView"; import { computePivotLayout, computerPassLayout, computerStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult } from "./CollectionFreeFormLayoutEngines"; import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; import "./CollectionFreeFormView.scss"; -import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; +import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); -import { PresBox } from "../../nodes/PresBox"; -import { SearchUtil } from "../../../util/SearchUtil"; -import { LinkManager } from "../../../util/LinkManager"; - -library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); export const panZoomSchema = createSchema({ _panX: "number", @@ -608,7 +603,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P pan = (e: PointerEvent | React.Touch | { clientX: number, clientY: number }): void => { // bcz: theres should be a better way of doing these than referencing these static instances directly MarqueeOptionsMenu.Instance?.fadeOut(true);// I think it makes sense for the marquee menu to go away when panned. -syip2 - // PDFMenu.Instance.fadeOut(true); (commented out for mobile) const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); this.setPan((this.Document._panX || 0) - dx, (this.Document._panY || 0) - dy, undefined, true); @@ -1261,7 +1255,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P const options = ContextMenu.Instance.findByDescription("Options..."); const optionItems = options && "subitems" in options ? options.subitems : []; !this.props.isAnnotationOverlay && !Doc.UserDoc().noviceMode && - optionItems.push({ description: (this.showTimeline ? "Close" : "Open") + " Animation Timeline", event: action(() => this.showTimeline = !this.showTimeline), icon: faEye }); + optionItems.push({ description: (this.showTimeline ? "Close" : "Open") + " Animation Timeline", event: action(() => this.showTimeline = !this.showTimeline), icon: "eye" }); this.props.ContainingCollectionView && optionItems.push({ description: "Undo Collection", event: this.promoteCollection, icon: "table" }); optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" }); @@ -1409,7 +1403,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P centeringShiftY={this.centeringShiftY} presPaths={BoolCast(this.Document.presPathView)} progressivize={BoolCast(this.Document.editProgressivize)} - zoomProgressivize={BoolCast(this.Document.editZoomProgressivize)} + presPinView={BoolCast(this.Document.presPinView)} transition={Cast(this.layoutDoc._viewTransition, "string", null)} viewDefDivClick={this.props.viewDefDivClick} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}> @@ -1495,7 +1489,7 @@ interface CollectionFreeFormViewPannableContentsProps { transition?: string; presPaths?: boolean; progressivize?: boolean; - zoomProgressivize?: boolean; + presPinView?: boolean; } @observer @@ -1562,58 +1556,40 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF doc.style.top = toNumber(top, e.movementY) + 'px'; doc.style.left = toNumber(left, e.movementX) + 'px'; } - this.updateAll(height, width, top, left); + // this.updateAll(height, width, top, left); return false; } return true; } - @action - updateAll = (width: number, height: number, top: number, left: number) => { - const activeItem = Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); - this.updateList(targetDoc, activeItem["viewfinder-width-indexed"], width); - this.updateList(targetDoc, activeItem["viewfinder-height-indexed"], height); - this.updateList(targetDoc, activeItem["viewfinder-top-indexed"], top); - this.updateList(targetDoc, activeItem["viewfinder-left-indexed"], left); - } - - @action - updateList = (doc: Doc, list: any, val: number) => { - const x: List<number> = list; - if (x && x.length >= NumCast(doc.currentFrame) + 1) { - x[NumCast(doc.currentFrame)] = val; - list = x; - } else if (doc && x) { - x.length = NumCast(doc.currentFrame) + 1; - x[NumCast(doc.currentFrame)] = val; - list = x; - } - } - // scale: NumCast(targetDoc._viewScale), @computed get zoomProgressivizeContainer() { - const activeItem = Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); - if (activeItem && activeItem.zoomProgressivize) { - const vfLeft: number = PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-left-indexed"]); - const vfWidth: number = PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-width-indexed"]); - const vfTop: number = PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-top-indexed"]); - const vfHeight: number = PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-height-indexed"]); - return !activeItem.editZoomProgressivize ? (null) : - <div id="resizable" key="zoomProgressivize" className="resizable" onPointerDown={this.onPointerDown} style={{ width: vfWidth, height: vfHeight, top: vfTop, left: vfLeft, position: 'absolute' }}> - <div className='resizers'> - <div id="resizer-tl" className='resizer top-left' onPointerDown={this.onPointerDown}></div> - <div id="resizer-tr" className='resizer top-right' onPointerDown={this.onPointerDown}></div> - <div id="resizer-bl" className='resizer bottom-left' onPointerDown={this.onPointerDown}></div> - <div id="resizer-br" className='resizer bottom-right' onPointerDown={this.onPointerDown}></div> - </div> - </div>; + const activeItem = PresBox.Instance.activeItem; + // const targetDoc = PresBox.Instance.targetDoc; + if (activeItem && activeItem.presPinView && activeItem.id) { + const vfLeft: number = NumCast(activeItem.presPinViewX); + const vfTop: number = NumCast(activeItem.presPinViewY); + const vfWidth: number = 100; + const vfHeight: number = 100; + console.log(vfTop + " | " + vfLeft); + console.log(this.props.presPinView); + return ( + <> + {!this.props.presPinView ? (null) : <div id="resizable" className="resizable" onPointerDown={this.onPointerDown} style={{ width: vfWidth, height: vfHeight, top: vfTop, left: vfLeft, position: 'absolute' }}> + <div className='resizers' key={'resizer' + activeItem.id}> + <div id="resizer-tl" className='resizer top-left' onPointerDown={this.onPointerDown}></div> + <div id="resizer-tr" className='resizer top-right' onPointerDown={this.onPointerDown}></div> + <div id="resizer-bl" className='resizer bottom-left' onPointerDown={this.onPointerDown}></div> + <div id="resizer-br" className='resizer bottom-right' onPointerDown={this.onPointerDown}></div> + </div> + </div>} + </> + ); } } @computed get zoomProgressivize() { - return PresBox.Instance && this.props.zoomProgressivize ? this.zoomProgressivizeContainer : (null); + return PresBox.Instance && PresBox.Instance.activeItem && PresBox.Instance.activeItem.presPinView && PresBox.Instance.layoutDoc.presStatus === 'edit' ? this.zoomProgressivizeContainer : (null); } @computed get progressivize() { diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx index a7f44bbbf..1d3604d7f 100644 --- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx +++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx @@ -9,13 +9,13 @@ import { InkField } from "../../../../fields/InkField"; import { BoolCast, Cast, NumCast } from "../../../../fields/Types"; import { DocumentType } from "../../../documents/DocumentTypes"; import { SelectionManager } from "../../../util/SelectionManager"; -import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu"; +import { AntimodeMenu, AntimodeMenuProps } from "../../AntimodeMenu"; import "./FormatShapePane.scss"; import { undoBatch } from "../../../util/UndoManager"; import { ColorState, SketchPicker } from 'react-color'; @observer -export default class FormatShapePane extends AntimodeMenu<AntimodeMenuProps> { +export class FormatShapePane extends AntimodeMenu<AntimodeMenuProps> { static Instance: FormatShapePane; private _lastFill = "#D0021B"; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx index 2cfe0183c..46298ec6f 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx @@ -1,13 +1,12 @@ import React = require("react"); -import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu"; -import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { unimplementedFunction } from "../../../../Utils"; -import { undoBatch } from "../../../util/UndoManager"; import { Tooltip } from "@material-ui/core"; +import { observer } from "mobx-react"; +import { unimplementedFunction } from "../../../../Utils"; +import { AntimodeMenu, AntimodeMenuProps } from "../../AntimodeMenu"; @observer -export default class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> { +export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> { static Instance: MarqueeOptionsMenu; public createCollection: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction; @@ -16,6 +15,7 @@ export default class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> public inkToText: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction; public showMarquee: () => void = unimplementedFunction; public hideMarquee: () => void = unimplementedFunction; + public pinWithView: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction; constructor(props: Readonly<{}>) { super(props); @@ -53,6 +53,14 @@ export default class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> <FontAwesomeIcon icon="font" size="lg" /> </button> </Tooltip>, + <Tooltip key="pinWithView" title={<><div className="dash-tooltip">Pin to presentation with selected view</div></>} placement="bottom"> + <button + className="antimodeMenu-button" + onPointerDown={this.pinWithView}> + <FontAwesomeIcon icon="map-pin" size="lg" /> + <div style={{ position: 'relative', fontSize: 25, fontWeight: 700, transform: 'translate(-4px, -22px)', color: 'rgba(250,250,250,0.55)' }}>V</div> + </button> + </Tooltip>, ]; return this.getElement(buttons); } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 3a9f31bef..b8019e37b 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,27 +1,28 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, Opt, DocListCast, DataSym, AclEdit, AclAddonly, AclAdmin } from "../../../../fields/Doc"; -import { GetEffectiveAcl } from "../../../../fields/util"; +import { AclAddonly, AclAdmin, AclEdit, DataSym, Doc, DocListCast, Opt } from "../../../../fields/Doc"; import { InkData, InkField, InkTool } from "../../../../fields/InkField"; import { List } from "../../../../fields/List"; import { RichTextField } from "../../../../fields/RichTextField"; import { SchemaHeaderField } from "../../../../fields/SchemaHeaderField"; import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types"; +import { GetEffectiveAcl } from "../../../../fields/util"; import { Utils } from "../../../../Utils"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { Docs, DocumentOptions, DocUtils } from "../../../documents/Documents"; +import { DocumentManager } from "../../../util/DocumentManager"; import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; import { undoBatch, UndoManager } from "../../../util/UndoManager"; import { ContextMenu } from "../../ContextMenu"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; import { PreviewCursor } from "../../PreviewCursor"; +import { CollectionDockingView } from "../CollectionDockingView"; import { SubCollectionViewProps } from "../CollectionSubView"; import { CollectionView } from "../CollectionView"; -import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; +import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu"; import "./MarqueeView.scss"; import React = require("react"); -import { ContextMenuItem } from "../../ContextMenuItem"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -252,6 +253,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque MarqueeOptionsMenu.Instance.showMarquee = this.showMarquee; MarqueeOptionsMenu.Instance.hideMarquee = this.hideMarquee; MarqueeOptionsMenu.Instance.jumpTo(e.clientX, e.clientY); + MarqueeOptionsMenu.Instance.pinWithView = this.pinWithView; document.addEventListener("pointerdown", hideMarquee); } else { this.hideMarquee(); @@ -383,6 +385,38 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque } @undoBatch @action + pinWithView = (e: KeyboardEvent | React.PointerEvent | undefined) => { + const doc = this.props.Document; + const bounds = this.Bounds; + const selected = this.marqueeSelect(false); + const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; + if (curPres) { + const pinDoc = Doc.MakeAlias(doc); + pinDoc.presentationTargetDoc = doc; + pinDoc.presZoomButton = true; + pinDoc.context = curPres; + Doc.AddDocToList(curPres, "data", pinDoc); + if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true; + if (!DocumentManager.Instance.getDocumentView(curPres)) { + CollectionDockingView.AddRightSplit(curPres); + } + if (e instanceof KeyboardEvent ? e.key === "c" : true) { + const x = this.Bounds.left + this.Bounds.width / 2; + const y = this.Bounds.top + this.Bounds.height / 2; + const panelWidth: number = this.props.PanelWidth(); + const panelHeight: number = this.props.PanelHeight(); + const scale = Math.min(Number(panelWidth) / this.Bounds.width, Number(panelHeight) / this.Bounds.height); + pinDoc.presPinView = true; + pinDoc.presPinViewX = x; + pinDoc.presPinViewY = y; + pinDoc.presPinViewScale = scale; + } + } + MarqueeOptionsMenu.Instance.fadeOut(true); + this.hideMarquee(); + } + + @undoBatch @action collection = (e: KeyboardEvent | React.PointerEvent | undefined) => { const bounds = this.Bounds; const selected = this.marqueeSelect(false); diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index e128f6aab..c4f8f4d44 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -1,40 +1,35 @@ import React = require("react"); +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Checkbox, Tooltip } from "@material-ui/core"; +import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import "./PropertiesView.scss"; -import { observable, action, computed, runInAction } from "mobx"; -import { Doc, Field, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt, DocCastAsync, DataSym } from "../../../../fields/Doc"; +import { ColorState, SketchPicker } from "react-color"; +import { AclAddonly, AclAdmin, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, Field, HeightSym, WidthSym } from "../../../../fields/Doc"; +import { Id } from "../../../../fields/FieldSymbols"; +import { InkField } from "../../../../fields/InkField"; import { ComputedField } from "../../../../fields/ScriptField"; -import { EditableView } from "../../EditableView"; -import { KeyValueBox } from "../../nodes/KeyValueBox"; import { Cast, NumCast, StrCast } from "../../../../fields/Types"; -import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView"; -import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils, returnEmptyDoclist } from "../../../../Utils"; -import { Id } from "../../../../fields/FieldSymbols"; -import { Transform } from "../../../util/Transform"; -import { PropertiesButtons } from "../../PropertiesButtons"; -import { SelectionManager } from "../../../util/SelectionManager"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Tooltip, Checkbox } from "@material-ui/core"; -import SharingManager from "../../../util/SharingManager"; +import { GetEffectiveAcl, SharingPermissions } from "../../../../fields/util"; +import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../../Utils"; import { DocumentType } from "../../../documents/DocumentTypes"; -import { SharingPermissions, GetEffectiveAcl } from "../../../../fields/util"; -import { InkField } from "../../../../fields/InkField"; +import { DocumentManager } from "../../../util/DocumentManager"; +import { SelectionManager } from "../../../util/SelectionManager"; +import { SharingManager } from "../../../util/SharingManager"; +import { Transform } from "../../../util/Transform"; import { undoBatch, UndoManager } from "../../../util/UndoManager"; -import { ColorState, SketchPicker } from "react-color"; -import "./FormatShapePane.scss"; +import { EditableView } from "../../EditableView"; +import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView"; +import { KeyValueBox } from "../../nodes/KeyValueBox"; import { PresBox } from "../../nodes/PresBox"; -import { DocumentManager } from "../../../util/DocumentManager"; -import FormatShapePane from "./FormatShapePane"; +import { PropertiesButtons } from "../../PropertiesButtons"; +import { FormatShapePane } from "./FormatShapePane"; +import "./FormatShapePane.scss"; +import "./PropertiesView.scss"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; const _global = (window /* browser */ || global /* node */) as any; -// import * as fa from '@fortawesome/free-solid-svg-icons'; -// import { library } from "@fortawesome/fontawesome-svg-core"; - -// library.add(fa.faPlus, fa.faMinus, fa.faCog); - interface PropertiesViewProps { width: number; height: number; @@ -441,7 +436,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @action setTitle = (value: string) => { if (this.dataDoc) { - this.selectedDoc && (this.selectedDoc.title = value); + this.selectedDoc && Doc.SetInPlace(this.selectedDoc, "title", value, true); KeyValueBox.SetField(this.dataDoc, "title", value, true); return true; } @@ -527,7 +522,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="inputBox-title"> {title} </div> <input className="inputBox-input" type="text" value={value} - onChange={e => setter(e.target.value)} /> + onChange={e => { + setter(e.target.value); + }} + onKeyPress={e => { + e.stopPropagation(); + }} /> <div className="inputBox-button"> <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => 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<FaceRectanglesProps> { +export class FaceRectangles extends React.Component<FaceRectanglesProps> { render() { const faces = DocListCast(this.props.document.faces); diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index fd71876b0..bc5abb0a4 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -64,14 +64,18 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>( const color = StrCast(this.layoutDoc.color, this._foregroundColor); const backgroundColor = StrCast(this.layoutDoc._backgroundColor, StrCast(this.rootDoc.backgroundColor, this.props.backgroundColor?.(this.rootDoc, this.props.renderDepth))); const shape = StrCast(this.layoutDoc.iconShape, "round"); - + const icon = StrCast(this.dataDoc.icon, "user") as any; + const presTrailsIcon = <img + style={{ width: shape === 'round' ? 25 : 30, height: shape === 'round' ? 25 : 30, filter: color === 'white' ? 'invert(100%)' : 'invert(0%)', transform: shape === 'round' ? 'translate(-5px, -7px)' : undefined }} + id={"pres-icon"} + src={`/assets/${"presTrails.png"}`} />; const button = <button className={`menuButton-${shape}`} ref={this._ref} onContextMenu={this.specificContextMenu} style={{ boxShadow: this.layoutDoc.ischecked ? `4px 4px 12px black` : undefined, backgroundColor: this.layoutDoc.iconShape === "square" ? backgroundColor : "", }}> <div className="menuButton-wrap"> - {<FontAwesomeIcon className={`menuButton-icon-${shape}`} icon={StrCast(this.dataDoc.icon, "user") as any} color={color} + {icon === 'pres-trail' ? presTrailsIcon : <FontAwesomeIcon className={`menuButton-icon-${shape}`} icon={icon} color={color} size={this.layoutDoc.iconShape === "square" ? "sm" : "lg"} />} {!label ? (null) : <div className="fontIconBox-label" style={{ color, backgroundColor }}> {label} </div>} {this.props.Document.watchedDocuments ? <FontIconBadge collection={Cast(this.props.Document.watchedDocuments, Doc, null)} /> : (null)} 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<FieldViewProps, ImageD > <FontAwesomeIcon className="imageBox-audioFont" style={{ color: [DocListCast(this.dataDoc[this.fieldKey + "-audioAnnotations"]).length ? "blue" : "gray", "green", "red"][this._audioState] }} - icon={!DocListCast(this.dataDoc[this.fieldKey + "-audioAnnotations"]).length ? "microphone" : faFileAudio} size="sm" /> + icon={!DocListCast(this.dataDoc[this.fieldKey + "-audioAnnotations"]).length ? "microphone" : "file-audio"} size="sm" /> </div>} {this.considerDownloadIcon} {this.considerGooglePhotosLink()} diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index c4d8f1a4f..08160a2f4 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -488,7 +488,7 @@ $light-background: #ececec; max-width: 200px; overflow: visible; - + .presBox-dropdownOption { cursor: pointer; font-size: 11; @@ -967,10 +967,10 @@ $light-background: #ececec; /* border: solid 1px; */ color: white; /* box-shadow: black 0.4vw 0.4vw 0.8vw; */ - + .miniPresOverlay { display: grid; - grid-template-columns: auto auto auto auto auto auto auto auto; + grid-template-columns: auto auto auto auto auto auto auto auto auto auto; grid-template-rows: 100%; height: 100%; justify-items: center; @@ -1028,4 +1028,4 @@ $light-background: #ececec; background-color: #5a5a5a; } } -} +}
\ No newline at end of file diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index ba59c2df7..9070bf2ae 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -58,9 +58,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @observable private expandBoolean: boolean = false; @observable private openMovementDropdown: boolean = false; @observable private openEffectDropdown: boolean = false; - @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); } @computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); } + @computed get activeItem() { return Cast(this.childDocs[this.itemIndex], Doc, null); } + @computed get targetDoc() { return Cast(this.activeItem?.presentationTargetDoc, Doc, null); } @computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); } constructor(props: any) { super(props); @@ -86,14 +87,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } 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; } @@ -108,6 +107,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.rootDoc._replacedChrome = "replaced"; this.layoutDoc.presStatus = "edit"; this.layoutDoc._gridGap = 5; + if (!DocListCast((Doc.UserDoc().myPresentations as Doc).data).includes(this.rootDoc)) { + Doc.AddDocToList(Doc.UserDoc().myPresentations as Doc, "data", this.rootDoc); + } } updateCurrentPresentation = () => { @@ -123,37 +125,40 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> next = () => { this.updateCurrentPresentation(); const activeNext = Cast(this.childDocs[this.itemIndex + 1], Doc, null); - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const presTargetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); - const childDocs = DocListCast(presTargetDoc[Doc.LayoutFieldKey(presTargetDoc)]); - const currentFrame = Cast(presTargetDoc.currentFrame, "number", null); - const lastFrame = Cast(presTargetDoc.lastFrame, "number", null); - const curFrame = NumCast(presTargetDoc.currentFrame); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; + const childDocs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]); + const currentFrame = Cast(targetDoc.currentFrame, "number", null); + const lastFrame = Cast(targetDoc.lastFrame, "number", null); + const curFrame = NumCast(targetDoc.currentFrame); let internalFrames: boolean = false; - if (presTargetDoc.presProgressivize || activeItem.zoomProgressivize || presTargetDoc.scrollProgressivize) internalFrames = true; + if (targetDoc.presProgressivize || activeItem.zoomProgressivize || targetDoc.scrollProgressivize) internalFrames = true; // Case 1: There are still other frames and should go through all frames before going to next slide if (internalFrames && lastFrame !== undefined && curFrame < lastFrame) { - presTargetDoc._viewTransition = "all 1s"; - setTimeout(() => presTargetDoc._viewTransition = undefined, 1010); - presTargetDoc.currentFrame = curFrame + 1; - if (presTargetDoc.scrollProgressivize) CollectionFreeFormDocumentView.updateScrollframe(presTargetDoc, currentFrame); - if (presTargetDoc.presProgressivize) CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0, presTargetDoc); - else presTargetDoc.editing = true; - if (activeItem.zoomProgressivize) this.zoomProgressivizeNext(presTargetDoc); + targetDoc._viewTransition = "all 1s"; + setTimeout(() => targetDoc._viewTransition = undefined, 1010); + targetDoc.currentFrame = curFrame + 1; + if (targetDoc.scrollProgressivize) CollectionFreeFormDocumentView.updateScrollframe(targetDoc, currentFrame); + if (targetDoc.presProgressivize) CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0, targetDoc); + else targetDoc.editing = true; + if (activeItem.zoomProgressivize) this.zoomProgressivizeNext(targetDoc); // Case 2: Audio or video therefore wait to play the audio or video before moving on - } else if ((presTargetDoc.type === DocumentType.AUDIO) && !this._moveOnFromAudio && this.layoutDoc.presStatus !== 'auto') { + } else if ((targetDoc.type === DocumentType.AUDIO) && !this._moveOnFromAudio && this.layoutDoc.presStatus !== 'auto') { AudioBox.Instance.playFrom(0); this._moveOnFromAudio = true; // Case 3: No more frames in current doc and next slide is defined, therefore move to next slide } else if (this.childDocs[this.itemIndex + 1] !== undefined) { const nextSelected = this.itemIndex + 1; - if (presTargetDoc.type === DocumentType.AUDIO) AudioBox.Instance.pause(); + if (targetDoc.type === DocumentType.AUDIO) AudioBox.Instance.pause(); this.gotoDocument(nextSelected, this.itemIndex); const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null); if (activeNext && targetNext.type === DocumentType.AUDIO && activeNext.playAuto) { AudioBox.Instance.playFrom(0); this._moveOnFromAudio = true; } else this._moveOnFromAudio = false; + } else if (this.childDocs[this.itemIndex + 1] === undefined && this.layoutDoc.presLoop) { + const nextSelected = 0; + this.gotoDocument(0, this.itemIndex); } } @@ -166,15 +171,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @action back = () => { this.updateCurrentPresentation(); - const docAtCurrent = this.childDocs[this.itemIndex]; - const targetDoc = Cast(docAtCurrent.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; const prevItem = Cast(this.childDocs[Math.max(0, this.itemIndex - 1)], Doc, null); const prevTargetDoc = Cast(prevItem.presentationTargetDoc, Doc, null); const lastFrame = Cast(targetDoc.lastFrame, "number", null); const curFrame = NumCast(targetDoc.currentFrame); if (lastFrame !== undefined && curFrame >= 1) { - this.prevKeyframe(targetDoc, docAtCurrent); - } else if (docAtCurrent) { + this.prevKeyframe(targetDoc, activeItem); + } else if (activeItem) { let prevSelected = this.itemIndex; prevSelected = Math.max(0, prevSelected - 1); this.gotoDocument(prevSelected, this.itemIndex); @@ -209,8 +214,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> * on the right. */ navigateToElement = async (curDoc: Doc) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; const srcContext = await DocCastAsync(targetDoc.context); const presCollection = Cast(this.layoutDoc.presCollection, Doc, null); const collectionDocView = presCollection ? await DocumentManager.Instance.getDocumentView(presCollection) : undefined; @@ -271,7 +276,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> * @param presTargetDoc: document for which internal zoom is used */ zoomProgressivizeNext = (activeItem: Doc) => { - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const targetDoc: Doc = this.targetDoc; const srcContext = Cast(targetDoc?.context, Doc, null); const docView = DocumentManager.Instance.getDocumentView(targetDoc); const vfLeft = this.checkList(targetDoc, activeItem["viewfinder-left-indexed"]); @@ -346,8 +351,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @action startAutoPres = (startSlide: number) => { this.updateCurrentPresentation(); - let activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - let targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + let activeItem: Doc = this.activeItem; + let targetDoc: Doc = this.targetDoc; let duration = NumCast(targetDoc.presDuration) + NumCast(targetDoc.presTransition); const timer = (ms: number) => new Promise(res => this._presTimer = setTimeout(res, ms)); const load = async () => { // Wrap the loop into an async function for this to work @@ -363,17 +368,27 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } await timer(duration); this.next(); // then the created Promise can be awaited - if (i === this.childDocs.length - 1) setTimeout(() => { clearTimeout(this._presTimer); if (this.layoutDoc.presStatus === 'auto') this.layoutDoc.presStatus = "manual"; }, duration); + if (i === this.childDocs.length - 1) { + setTimeout(() => { + clearTimeout(this._presTimer); + 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"; + this.startPresentation(startSlide); + this.gotoDocument(startSlide, this.itemIndex); + load(); + } + + @action + pauseAutoPres = () => { if (this.layoutDoc.presStatus === "auto") { if (this._presTimer) clearTimeout(this._presTimer); this.layoutDoc.presStatus = "manual"; - } else { - this.layoutDoc.presStatus = "auto"; - this.startPresentation(startSlide); - this.gotoDocument(startSlide, this.itemIndex); - load(); + this.layoutDoc.presLoop = false; } } @@ -401,12 +416,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> startPresentation = (startIndex: number) => { this.updateCurrentPresentation(); this.childDocs.map(doc => { - const presTargetDoc = doc.presentationTargetDoc as Doc; + const tagDoc = doc.presentationTargetDoc as Doc; if (doc.presHideTillShownButton && this.childDocs.indexOf(doc) > startIndex) { - presTargetDoc.opacity = 0; + tagDoc.opacity = 0; } if (doc.presHideAfterButton && this.childDocs.indexOf(doc) < startIndex) { - presTargetDoc.opacity = 0; + tagDoc.opacity = 0; } }); } @@ -418,11 +433,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @undoBatch @action updateMinimize = () => { + const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc); if (this.layoutDoc.inOverlay) { this.layoutDoc.presStatus = 'edit'; Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc); CollectionDockingView.AddRightSplit(this.rootDoc); this.layoutDoc.inOverlay = false; + } else if (this.layoutDoc.context && docView) { + this.layoutDoc.presStatus = 'manual'; + const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); + this.rootDoc.x = pt[0] + (this.props.PanelWidth() - 250); + this.rootDoc.y = pt[1] + 10; + this.rootDoc._height = 35; + this.rootDoc._width = 250; + docView.props.removeDocument?.(this.layoutDoc); + Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc); } else { this.layoutDoc.presStatus = 'manual'; const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); @@ -453,31 +478,32 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> * When the movement dropdown is changes */ @undoBatch - movementChanged = action((movement: string) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + updateMovement = action((movement: any, activeItem: Doc, targetDoc: Doc) => { switch (movement) { case 'zoom': //Pan and zoom - activeItem.presZoomButton = !activeItem.presZoomButton; - if (activeItem.presZoomButton) activeItem.presMovement = 'Zoom'; - else activeItem.presMovement = 'None'; activeItem.presNavButton = false; + activeItem.presZoomButton = !activeItem.presZoomButton; + targetDoc.presTransition = activeItem.presTransition; + if (activeItem.presZoomButton) activeItem.presMovement = 'zoom'; + else activeItem.presMovement = 'none'; break; case 'pan': //Pan activeItem.presZoomButton = false; activeItem.presNavButton = !activeItem.presNavButton; - if (activeItem.presNavButton) activeItem.presMovement = 'Pan'; - else activeItem.presMovement = 'None'; + targetDoc.presTransition = activeItem.presTransition; + if (activeItem.presNavButton) activeItem.presMovement = 'pan'; + else activeItem.presMovement = 'none'; break; case 'jump': //Jump Cut + activeItem.presTransition = targetDoc.presTransition; targetDoc.presTransition = 0; activeItem.presZoomButton = true; activeItem.presSwitchButton = !activeItem.presSwitchButton; - if (activeItem.presSwitchButton) activeItem.presMovement = 'Jump cut'; - else activeItem.presMovement = 'None'; + if (activeItem.presSwitchButton) activeItem.presMovement = 'jump'; + else activeItem.presMovement = 'none'; break; case 'none': default: - activeItem.presMovement = 'None'; + activeItem.presMovement = 'none'; activeItem.presZoomButton = false; activeItem.presNavButton = false; activeItem.presSwitchButton = false; @@ -485,6 +511,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } }); + setMovementName = action((movement: any, activeItem: Doc): string => { + let output: string = 'none'; + switch (movement) { + case 'zoom': output = 'Zoom'; break; //Pan and zoom + case 'pan': output = 'Pan'; break; //Pan + case 'jump': output = 'Jump cut'; break; //Jump Cut + case 'none': output = 'None'; break; //None + default: output = 'Zoom'; activeItem.presMovement = 'zoom'; break; //default set as zoom + } + return output; + }); + whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); // For dragging documents into the presentation trail addDocumentFilter = (doc: Doc | Doc[]) => { @@ -501,7 +539,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> return true; } childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement; - removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc); + removeDocument = (doc: Doc) => { Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc); }; getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight panelHeight = () => this.props.PanelHeight() - 40; active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground) && @@ -526,10 +564,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> */ @computed get listOfSelected() { const list = this._selectedArray.map((doc: Doc, index: any) => { - const activeItem = Cast(doc, Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc!, Doc, null); + const curDoc = Cast(doc, Doc, null); + const tagDoc = Cast(curDoc.presentationTargetDoc!, Doc, null); return ( - <div className="selectedList-items">{index + 1}. {targetDoc.title}</div> + <div className="selectedList-items">{index + 1}. {tagDoc.title}</div> ); }); return list; @@ -563,8 +601,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @action shiftSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => { this._selectedArray = []; - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - if (activeItem) { + // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + if (this.activeItem) { for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) { this._selectedArray.push(this.childDocs[i]); this._eleArray.push(ref); @@ -577,6 +615,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> // 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; @@ -592,27 +631,42 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> 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); else this.layoutDoc.presStatus = "manual"; if (this._presTimer) clearTimeout(this._presTimer); handled = true; - } - if (e.keyCode === 8) { // delete selected items + } 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 = []; handled = true; } - } - if (handled) { + } if (handled) { e.stopPropagation(); e.preventDefault(); + } if ((e.keyCode === 37 || e.keyCode === 38) && e.shiftKey) { // left(37) / a(65) / up(38) to go back + if (this.layoutDoc.presStatus === "edit" && this._selectedArray.length > 0) { + const index = this.childDocs.indexOf(this._selectedArray[this._selectedArray.length]); + if ((index - 1) > 0) this._selectedArray.push(this.childDocs[index - 1]); + } + handled = true; + } if ((e.keyCode === 39 || e.keyCode === 40) && e.shiftKey) { // left(37) / a(65) / up(38) to go back + if (this.layoutDoc.presStatus === "edit" && this._selectedArray.length > 0) { + const index = this.childDocs.indexOf(this._selectedArray[this._selectedArray.length]); + if ((index - 1) > 0) { + this._selectedArray.push(this.childDocs[index - 1]); + } + } + handled = true; } } @@ -636,12 +690,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get order() { const order: JSX.Element[] = []; this.childDocs.forEach((doc, index) => { - const targetDoc = Cast(doc.presentationTargetDoc, Doc, null); - const srcContext = Cast(targetDoc?.context, Doc, null); + const tagDoc = Cast(doc.presentationTargetDoc, Doc, null); + const srcContext = Cast(tagDoc?.context, Doc, null); // Case A: Document is contained within the colleciton if (this.rootDoc.presCollection === srcContext) { order.push( - <div className="pathOrder" style={{ top: NumCast(targetDoc.y), left: NumCast(targetDoc.x) }}> + <div className="pathOrder" style={{ top: NumCast(tagDoc.y), left: NumCast(tagDoc.x) }}> <div className="pathOrder-frame">{index + 1}</div> </div>); // Case B: Document is not inside of the collection @@ -666,11 +720,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get paths() { let pathPoints = ""; this.childDocs.forEach((doc, index) => { - const targetDoc = Cast(doc.presentationTargetDoc, Doc, null); - const srcContext = Cast(targetDoc?.context, Doc, null); - if (targetDoc && this.rootDoc.presCollection === srcContext) { - const n1x = NumCast(targetDoc.x) + (NumCast(targetDoc._width) / 2); - const n1y = NumCast(targetDoc.y) + (NumCast(targetDoc._height) / 2); + const tagDoc = Cast(doc.presentationTargetDoc, Doc, null); + const srcContext = Cast(tagDoc?.context, Doc, null); + if (tagDoc && this.rootDoc.presCollection === srcContext) { + const n1x = NumCast(tagDoc.x) + (NumCast(tagDoc._width) / 2); + const n1y = NumCast(tagDoc.y) + (NumCast(tagDoc._height) / 2); if (index = 0) pathPoints = n1x + "," + n1y; else pathPoints = pathPoints + " " + n1x + "," + n1y; } else { @@ -701,8 +755,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @action onFadeDocumentAfterPresentedClick = (e: React.MouseEvent) => { e.stopPropagation(); - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; activeItem.presFadeButton = !activeItem.presFadeButton; if (!activeItem.presFadeButton) { if (targetDoc) { @@ -722,9 +776,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (change) timeInMS += change; if (timeInMS < 100) timeInMS = 100; if (timeInMS > 10000) timeInMS = 10000; - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); - if (targetDoc) targetDoc.presTransition = timeInMS; + if (this.targetDoc) this.targetDoc.presTransition = timeInMS; } // Converts seconds to ms and updates presDuration @@ -733,15 +785,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (change) timeInMS += change; if (timeInMS < 100) timeInMS = 100; if (timeInMS > 20000) timeInMS = 20000; - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); - if (targetDoc) targetDoc.presDuration = timeInMS; + if (this.targetDoc) this.targetDoc.presDuration = timeInMS; } @computed get transitionDropdown() { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; if (activeItem && targetDoc) { const transitionSpeed = targetDoc.presTransition ? NumCast(targetDoc.presTransition) / 1000 : 0.5; let duration = targetDoc.presDuration ? NumCast(targetDoc.presDuration) / 1000 : 2; @@ -753,21 +803,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-box"> Movement <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = !this.openMovementDropdown; })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5, border: this.openMovementDropdown ? 'solid 2px #5B9FDD' : 'solid 1px black' }}> - {activeItem.presMovement} + {this.setMovementName(activeItem.presMovement, activeItem)} <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openMovementDropdown ? '#5B9FDD' : 'black' }} icon={"angle-down"} /> <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={e => e.stopPropagation()} style={{ display: this.openMovementDropdown ? "grid" : "none" }}> - <div className={`presBox-dropdownOption ${activeItem.presMovement === 'None' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('none')}>None</div> - <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Zoom' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('zoom')}>Pan and Zoom</div> - <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Pan' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('pan')}>Pan</div> - <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Jump cut' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('jump')}>Jump cut</div> + <div className={`presBox-dropdownOption ${activeItem.presMovement === 'none' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement('none', activeItem, targetDoc)}>None</div> + <div className={`presBox-dropdownOption ${activeItem.presMovement === 'zoom' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement('zoom', activeItem, targetDoc)}>Pan and Zoom</div> + <div className={`presBox-dropdownOption ${activeItem.presMovement === 'pan' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement('pan', activeItem, targetDoc)}>Pan</div> + <div className={`presBox-dropdownOption ${activeItem.presMovement === 'jump' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement('jump', activeItem, targetDoc)}>Jump cut</div> </div> </div> - <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "inline-flex" : "none" }}> + <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === 'pan' || activeItem.presMovement === 'zoom' ? "inline-flex" : "none" }}> <div className="presBox-subheading">Transition Speed</div> <div className="ribbon-property"> <input className="presBox-input" type="number" value={transitionSpeed} - onFocus={() => { document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e) => this.setTransitionTime(e.target.value))} /> s </div> <div className="ribbon-propertyUpDown"> @@ -779,8 +829,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> </div> </div> - <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed} className={`toolbar-slider ${activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} /> - <div className={`slider-headers ${activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "" : "none"}`}> + <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed} className={`toolbar-slider ${activeItem.presMovement === 'pan' || activeItem.presMovement === 'zoom' ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} /> + <div className={`slider-headers ${activeItem.presMovement === 'pan' || activeItem.presMovement === 'zoom' ? "" : "none"}`}> <div className="slider-text">Fast</div> <div className="slider-text">Medium</div> <div className="slider-text">Slow</div> @@ -797,7 +847,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-property"> <input className="presBox-input" type="number" value={duration} - onFocus={() => { document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e) => this.setDurationTime(e.target.value))} /> s </div> <div className="ribbon-propertyUpDown"> @@ -858,10 +908,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } @computed get effectDirection(): string { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); let effect = ''; - switch (targetDoc.presEffectDirection) { + switch (this.targetDoc.presEffectDirection) { case 'left': effect = "Enter from left"; break; case 'right': effect = "Enter from right"; break; case 'top': effect = "Enter from top"; break; @@ -874,8 +922,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @undoBatch @action applyTo = (array: Doc[]) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; array.forEach((doc, index) => { const curDoc = Cast(doc, Doc, null); const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null); @@ -885,14 +933,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> tagDoc.presEffect = targetDoc.presEffect; tagDoc.presEffectDirection = targetDoc.presEffectDirection; curDoc.presMovement = activeItem.presMovement; + this.updateMovement(activeItem.presMovement, curDoc, tagDoc); curDoc.presHideTillShownButton = activeItem.presHideTillShownButton; curDoc.presHideAfterButton = activeItem.presHideAfterButton; } }); } @computed get optionsDropdown() { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; if (activeItem && targetDoc) { return ( <div> @@ -909,6 +958,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-button" style={{ backgroundColor: activeItem.presPinView ? "#aedef8" : "" }} onClick={() => { activeItem.presPinView = !activeItem.presPinView; + targetDoc.presPinView = activeItem.presPinView; if (activeItem.presPinView) { const x = targetDoc._panX; const y = targetDoc._panY; @@ -926,7 +976,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <input className="presBox-input" style={{ textAlign: 'left', width: 50 }} type="number" value={NumCast(activeItem.presPinViewX)} - onFocus={() => { document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewX = Number(val); })} /> </div> </div> @@ -936,7 +986,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <input className="presBox-input" style={{ textAlign: 'left', width: 50 }} type="number" value={NumCast(activeItem.presPinViewY)} - onFocus={() => { document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewY = Number(val); })} /> </div> </div> @@ -946,7 +996,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <input className="presBox-input" style={{ textAlign: 'left', width: 50 }} type="number" value={NumCast(activeItem.presPinViewScale)} - onFocus={() => { document.removeEventListener("keydown", this.keyEvents, true); }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScale = Number(val); })} /> </div> </div> @@ -996,9 +1046,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-box"> Slide Title: <br></br> <input className="ribbon-textInput" placeholder="..." type="text" name="fname" - onFocus={() => { - document.removeEventListener("keydown", this.keyEvents, true); - }} + onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)} onChange={(e) => { e.stopPropagation(); e.preventDefault(); @@ -1067,8 +1115,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } createTemplate = (layout: string, input?: string) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; let x = 0; let y = 0; if (activeItem && targetDoc) { @@ -1122,7 +1170,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> // Case in which the document has keyframes to navigate to next key frame @undoBatch @action - nextKeyframe = (tagDoc: Doc, activeItem: Doc): void => { + nextKeyframe = (tagDoc: Doc, curDoc: Doc): void => { const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]); const currentFrame = Cast(tagDoc.currentFrame, "number", null); if (currentFrame === undefined) { @@ -1134,20 +1182,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0, tagDoc); tagDoc.currentFrame = Math.max(0, (currentFrame || 0) + 1); tagDoc.lastFrame = Math.max(NumCast(tagDoc.currentFrame), NumCast(tagDoc.lastFrame)); - if (activeItem.zoomProgressivize) { + if (curDoc.zoomProgressivize) { const resize = document.getElementById('resizable'); if (resize) { - resize.style.width = this.checkList(tagDoc, activeItem["viewfinder-width-indexed"]) + 'px'; - resize.style.height = this.checkList(tagDoc, activeItem["viewfinder-height-indexed"]) + 'px'; - resize.style.top = this.checkList(tagDoc, activeItem["viewfinder-top-indexed"]) + 'px'; - resize.style.left = this.checkList(tagDoc, activeItem["viewfinder-left-indexed"]) + 'px'; + resize.style.width = this.checkList(tagDoc, curDoc["viewfinder-width-indexed"]) + 'px'; + resize.style.height = this.checkList(tagDoc, curDoc["viewfinder-height-indexed"]) + 'px'; + resize.style.top = this.checkList(tagDoc, curDoc["viewfinder-top-indexed"]) + 'px'; + resize.style.left = this.checkList(tagDoc, curDoc["viewfinder-left-indexed"]) + 'px'; } } } @undoBatch @action - prevKeyframe = (tagDoc: Doc, activeItem: Doc): void => { + prevKeyframe = (tagDoc: Doc, actItem: Doc): void => { const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]); const currentFrame = Cast(tagDoc.currentFrame, "number", null); if (currentFrame === undefined) { @@ -1156,13 +1204,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } CollectionFreeFormDocumentView.gotoKeyframe(childDocs.slice()); tagDoc.currentFrame = Math.max(0, (currentFrame || 0) - 1); - if (activeItem.zoomProgressivize) { + if (actItem.zoomProgressivize) { const resize = document.getElementById('resizable'); if (resize) { - resize.style.width = this.checkList(tagDoc, activeItem["viewfinder-width-indexed"]) + 'px'; - resize.style.height = this.checkList(tagDoc, activeItem["viewfinder-height-indexed"]) + 'px'; - resize.style.top = this.checkList(tagDoc, activeItem["viewfinder-top-indexed"]) + 'px'; - resize.style.left = this.checkList(tagDoc, activeItem["viewfinder-left-indexed"]) + 'px'; + resize.style.width = this.checkList(tagDoc, actItem["viewfinder-width-indexed"]) + 'px'; + resize.style.height = this.checkList(tagDoc, actItem["viewfinder-height-indexed"]) + 'px'; + resize.style.top = this.checkList(tagDoc, actItem["viewfinder-top-indexed"]) + 'px'; + resize.style.left = this.checkList(tagDoc, actItem["viewfinder-left-indexed"]) + 'px'; } } } @@ -1171,8 +1219,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> * Returns the collection type as a string for headers */ @computed get stringType(): string { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; let type: string = ''; if (activeItem) { switch (targetDoc.type) { @@ -1195,11 +1243,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get progressivizeDropdown() { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); - const activeFontColor = targetDoc["pres-text-color"] ? StrCast(targetDoc["pres-text-color"]) : "Black"; - const viewedFontColor = targetDoc["pres-text-viewed-color"] ? StrCast(targetDoc["pres-text-viewed-color"]) : "Black"; + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; if (activeItem && targetDoc) { + const activeFontColor = targetDoc["pres-text-color"] ? StrCast(targetDoc["pres-text-color"]) : "Black"; + const viewedFontColor = targetDoc["pres-text-viewed-color"] ? StrCast(targetDoc["pres-text-viewed-color"]) : "Black"; return ( <div> <div className={`presBox-ribbon ${this.progressivizeTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> @@ -1211,7 +1259,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> <div className="ribbon-doubleButton" style={{ display: activeItem.presProgressivize ? "inline-flex" : "none" }}> <div className="presBox-subheading">Active text color</div> - <div className="ribbon-property" style={{ backgroundColor: activeFontColor }} onClick={action(() => { console.log("hi"); this.openActiveColorPicker = !this.openActiveColorPicker; })}> + <div className="ribbon-property" style={{ backgroundColor: activeFontColor }} onClick={action(() => { this.openActiveColorPicker = !this.openActiveColorPicker; })}> </div> </div> {this.activeColorPicker} @@ -1258,8 +1306,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @undoBatch @action switchActive = (color: ColorState) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; const val = String(color.hex); targetDoc["pres-text-color"] = val; return true; @@ -1267,16 +1315,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @undoBatch @action switchPresented = (color: ColorState) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; const val = String(color.hex); targetDoc["pres-text-viewed-color"] = val; return true; } @computed get activeColorPicker() { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; return !this.openActiveColorPicker ? (null) : <SketchPicker onChange={this.switchActive} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', @@ -1285,8 +1333,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } @computed get viewedColorPicker() { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; return !this.openViewedColorPicker ? (null) : <SketchPicker onChange={this.switchPresented} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', @@ -1310,8 +1358,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> //Toggle whether the user edits or not @action editZoomProgressivize = (e: React.MouseEvent) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; if (!targetDoc.editZoomProgressivize) { if (!activeItem.zoomProgressivize) activeItem.zoomProgressivize = true; targetDoc.zoomProgressivize = true; targetDoc.editZoomProgressivize = true; @@ -1325,8 +1373,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> //Toggle whether the user edits or not @action editScrollProgressivize = (e: React.MouseEvent) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; if (!targetDoc.editScrollProgressivize) { if (!targetDoc.scrollProgressivize) { targetDoc.scrollProgressivize = true; activeItem.scrollProgressivize = true; } targetDoc.editScrollProgressivize = true; @@ -1339,9 +1387,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @action progressivizeScroll = (e: React.MouseEvent) => { e.stopPropagation(); - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + const activeItem: Doc = this.activeItem; activeItem.scrollProgressivize = !activeItem.scrollProgressivize; - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const targetDoc: Doc = this.targetDoc; targetDoc.scrollProgressivize = !targetDoc.scrollProgressivize; CollectionFreeFormDocumentView.setupScroll(targetDoc, NumCast(targetDoc.currentFrame)); if (targetDoc.editScrollProgressivize) { @@ -1355,9 +1403,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @action progressivizeZoom = (e: React.MouseEvent) => { e.stopPropagation(); - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + const activeItem: Doc = this.activeItem; activeItem.zoomProgressivize = !activeItem.zoomProgressivize; - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const targetDoc: Doc = this.targetDoc; targetDoc.zoomProgressivize = !targetDoc.zoomProgressivize; CollectionFreeFormDocumentView.setupZoom(activeItem, targetDoc); if (activeItem.editZoomProgressivize) { @@ -1370,8 +1418,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> //Progressivize Child Docs @action editProgressivize = (e: React.MouseEvent) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; targetDoc.currentFrame = targetDoc.lastFrame; if (!targetDoc.editProgressivize) { if (!activeItem.presProgressivize) { activeItem.presProgressivize = true; targetDoc.presProgressivize = true; } @@ -1384,8 +1432,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @action progressivizeChild = (e: React.MouseEvent) => { e.stopPropagation(); - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const activeItem: Doc = this.activeItem; + const targetDoc: Doc = this.targetDoc; const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]); if (!activeItem.presProgressivize) { targetDoc.editing = false; @@ -1450,8 +1498,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } @computed get progressivizeChildDocs() { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const targetDoc: Doc = this.targetDoc; const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]); const tags: JSX.Element[] = []; docs.forEach((doc, index) => { @@ -1471,8 +1518,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @undoBatch @action nextAppearFrame = (doc: Doc, i: number): void => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + // const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); const appearFrame = Cast(doc.appearFrame, "number", null); if (appearFrame === undefined) { doc.appearFrame = 0; @@ -1484,8 +1531,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @undoBatch @action prevAppearFrame = (doc: Doc, i: number): void => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + // const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); const appearFrame = Cast(doc.appearFrame, "number", null); if (appearFrame === undefined) { doc.appearFrame = 0; @@ -1606,11 +1653,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } @computed get playButtonFrames() { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + const targetDoc: Doc = this.targetDoc; return ( <> - {targetDoc ? <div className="miniPres-button-frame" style={{ display: targetDoc.lastFrame !== undefined && targetDoc.lastFrame >= 0 ? "inline-flex" : "none" }}> + {this.targetDoc ? <div className="miniPres-button-frame" style={{ display: targetDoc.lastFrame !== undefined && targetDoc.lastFrame >= 0 ? "inline-flex" : "none" }}> <div>{targetDoc.currentFrame}</div> <div className="miniPres-divider" style={{ border: 'solid 0.5px white', height: '60%' }}></div> <div>{targetDoc.lastFrame}</div> @@ -1622,8 +1668,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get playButtons() { // Case 1: There are still other frames and should go through all frames before going to next slide return (<div className="presPanelOverlay" style={{ display: this.layoutDoc.presStatus !== "edit" ? "inline-flex" : "none" }}> + <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? '#AEDDF8' : 'white' }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip> + <div className="presPanel-divider"></div> <div className="presPanel-button" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></div> - <div className="presPanel-button" onClick={() => this.startAutoPres(this.itemIndex)}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div> + <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === "auto" ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip> <div className="presPanel-button" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></div> <div className="presPanel-divider"></div> <div className="presPanel-button-text" style={{ display: this.props.PanelWidth() > 250 ? "inline-flex" : "none" }}> @@ -1638,6 +1686,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div>); } + @action + startOrPause = () => { + if (this.layoutDoc.presStatus === "manual") this.startAutoPres(this.itemIndex); + else this.pauseAutoPres(); + } + render() { // calling this method for keyEvents this.isPres; @@ -1647,8 +1701,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> return this.layoutDoc.inOverlay ? <div className="miniPres" style={{ width: 250, height: 35, background: '#323232', top: 0, zIndex: 3000000 }}> {<div className="miniPresOverlay"> + <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="miniPres-button" style={{ color: this.layoutDoc.presLoop ? '#AEDDF8' : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip> + <div className="miniPres-divider"></div> <div className="miniPres-button" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></div> - <div className="miniPres-button" onClick={() => this.startAutoPres(this.itemIndex)}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div> + <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === "auto" ? "Pause" : "Autoplay"}</div></>}><div className="miniPres-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip> <div className="miniPres-button" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></div> <div className="miniPres-divider"></div> <div className="miniPres-button-text"> 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<FieldViewProps, ScreenshotDocument>(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<Doc>; // 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<S extends Schema<any>>(schema: S, props: any, mapKeys?: KeyMap): KeyMap { +export function buildKeymap<S extends Schema<any>>(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<AntimodeMenuProps> { +export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { 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<IAnnotationProps> { 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<AntimodeMenuProps> { +export class PDFMenu extends AntimodeMenu<AntimodeMenuProps> { static Instance: PDFMenu; private _commentCont = React.createRef<HTMLButtonElement>(); 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/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index dfcf575f1..e965ac656 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -206,6 +206,15 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc } } + @action + removeItem = (e: React.MouseEvent) => { + this.props.removeDocument?.(this.rootDoc); + if (PresBox.Instance._selectedArray.includes(this.rootDoc)) { + PresBox.Instance._selectedArray.splice(PresBox.Instance._selectedArray.indexOf(this.rootDoc), 1); + } + e.stopPropagation(); + } + render() { const className = "presElementBox-item" + (PresBox.Instance._selectedArray.includes(this.rootDoc) ? " presElementBox-active" : ""); const pbi = "presElementBox-interaction"; @@ -254,10 +263,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc <Tooltip title={<><div className="dash-tooltip">{"Presentation pin view"}</div></>}><div className="presElementBox-time" style={{ fontWeight: 700, display: this.rootDoc.presPinView && PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>V</div></Tooltip> <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div className="presElementBox-closeIcon" - onClick={e => { - this.props.removeDocument?.(this.rootDoc); - e.stopPropagation(); - }}> + onClick={this.removeItem}> <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} /> </div></Tooltip> <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"presElementBox-expand" + (this.rootDoc.presExpandInlineButton ? "-selected" : "")} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}> 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<IconButtonProps>{ 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<IconButtonProps>{ //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 (<FontAwesomeIcon className="fontawesome-icon" icon={faBan} />); - case (DocumentType.AUDIO): - return (<FontAwesomeIcon className="fontawesome-icon" icon={faMusic} />); - case (DocumentType.COL): - return (<FontAwesomeIcon className="fontawesome-icon" icon={faObjectGroup} />); - case (DocumentType.IMG): - return (<FontAwesomeIcon className="fontawesome-icon" icon={faImage} />); - case (DocumentType.LINK): - return (<FontAwesomeIcon className="fontawesome-icon" icon={faLink} />); - case (DocumentType.PDF): - return (<FontAwesomeIcon className="fontawesome-icon" icon={faFilePdf} />); - case (DocumentType.RTF): - return (<FontAwesomeIcon className="fontawesome-icon" icon={faStickyNote} />); - case (DocumentType.VID): - return (<FontAwesomeIcon className="fontawesome-icon" icon={faVideo} />); - case (DocumentType.WEB): - return (<FontAwesomeIcon className="fontawesome-icon" icon={faGlobeAsia} />); - default: - return (<FontAwesomeIcon className="fontawesome-icon" icon={faCaretDown} />); - } - } - render() { return ( <div className="type-outer" id={this.props.type + "-filter"} - onMouseEnter={this.onMouseEnter} - onMouseLeave={this.onMouseLeave} + onMouseEnter={() => this._hover = true} + onMouseLeave={() => this._hover = false} onClick={this.onClick}> <div className="type-icon" id={this.props.type + "-icon"} style={this._hover ? this.hoverStyle : this._isSelected ? this.selected : this.notSelected} > - {this.getFA()} + <FontAwesomeIcon className="fontawesome-icon" icon={this.getIcon()} /> </div> {/* <div className="filter-description">{this.props.type}</div> */} </div> 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; |