From 416d9a1ef143cffed341fdb390a245b82c4b4137 Mon Sep 17 00:00:00 2001 From: Jenny Yu Date: Thu, 28 Apr 2022 17:55:49 -0400 Subject: feat: hiding recording --- src/client/views/MainView.tsx | 1220 +++++++++--------- .../views/nodes/RecordingBox/RecordingView.tsx | 41 - src/client/views/nodes/button/FontIconBox.tsx | 1300 ++++++++++---------- src/client/views/nodes/trails/PresElementBox.tsx | 55 +- 4 files changed, 1306 insertions(+), 1310 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 8e9be1eeb..7ee9f5b70 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -68,310 +68,342 @@ const _global = (window /* browser */ || global /* node */) as any; @observer export class MainView extends React.Component { - public static Instance: MainView; - public static Live: boolean = false; - private _docBtnRef = React.createRef(); - @observable public LastButton: Opt; - @observable private _windowWidth: number = 0; - @observable private _windowHeight: number = 0; - @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) - @observable private _dashUIHeight: number = 0; // height of entire main dashboard region including top menu buttons - @observable private _panelContent: string = "none"; - @observable private _sidebarContent: any = this.userDoc?.sidebar; - @observable private _leftMenuFlyoutWidth: number = 0; - - @computed private get dashboardTabHeight() { return 27; } // 27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js - @computed private get topOfDashUI() { return Number(DASHBOARD_SELECTOR_HEIGHT.replace("px", "")); } - @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight(); } - @computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; } - @computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; } - @computed private get userDoc() { return Doc.UserDoc(); } - @computed private get colorScheme() { return StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); } - @computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; } - @computed public get mainFreeform(): Opt { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } - - topMenuHeight = () => 35; - topMenuWidth = returnZero; // value is ignored ... - leftMenuWidth = () => Number(LEFT_MENU_WIDTH.replace("px", "")); - leftMenuHeight = () => this._dashUIHeight; - leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth; - leftMenuFlyoutHeight = () => this._dashUIHeight; - propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, CurrentUserUtils.propertiesWidth || 0)); - propertiesHeight = () => this._dashUIHeight; - mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth(); - mainDocViewHeight = () => this._dashUIHeight; - - componentDidMount() { - document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!)); - const ele = document.getElementById("loader"); - const prog = document.getElementById("dash-progress"); - if (ele && prog) { - // remove from DOM - setTimeout(() => { - clearTimeout(); - prog.style.transition = "1s"; - prog.style.width = "100%"; - }, 0); - setTimeout(() => ele.outerHTML = '', 1000); - } - this._sidebarContent.proto = undefined; - if (!MainView.Live) { - DocServer.setPlaygroundFields(["dataTransition", "treeViewOpen", "autoHeight", "showSidebar", "sidebarWidthPercent", "viewTransition", - "panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "text-scrollHeight", "text-height", "hideMinimap", - "viewScale", "scrollTop", "hidden", "curPage", "viewType", "chromeHidden", "nativeWidth"]); // can play with these fields on someone else's - } - DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg))); - - const tag = document.createElement('script'); - tag.src = "https://www.youtube.com/iframe_api"; - const firstScriptTag = document.getElementsByTagName('script')[0]; - firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); - window.removeEventListener("keydown", KeyManager.Instance.handle); - window.addEventListener("keydown", KeyManager.Instance.handle); - window.removeEventListener("keyup", KeyManager.Instance.unhandle); - window.addEventListener("keyup", KeyManager.Instance.unhandle); - window.addEventListener("paste", KeyManager.Instance.paste as any); - document.addEventListener("dash", (e: any) => { // event used by chrome plugin to tell Dash which document to focus on - const id = FormattedTextBox.GetDocFromUrl(e.detail); - DocServer.GetRefField(id).then(doc => (doc instanceof Doc) ? DocumentManager.Instance.jumpToDocument(doc, false, undefined) : (null)); - }); - document.addEventListener("linkAnnotationToDash", Hypothesis.linkListener); - this.initEventListeners(); - } - - componentWillUnMount() { - window.removeEventListener("keyup", KeyManager.Instance.unhandle); - window.removeEventListener("keydown", KeyManager.Instance.handle); - window.removeEventListener("pointerdown", this.globalPointerDown); - window.removeEventListener("paste", KeyManager.Instance.paste as any); - document.removeEventListener("linkAnnotationToDash", Hypothesis.linkListener); - } - - constructor(props: Readonly<{}>) { - super(props); - MainView.Instance = this; - CurrentUserUtils._urlState = HistoryUtil.parseUrl(window.location) || {} as any; - - // causes errors to be generated when modifying an observable outside of an action - configure({ enforceActions: "observed" }); - - if (window.location.pathname !== "/home") { - const pathname = window.location.pathname.substr(1).split("/"); - if (pathname.length > 1 && pathname[0] === "doc") { - CurrentUserUtils.MainDocId = pathname[1]; - !this.userDoc && DocServer.GetRefField(pathname[1]).then(action(field => field instanceof Doc && (CurrentUserUtils.GuestTarget = field))); + public static Instance: MainView; + public static Live: boolean = false; + private _docBtnRef = React.createRef(); + @observable public LastButton: Opt; + @observable private _windowWidth: number = 0; + @observable private _windowHeight: number = 0; + @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) + @observable private _dashUIHeight: number = 0; // height of entire main dashboard region including top menu buttons + @observable private _panelContent: string = "none"; + @observable private _sidebarContent: any = this.userDoc?.sidebar; + @observable private _leftMenuFlyoutWidth: number = 0; + + @computed private get dashboardTabHeight() { return 27; } // 27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js + @computed private get topOfDashUI() { return Number(DASHBOARD_SELECTOR_HEIGHT.replace("px", "")); } + @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight(); } + @computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; } + @computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; } + @computed private get userDoc() { return Doc.UserDoc(); } + @computed private get colorScheme() { return StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); } + @computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; } + @computed public get mainFreeform(): Opt { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } + + topMenuHeight = () => 35; + topMenuWidth = returnZero; // value is ignored ... + leftMenuWidth = () => Number(LEFT_MENU_WIDTH.replace("px", "")); + leftMenuHeight = () => this._dashUIHeight; + leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth; + leftMenuFlyoutHeight = () => this._dashUIHeight; + propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, CurrentUserUtils.propertiesWidth || 0)); + propertiesHeight = () => this._dashUIHeight; + mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth(); + mainDocViewHeight = () => this._dashUIHeight; + + componentDidMount() { + document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!)); + const ele = document.getElementById("loader"); + const prog = document.getElementById("dash-progress"); + if (ele && prog) { + // remove from DOM + setTimeout(() => { + clearTimeout(); + prog.style.transition = "1s"; + prog.style.width = "100%"; + }, 0); + setTimeout(() => ele.outerHTML = '', 1000); } - } - - library.add(...[fa.faEdit, fa.faTrash, fa.faTrashAlt, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faCalendar, - fa.faSquare, far.faSquare as any, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, - 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.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.faChevronLeft, fa.faChevronDown, fa.faChevronUp, - fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt, - fa.faFileAudio, fa.faFileVideo, 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.faArrowsAltV, - 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, - fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faClipboard, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript, - fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper as any, - fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, far.faCircle as any, - fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer as any, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp, - fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl, - 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.faBorderAll, - fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines, - fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faMapMarkerAlt, fa.faSearchPlus, fa.faVolumeUp, fa.faVolumeDown]); - this.initAuthenticationRouters(); - } - - globalPointerDown = action((e: PointerEvent) => { - AudioBox.Enabled = true; - const targets = document.elementsFromPoint(e.x, e.y); - if (targets.length) { - const targClass = targets[0].className.toString(); - !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu(); - !["timeline-menu-desc", "timeline-menu-item", "timeline-menu-input"].includes(targClass) && TimelineMenu.Instance.closeMenu(); - } - }); - - initEventListeners = () => { - window.addEventListener("drop", e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page - window.addEventListener("dragover", e => e.preventDefault(), false); - // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined)); - document.addEventListener("pointerdown", this.globalPointerDown); - document.addEventListener("click", (e: MouseEvent) => { - if (!e.cancelBubble) { - const pathstr = (e as any)?.path?.map((p: any) => p.classList?.toString()).join(); - if (pathstr?.includes("libraryFlyout")) { - SelectionManager.DeselectAll(); - } + this._sidebarContent.proto = undefined; + if (!MainView.Live) { + DocServer.setPlaygroundFields(["dataTransition", "treeViewOpen", "autoHeight", "showSidebar", "sidebarWidthPercent", "viewTransition", + "panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "text-scrollHeight", "text-height", "hideMinimap", + "viewScale", "scrollTop", "hidden", "curPage", "viewType", "chromeHidden", "nativeWidth"]); // can play with these fields on someone else's } - }, false); - document.oncontextmenu = () => false; - } - - initAuthenticationRouters = async () => { - // Load the user's active dashboard, or create a new one if initial session after signup - const received = CurrentUserUtils.MainDocId; - if (received && !this.userDoc) { - reaction(() => CurrentUserUtils.GuestTarget, target => target && CurrentUserUtils.createNewDashboard(Doc.UserDoc()), { fireImmediately: true }); - } else { - if (received && CurrentUserUtils._urlState.sharing) { - reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized, - initialized => initialized && received && DocServer.GetRefField(received).then(docField => { - if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) { - CollectionDockingView.AddSplit(docField, "right"); + DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg))); + + const tag = document.createElement('script'); + tag.src = "https://www.youtube.com/iframe_api"; + const firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); + window.removeEventListener("keydown", KeyManager.Instance.handle); + window.addEventListener("keydown", KeyManager.Instance.handle); + window.removeEventListener("keyup", KeyManager.Instance.unhandle); + window.addEventListener("keyup", KeyManager.Instance.unhandle); + window.addEventListener("paste", KeyManager.Instance.paste as any); + document.addEventListener("dash", (e: any) => { // event used by chrome plugin to tell Dash which document to focus on + const id = FormattedTextBox.GetDocFromUrl(e.detail); + DocServer.GetRefField(id).then(doc => (doc instanceof Doc) ? DocumentManager.Instance.jumpToDocument(doc, false, undefined) : (null)); + }); + document.addEventListener("linkAnnotationToDash", Hypothesis.linkListener); + this.initEventListeners(); + } + + componentWillUnMount() { + window.removeEventListener("keyup", KeyManager.Instance.unhandle); + window.removeEventListener("keydown", KeyManager.Instance.handle); + window.removeEventListener("pointerdown", this.globalPointerDown); + window.removeEventListener("paste", KeyManager.Instance.paste as any); + document.removeEventListener("linkAnnotationToDash", Hypothesis.linkListener); + } + + constructor(props: Readonly<{}>) { + super(props); + MainView.Instance = this; + CurrentUserUtils._urlState = HistoryUtil.parseUrl(window.location) || {} as any; + + // causes errors to be generated when modifying an observable outside of an action + configure({ enforceActions: "observed" }); + + if (window.location.pathname !== "/home") { + const pathname = window.location.pathname.substr(1).split("/"); + if (pathname.length > 1 && pathname[0] === "doc") { + CurrentUserUtils.MainDocId = pathname[1]; + !this.userDoc && DocServer.GetRefField(pathname[1]).then(action(field => field instanceof Doc && (CurrentUserUtils.GuestTarget = field))); + } + } + + library.add(...[fa.faEdit, fa.faTrash, fa.faTrashAlt, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faCalendar, fa.faVideoSlash, fa.faVideo, + fa.faSquare, far.faSquare as any, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, + 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.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.faChevronLeft, fa.faChevronDown, fa.faChevronUp, + fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt, + fa.faFileAudio, fa.faFileVideo, 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.faArrowsAltV, + 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, + fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faClipboard, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript, + fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper as any, + fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, far.faCircle as any, + fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer as any, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp, + fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl, + 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.faBorderAll, + fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines, + fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faMapMarkerAlt, fa.faSearchPlus, fa.faVolumeUp, fa.faVolumeDown]); + this.initAuthenticationRouters(); + } + + globalPointerDown = action((e: PointerEvent) => { + AudioBox.Enabled = true; + const targets = document.elementsFromPoint(e.x, e.y); + if (targets.length) { + const targClass = targets[0].className.toString(); + !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu(); + !["timeline-menu-desc", "timeline-menu-item", "timeline-menu-input"].includes(targClass) && TimelineMenu.Instance.closeMenu(); + } + }); + + initEventListeners = () => { + window.addEventListener("drop", e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page + window.addEventListener("dragover", e => e.preventDefault(), false); + // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined)); + document.addEventListener("pointerdown", this.globalPointerDown); + document.addEventListener("click", (e: MouseEvent) => { + if (!e.cancelBubble) { + const pathstr = (e as any)?.path?.map((p: any) => p.classList?.toString()).join(); + if (pathstr?.includes("libraryFlyout")) { + SelectionManager.DeselectAll(); } - }), - ); + } + }, false); + document.oncontextmenu = () => false; + } + + initAuthenticationRouters = async () => { + // Load the user's active dashboard, or create a new one if initial session after signup + const received = CurrentUserUtils.MainDocId; + if (received && !this.userDoc) { + reaction(() => CurrentUserUtils.GuestTarget, target => target && CurrentUserUtils.createNewDashboard(Doc.UserDoc()), { fireImmediately: true }); + } else { + if (received && CurrentUserUtils._urlState.sharing) { + reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized, + initialized => initialized && received && DocServer.GetRefField(received).then(docField => { + if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) { + CollectionDockingView.AddSplit(docField, "right"); + } + }), + ); + } + const activeDash = PromiseValue(this.userDoc.activeDashboard); + activeDash.then(dash => { + if (dash instanceof Doc) CurrentUserUtils.openDashboard(this.userDoc, dash); + else CurrentUserUtils.createNewDashboard(this.userDoc); + }); } - const activeDash = PromiseValue(this.userDoc.activeDashboard); - activeDash.then(dash => { - if (dash instanceof Doc) CurrentUserUtils.openDashboard(this.userDoc, dash); - else CurrentUserUtils.createNewDashboard(this.userDoc); - }); - } - } - - @action - createNewPresentation = async () => { - if (!await this.userDoc.myTrails) { - this.userDoc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "TRAILS", childDontRegisterViews: true, _height: 100, _forceActive: true, boxShadow: "0 0", _lockedPosition: true, treeViewOpen: true, system: true - })); - } - const pres = Docs.Create.PresDocument(new List(), - { title: "Untitled Trail", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0" }); - CollectionDockingView.AddSplit(pres, "right"); - this.userDoc.activePresentation = pres; - Doc.AddDocToList(this.userDoc.myTrails as Doc, "data", pres); - } - - @action - createNewFolder = async () => { - if (!await this.userDoc.myFilesystem) { - this.userDoc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); - const newFolder = ScriptField.MakeFunction(`createNewFolder()`, { scriptContext: "any" })!; - const newFolderButton: Doc = Docs.Create.FontIconDocument({ - onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", - btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true - }); - this.userDoc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([this.userDoc.myFileOrphans as Doc], { - title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, ignoreClick: true, - isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, - _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, - explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." - })); - } - const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true }); - Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder); - } - - @computed get mainDocView() { - return ; - } - - @computed get dockingContent() { - return
{ e.stopPropagation(); e.preventDefault(); }} - style={{ - minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`, - transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined, - }}> - {!this.mainContainer ? (null) : this.mainDocView} -
; - } - - @action - onPropertiesPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, - action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX)) ? false : false), - action(() => CurrentUserUtils.propertiesWidth < 5 && (CurrentUserUtils.propertiesWidth = 0)), - action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0), false); - } - - @action - onFlyoutPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, - action(e => (this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false), - () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(), - this.closeFlyout); - } - - sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1); - mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0); - addDocTabFunc = (doc: Doc, location: string): boolean => { - const locationFields = doc._viewType === CollectionViewType.Docking ? ["dashboard"] : location.split(":"); - const locationParams = locationFields.length > 1 ? locationFields[1] : ""; - if (doc.dockingConfig) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); - switch (locationFields[0]) { - case "dashboard": return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); - case "close": return CollectionDockingView.CloseSplit(doc, locationParams); - case "fullScreen": return CollectionDockingView.OpenFullScreen(doc); - case "lightbox": return LightboxView.AddDocTab(doc, location); - case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams); - case "inPlace": - case "add": - default: - return CollectionDockingView.AddSplit(doc, locationParams); - } - } - - - @computed get flyout() { - return !this._leftMenuFlyoutWidth ?
- {this.docButtons} -
: -
-
- { + if (!await this.userDoc.myTrails) { + this.userDoc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], { + title: "TRAILS", childDontRegisterViews: true, _height: 100, _forceActive: true, boxShadow: "0 0", _lockedPosition: true, treeViewOpen: true, system: true + })); + } + const pres = Docs.Create.PresDocument(new List(), + { title: "Untitled Trail", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0" }); + CollectionDockingView.AddSplit(pres, "right"); + this.userDoc.activePresentation = pres; + Doc.AddDocToList(this.userDoc.myTrails as Doc, "data", pres); + } + + @action + createNewFolder = async () => { + if (!await this.userDoc.myFilesystem) { + this.userDoc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); + const newFolder = ScriptField.MakeFunction(`createNewFolder()`, { scriptContext: "any" })!; + const newFolderButton: Doc = Docs.Create.FontIconDocument({ + onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", + btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true + }); + this.userDoc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([this.userDoc.myFileOrphans as Doc], { + title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewTruncateTitleWidth: 150, ignoreClick: true, + isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, + _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, + explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." + })); + } + const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true }); + Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder); + } + + @computed get mainDocView() { + return ; + } + + @computed get dockingContent() { + return
{ e.stopPropagation(); e.preventDefault(); }} + style={{ + minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`, + transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined, + }}> + {!this.mainContainer ? (null) : this.mainDocView} +
; + } + + @action + onPropertiesPointerDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, + action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX)) ? false : false), + action(() => CurrentUserUtils.propertiesWidth < 5 && (CurrentUserUtils.propertiesWidth = 0)), + action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0), false); + } + + @action + onFlyoutPointerDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, + action(e => (this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false), + () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(), + this.closeFlyout); + } + + sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1); + mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0); + addDocTabFunc = (doc: Doc, location: string): boolean => { + const locationFields = doc._viewType === CollectionViewType.Docking ? ["dashboard"] : location.split(":"); + const locationParams = locationFields.length > 1 ? locationFields[1] : ""; + if (doc.dockingConfig) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); + switch (locationFields[0]) { + case "dashboard": return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); + case "close": return CollectionDockingView.CloseSplit(doc, locationParams); + case "fullScreen": return CollectionDockingView.OpenFullScreen(doc); + case "lightbox": return LightboxView.AddDocTab(doc, location); + case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams); + case "inPlace": + case "add": + default: + return CollectionDockingView.AddSplit(doc, locationParams); + } + } + + + @computed get flyout() { + return !this._leftMenuFlyoutWidth ?
+ {this.docButtons} +
: +
+
+ +
+ {this.docButtons} +
; + } + + @computed get leftMenuPanel() { + return
+ -
- {this.docButtons} + scriptContext={this} + />
; - } - - @computed get leftMenuPanel() { - return
- -
; - } - - @action - selectMenu = (button: Doc) => { - const title = StrCast(Doc.GetProto(button).title); - const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title; - this.closeFlyout(); - if (willOpen) { - switch (this._panelContent = title) { - case "Settings": - SettingsManager.Instance.open(); - break; - case "Help": - break; - default: - this.expandFlyout(button); + } + + @action + selectMenu = (button: Doc) => { + const title = StrCast(Doc.GetProto(button).title); + const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title; + this.closeFlyout(); + if (willOpen) { + switch (this._panelContent = title) { + case "Settings": + SettingsManager.Instance.open(); + break; + case "Help": + break; + default: + this.expandFlyout(button); + } } - } - return true; - } - - @computed get mainInnerContent() { - const leftMenuFlyoutWidth = this._leftMenuFlyoutWidth + this.leftMenuWidth(); - const width = this.propertiesWidth() + leftMenuFlyoutWidth; - return <> - {this.leftMenuPanel} -
- {this.flyout} -
- -
-
- - {this.dockingContent} - -
- -
-
- {this.propertiesWidth() < 10 ? (null) : } -
-
-
- ; - } - - @computed get mainDashboardArea() { - return !this.userDoc ? (null) : -
{ - r && new _global.ResizeObserver(action(() => { - this._dashUIWidth = r.getBoundingClientRect().width; - this._dashUIHeight = r.getBoundingClientRect().height; - })).observe(r); - }} style={{ - color: this.colorScheme === ColorScheme.Dark ? "rgb(205,205,205)" : "black", - height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`, - width: "100%", - }} > - {this.mainInnerContent} -
; - } - - - expandFlyout = action((button: Doc) => { - // bcz: What's going on here!? - // Chrome(not firefox) seems to have a bug when the flyout expands and there's a zoomed freeform tab. All of the div below the CollectionFreeFormView's main div - // generate the wrong value from getClientRectangle() -- specifically they return an 'x' that is the flyout's width greater than it should be. - // interactively adjusting the flyout fixes the problem. So does programmatically changing the value after a timeout to something *fractionally* different (ie, 1.5, not 1);) - this._leftMenuFlyoutWidth = (this._leftMenuFlyoutWidth || 250); - setTimeout(action(() => this._leftMenuFlyoutWidth += 0.5), 0); - - this._sidebarContent.proto = button.target as any; - this.LastButton = button; - }); - - closeFlyout = action(() => { - this.LastButton = undefined; - this._panelContent = "none"; - this._sidebarContent.proto = undefined; - this._leftMenuFlyoutWidth = 0; - }); - - remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); - moveButtonDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(doc) && addDocument(doc); - addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); - - buttonBarXf = () => { - if (!this._docBtnRef.current) return Transform.Identity(); - const { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current); - return new Transform(-translateX, -translateY, 1 / scale); - } - - @computed get docButtons() { - return !(this.userDoc.dockedBtns instanceof Doc) ? (null) : -
- - {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ?
{this.userDoc?.presentationMode}
: <>} + return true; + } + + @computed get mainInnerContent() { + const leftMenuFlyoutWidth = this._leftMenuFlyoutWidth + this.leftMenuWidth(); + const width = this.propertiesWidth() + leftMenuFlyoutWidth; + return <> + {this.leftMenuPanel} +
+ {this.flyout} +
+ +
+
+ + {this.dockingContent} + +
+ +
+
+ {this.propertiesWidth() < 10 ? (null) : } +
+
+
+ ; + } + + @computed get mainDashboardArea() { + return !this.userDoc ? (null) : +
{ + r && new _global.ResizeObserver(action(() => { + this._dashUIWidth = r.getBoundingClientRect().width; + this._dashUIHeight = r.getBoundingClientRect().height; + })).observe(r); + }} style={{ + color: this.colorScheme === ColorScheme.Dark ? "rgb(205,205,205)" : "black", + height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`, + width: "100%", + }} > + {this.mainInnerContent} +
; + } + + + expandFlyout = action((button: Doc) => { + // bcz: What's going on here!? + // Chrome(not firefox) seems to have a bug when the flyout expands and there's a zoomed freeform tab. All of the div below the CollectionFreeFormView's main div + // generate the wrong value from getClientRectangle() -- specifically they return an 'x' that is the flyout's width greater than it should be. + // interactively adjusting the flyout fixes the problem. So does programmatically changing the value after a timeout to something *fractionally* different (ie, 1.5, not 1);) + this._leftMenuFlyoutWidth = (this._leftMenuFlyoutWidth || 250); + setTimeout(action(() => this._leftMenuFlyoutWidth += 0.5), 0); + + this._sidebarContent.proto = button.target as any; + this.LastButton = button; + }); + + closeFlyout = action(() => { + this.LastButton = undefined; + this._panelContent = "none"; + this._sidebarContent.proto = undefined; + this._leftMenuFlyoutWidth = 0; + }); + + remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); + moveButtonDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(doc) && addDocument(doc); + addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); + + buttonBarXf = () => { + if (!this._docBtnRef.current) return Transform.Identity(); + const { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current); + return new Transform(-translateX, -translateY, 1 / scale); + } + + @computed get docButtons() { + return !(this.userDoc.dockedBtns instanceof Doc) ? (null) : +
+ + {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ?
{this.userDoc?.presentationMode}
: <>} +
; + } + @computed get snapLines() { + return !this.userDoc.showSnapLines ? (null) :
+ + {SnappingManager.horizSnapLines().map(l => )} + {SnappingManager.vertSnapLines().map(l => )} +
; - } - @computed get snapLines() { - return !this.userDoc.showSnapLines ? (null) :
- - {SnappingManager.horizSnapLines().map(l => )} - {SnappingManager.vertSnapLines().map(l => )} - -
; - } - - @computed get inkResources() { - return - - - + - - - - - - - - - - - ; - } - - @computed get topbar() { - TraceMobx(); - return
- -
; - } - - @computed get invisibleWebBox() { // see note under the makeLink method in HypothesisUtils.ts - return !DocumentLinksButton.invisibleWebDoc ? null : -
- 500} - PanelHeight={() => 800} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - /> + + + + + + + + + + + ; + } + + @computed get topbar() { + TraceMobx(); + return
+
; - } - - render() { - return (
((ele) => ele.scrollTop = ele.scrollLeft = 0)(document.getElementById("root")!)} - ref={r => { - r && new _global.ResizeObserver(action(() => { this._windowWidth = r.getBoundingClientRect().width; this._windowHeight = r.getBoundingClientRect().height; })).observe(r); - }}> - {this.inkResources} - - - - - - - - - {this.topbar} - {LinkDescriptionPopup.descriptionPopup ? : null} - {DocumentLinksButton.LinkEditorDocView ? DocumentLinksButton.LinkEditorDocView = undefined)} docView={DocumentLinksButton.LinkEditorDocView} /> : (null)} - {LinkDocPreview.LinkInfo ? : (null)} -
- -
- - {this.mainDashboardArea} - - - - - - - - - - - {this.snapLines} -
- -
); - } - - makeWebRef = (ele: HTMLDivElement) => { - reaction(() => DocumentLinksButton.invisibleWebDoc, - invisibleDoc => { - ReactDOM.unmountComponentAtNode(ele); - invisibleDoc && ReactDOM.render( -
+ } + + @computed get invisibleWebBox() { // see note under the makeLink method in HypothesisUtils.ts + return !DocumentLinksButton.invisibleWebDoc ? null : +
500} - PanelHeight={() => 800} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} + fieldKey={"data"} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + Document={DocumentLinksButton.invisibleWebDoc} + dropAction={"move"} + layerProvider={undefined} + styleProvider={undefined} + isSelected={returnFalse} + select={returnFalse} + setHeight={returnFalse} + rootSelected={returnFalse} + renderDepth={0} + addDocTab={returnFalse} + pinToPres={returnFalse} + ScreenToLocalTransform={Transform.Identity} + bringToFront={returnFalse} + isContentActive={emptyFunction} + whenChildContentsActiveChanged={returnFalse} + focus={returnFalse} + docViewPath={returnEmptyDoclist} + PanelWidth={() => 500} + PanelHeight={() => 800} + docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} /> -
; - , ele); - - let success = false; - const onSuccess = () => { - success = true; - clearTimeout(interval); - document.removeEventListener("editSuccess", onSuccess); - }; - - // 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), 500); - setTimeout(() => !success && clearInterval(interval), 10000); // give up if no success after 10s - document.addEventListener("editSuccess", onSuccess); - }); - } +
; + } + + render() { + return (
((ele) => ele.scrollTop = ele.scrollLeft = 0)(document.getElementById("root")!)} + ref={r => { + r && new _global.ResizeObserver(action(() => { this._windowWidth = r.getBoundingClientRect().width; this._windowHeight = r.getBoundingClientRect().height; })).observe(r); + }}> + {this.inkResources} + + + + + + + + + {this.topbar} + {LinkDescriptionPopup.descriptionPopup ? : null} + {DocumentLinksButton.LinkEditorDocView ? DocumentLinksButton.LinkEditorDocView = undefined)} docView={DocumentLinksButton.LinkEditorDocView} /> : (null)} + {LinkDocPreview.LinkInfo ? : (null)} +
+ +
+ + {this.mainDashboardArea} + + + + + + + + + + + {this.snapLines} +
+ +
); + } + + makeWebRef = (ele: HTMLDivElement) => { + reaction(() => DocumentLinksButton.invisibleWebDoc, + invisibleDoc => { + ReactDOM.unmountComponentAtNode(ele); + invisibleDoc && ReactDOM.render( +
+ 500} + PanelHeight={() => 800} + docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + /> +
; +
, ele); + + let success = false; + const onSuccess = () => { + success = true; + clearTimeout(interval); + document.removeEventListener("editSuccess", onSuccess); + }; + + // 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), 500); + setTimeout(() => !success && clearInterval(interval), 10000); // give up if no success after 10s + document.addEventListener("editSuccess", onSuccess); + }); + } } ScriptingGlobals.add(function selectMainMenu(doc: Doc, title: string) { MainView.Instance.selectMenu(doc); }); \ No newline at end of file diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx index 6aed07c60..a2a08f5b8 100644 --- a/src/client/views/nodes/RecordingBox/RecordingView.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx @@ -67,23 +67,13 @@ export function RecordingView(props: IRecordingViewProps) { if (finished) { props.setDuration(recordingTimer * 100) let allVideoChunks: any = [] - console.log(videos) videos.forEach((vid) => { console.log(vid.videoChunks) allVideoChunks = allVideoChunks.concat(vid.videoChunks) }) - console.log(allVideoChunks) const videoFile = new File(allVideoChunks, "video.mkv", { type: allVideoChunks[0].type, lastModified: Date.now() }); - // const uploadVideo = async () => { - // const [{ result }] = await Networking.UploadFilesToServer(videoFile); - // console.log("upload result", result); - // if (!(result instanceof Error)) { - // setResult(result) - // } - // } - Networking.UploadFilesToServer(videoFile) .then((data) => { const result = data[0].result @@ -93,13 +83,9 @@ export function RecordingView(props: IRecordingViewProps) { alert("video conversion failed"); } }) - // uploadVideo() // this.dataDoc[this.fieldKey + "-duration"] = (new Date().getTime() - this.recordingStart!) / 1000; - - - // change to one recording box } @@ -190,7 +176,6 @@ export function RecordingView(props: IRecordingViewProps) { // recording paused videoRecorder.current.onpause = (event: any) => { // append the current portion to the video pieces - console.log(videoChunks) setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }]) // reset the temporary chunks @@ -199,7 +184,6 @@ export function RecordingView(props: IRecordingViewProps) { } videoRecorder.current.onresume = async (event: any) => { - console.log(event) await startShowingStream(); setRecording(true); } @@ -226,7 +210,6 @@ export function RecordingView(props: IRecordingViewProps) { } const startOrResume = () => { - console.log('[RecordingView.tsx] startOrResume') if (!videoRecorder.current || videoRecorder.current.state === "inactive") { record(); } else if (videoRecorder.current.state === "paused") { @@ -234,22 +217,6 @@ export function RecordingView(props: IRecordingViewProps) { } } - // const playSegment = (idx: number) => { - // console.log(idx) - // let currentChunks = videos[idx].chunks - // console.log(currentChunks) - - // const blob = new Blob(currentChunks, { - // type: 'video/webm' - // }) - // const blobUrl = URL.createObjectURL(blob) - // console.log(blobUrl) - - // videoElementRef.current!.srcObject = null - // videoElementRef.current!.src = blobUrl - // videoElementRef.current!.muted = false - // } - const clearPrevious = () => { const numVideos = videos.length setRecordingTimer(numVideos == 1 ? 0 : videos[numVideos - 2].endTime) @@ -284,14 +251,6 @@ export function RecordingView(props: IRecordingViewProps) { return toTwoDigit(minutes) + " : " + toTwoDigit(seconds); } - - - - useEffect(() => { - console.log(videos.map((elt) => elt.endTime / MAXTIME * 100)) - console.log(videos) - }, [videos]) - return (
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index ca13590de..71b165618 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -30,540 +30,540 @@ import { WebBox } from '../WebBox'; import { FontIconBadge } from './FontIconBadge'; import './FontIconBox.scss'; const FontIconSchema = createSchema({ - icon: "string", + icon: "string", }); export enum ButtonType { - TextButton = "textBtn", - MenuButton = "menuBtn", - DropdownList = "drpdownList", - DropdownButton = "drpdownBtn", - ClickButton = "clickBtn", - DoubleButton = "dblBtn", - ToggleButton = "tglBtn", - ColorButton = "colorBtn", - ToolButton = "toolBtn", - NumberButton = "numBtn", - EditableText = "editableText" + TextButton = "textBtn", + MenuButton = "menuBtn", + DropdownList = "drpdownList", + DropdownButton = "drpdownBtn", + ClickButton = "clickBtn", + DoubleButton = "dblBtn", + ToggleButton = "tglBtn", + ColorButton = "colorBtn", + ToolButton = "toolBtn", + NumberButton = "numBtn", + EditableText = "editableText" } export enum NumButtonType { - Slider = "slider", - DropdownOptions = "list", - Inline = "inline" + Slider = "slider", + DropdownOptions = "list", + Inline = "inline" } export interface ButtonProps extends FieldViewProps { - type?: ButtonType; + type?: ButtonType; } @observer export class FontIconBox extends DocComponent() { - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); } - showTemplate = (): void => { - const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null); - dragFactory && this.props.addDocTab(dragFactory, "add:right"); - } - dragAsTemplate = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); }; - useAsPrototype = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)'); }; - - specificContextMenu = (): void => { - if (!Doc.UserDoc().noviceMode) { - const cm = ContextMenu.Instance; - cm.addItem({ description: "Show Template", event: this.showTemplate, icon: "tag" }); - cm.addItem({ description: "Use as Render Template", event: this.dragAsTemplate, icon: "tag" }); - cm.addItem({ description: "Use as Prototype", event: this.useAsPrototype, icon: "tag" }); - } - } - - // Determining UI Specs - @observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title)); - @observable private icon = StrCast(this.dataDoc.icon, "user") as any; - @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen); - @observable private buttonList: string[] = StrListCast(this.rootDoc.btnList); - @observable private type = StrCast(this.rootDoc.btnType); - - /** - * Types of buttons in dash: - * - Main menu button (LHS) - * - Tool button - * - Expandable button (CollectionLinearView) - * - Button inside of CollectionLinearView vs. outside of CollectionLinearView - * - Action button - * - Dropdown button - * - Color button - * - Dropdown list - * - Number button - **/ - - _batch: UndoManager.Batch | undefined = undefined; - /** - * Number button - */ - @computed get numberButton() { - const numBtnType: string = StrCast(this.rootDoc.numBtnType); - const numScript = ScriptCast(this.rootDoc.script); - const setValue = (value: number) => numScript?.script.run({ value, _readOnly_: false }); - - // Script for checking the outcome of the toggle - const checkResult: number = numScript?.script.run({ value: 0, _readOnly_: true }).result || 0; - - if (numBtnType === NumButtonType.Slider) { - const dropdown = -
e.stopPropagation()} - > - this._batch = UndoManager.StartBatch("presDuration")} - onPointerUp={() => this._batch?.end()} - onChange={e => { e.stopPropagation(); setValue(Number(e.target.value)); }} - /> -
; - return ( -
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)} - > - {checkResult} - {this.rootDoc.dropDownOpen ? dropdown : null} -
- ); - } else if (numBtnType === NumButtonType.DropdownOptions) { - const items: number[] = []; - for (let i = 0; i < 100; i++) { - if (i % 2 === 0) { - items.push(i); - } + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); } + showTemplate = (): void => { + const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null); + dragFactory && this.props.addDocTab(dragFactory, "add:right"); + } + dragAsTemplate = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); }; + useAsPrototype = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)'); }; + + specificContextMenu = (): void => { + if (!Doc.UserDoc().noviceMode) { + const cm = ContextMenu.Instance; + cm.addItem({ description: "Show Template", event: this.showTemplate, icon: "tag" }); + cm.addItem({ description: "Use as Render Template", event: this.dragAsTemplate, icon: "tag" }); + cm.addItem({ description: "Use as Prototype", event: this.useAsPrototype, icon: "tag" }); } - const list = items.map((value) => { - return
setValue(value)}> - {value} -
; - }); - return ( -
-
setValue(Number(checkResult) - 1))}> - -
-
{ - e.stopPropagation(); - e.preventDefault(); - }} - onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)} - > - setValue(Number(e.target.value)))} - /> -
-
setValue(Number(checkResult) + 1))}> - -
- - {this.rootDoc.dropDownOpen ? + } + + // Determining UI Specs + @observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title)); + @observable private icon = StrCast(this.dataDoc.icon, "user") as any; + @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen); + @observable private buttonList: string[] = StrListCast(this.rootDoc.btnList); + @observable private type = StrCast(this.rootDoc.btnType); + + /** + * Types of buttons in dash: + * - Main menu button (LHS) + * - Tool button + * - Expandable button (CollectionLinearView) + * - Button inside of CollectionLinearView vs. outside of CollectionLinearView + * - Action button + * - Dropdown button + * - Color button + * - Dropdown list + * - Number button + **/ + + _batch: UndoManager.Batch | undefined = undefined; + /** + * Number button + */ + @computed get numberButton() { + const numBtnType: string = StrCast(this.rootDoc.numBtnType); + const numScript = ScriptCast(this.rootDoc.script); + const setValue = (value: number) => numScript?.script.run({ value, _readOnly_: false }); + + // Script for checking the outcome of the toggle + const checkResult: number = numScript?.script.run({ value: 0, _readOnly_: true }).result || 0; + + if (numBtnType === NumButtonType.Slider) { + const dropdown = +
e.stopPropagation()} + > + this._batch = UndoManager.StartBatch("presDuration")} + onPointerUp={() => this._batch?.end()} + onChange={e => { e.stopPropagation(); setValue(Number(e.target.value)); }} + /> +
; + return ( +
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)} + > + {checkResult} + {this.rootDoc.dropDownOpen ? dropdown : null} +
+ ); + } else if (numBtnType === NumButtonType.DropdownOptions) { + const items: number[] = []; + for (let i = 0; i < 100; i++) { + if (i % 2 === 0) { + items.push(i); + } + } + const list = items.map((value) => { + return
setValue(value)}> + {value} +
; + }); + return ( +
+
setValue(Number(checkResult) - 1))}> + +
+
{ + e.stopPropagation(); + e.preventDefault(); + }} + onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)} + > + setValue(Number(e.target.value)))} + /> +
+
setValue(Number(checkResult) + 1))}> + +
+ + {this.rootDoc.dropDownOpen ? +
+
+ {list} +
+
{ e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> +
: null} + +
+ ); + } else { + return (
-
- {list} -
-
{ e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> -
: null} - -
- ); - } else { - return ( -
-
- ); - } - - - } - - /** - * Dropdown button - */ - @computed get dropdownButton() { - const active: string = StrCast(this.rootDoc.dropDownOpen); - const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); - return ( -
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}> - - {!this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
} -
- -
- {this.rootDoc.dropDownOpen ? -
- {/* DROPDOWN BOX CONTENTS */} -
: null} -
- ); - } - - /** - * Dropdown list - */ - @computed get dropdownListButton() { - const active: string = StrCast(this.rootDoc.dropDownOpen); - const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); - - const script = ScriptCast(this.rootDoc.script); - - let noviceList: string[] = []; - let text: string | undefined; - let dropdown = true; - let icon: IconProp = "caret-down"; - try { - if (script.script.originalScript.startsWith('setView')) { - const selected = SelectionManager.Docs().lastElement(); - if (selected) { - if (StrCast(selected.type) === DocumentType.COL) { - text = StrCast(selected._viewType); - } else { - dropdown = false; - text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type); - icon = Doc.toIcon(selected); - } - } else { - dropdown = false; - icon = "globe-asia"; - text = "User Default"; - } - noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking]; - } else if (script.script.originalScript.startsWith('setFont')) { - const editorView = RichTextMenu.Instance?.TextView?.EditorView; - text = StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); - noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia", - "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; - } - } catch (e) { - console.log(e); - } - - // Get items to place into the list - const list = this.buttonList.map((value) => { - if (Doc.UserDoc().noviceMode && !noviceList.includes(value)) { - return; +
+ ); } - return
script.script.run({ value }).result}> - {value[0].toUpperCase() + value.slice(1)} -
; - }); - const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : -
- {this.label} -
; - return ( -
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}> - {dropdown ? (null) : } -
- {text && text[0].toUpperCase() + text.slice(1)} -
- {label} - {!dropdown ? (null) :
- -
} - {this.rootDoc.dropDownOpen ? -
-
- {list} -
-
{ e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> -
- : null} -
- ); - } - - @observable colorPickerClosed: boolean = true; - @computed get colorScript() { return ScriptCast(this.rootDoc.script); } - - colorPicker = (curColor: string) => { - const change = (value: ColorState) => { - const s = this.colorScript; - s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)(); - }; - const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', - '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', - '#FFFFFF', '#f1efeb', "transparent"]; - return ; - } - /** - * Color button - */ - @computed get colorButton() { - const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); - const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? "transparent"; - - const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : -
- {this.label} -
; + } - const dropdownCaret =
- -
; - setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView - return ( -
this.colorPickerClosed = !this.colorPickerClosed)} - onPointerDown={e => e.stopPropagation()}> - -
- {label} - {/* {dropdownCaret} */} - {this.colorPickerClosed ? (null) : -
-
e.stopPropagation()} - onClick={e => e.stopPropagation()}> - {this.colorPicker(curColor)} + /** + * Dropdown button + */ + @computed get dropdownButton() { + const active: string = StrCast(this.rootDoc.dropDownOpen); + const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + return ( +
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}> + + {!this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
} +
+
-
{ - e.stopPropagation(); this.colorPickerClosed = true; - })} /> -
} -
- ); - } - - @computed get toggleButton() { - // Determine the type of toggle button - const switchToggle: boolean = BoolCast(this.rootDoc.switchToggle); - const buttonText: string = StrCast(this.rootDoc.buttonText); - // Colors - const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); - - // Button label - const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : -
- {this.label} -
; + {this.rootDoc.dropDownOpen ? +
+ {/* DROPDOWN BOX CONTENTS */} +
: null} +
+ ); + } + + /** + * Dropdown list + */ + @computed get dropdownListButton() { + const active: string = StrCast(this.rootDoc.dropDownOpen); + const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + + const script = ScriptCast(this.rootDoc.script); + + let noviceList: string[] = []; + let text: string | undefined; + let dropdown = true; + let icon: IconProp = "caret-down"; + try { + if (script.script.originalScript.startsWith('setView')) { + const selected = SelectionManager.Docs().lastElement(); + if (selected) { + if (StrCast(selected.type) === DocumentType.COL) { + text = StrCast(selected._viewType); + } else { + dropdown = false; + text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type); + icon = Doc.toIcon(selected); + } + } else { + dropdown = false; + icon = "globe-asia"; + text = "User Default"; + } + noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking]; + } else if (script.script.originalScript.startsWith('setFont')) { + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + text = StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); + noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia", + "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; + } + } catch (e) { + console.log(e); + } + + // Get items to place into the list + const list = this.buttonList.map((value) => { + if (Doc.UserDoc().noviceMode && !noviceList.includes(value)) { + return; + } + return
script.script.run({ value }).result}> + {value[0].toUpperCase() + value.slice(1)} +
; + }); + + const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : +
+ {this.label} +
; - if (switchToggle) { return ( -
- {buttonText ? buttonText : null} - -
+
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}> + {dropdown ? (null) : } +
+ {text && text[0].toUpperCase() + text.slice(1)} +
+ {label} + {!dropdown ? (null) :
+ +
} + {this.rootDoc.dropDownOpen ? +
+
+ {list} +
+
{ e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} /> +
+ : null} +
); - } else { + } + + @observable colorPickerClosed: boolean = true; + @computed get colorScript() { return ScriptCast(this.rootDoc.script); } + + colorPicker = (curColor: string) => { + const change = (value: ColorState) => { + const s = this.colorScript; + s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)(); + }; + const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', + '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', + '#FFFFFF', '#f1efeb', "transparent"]; + return ; + } + /** + * Color button + */ + @computed get colorButton() { + const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? "transparent"; + + const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : +
+ {this.label} +
; + + const dropdownCaret =
+ +
; + setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView return ( -
- - {label} -
+
this.colorPickerClosed = !this.colorPickerClosed)} + onPointerDown={e => e.stopPropagation()}> + +
+ {label} + {/* {dropdownCaret} */} + {this.colorPickerClosed ? (null) : +
+
e.stopPropagation()} + onClick={e => e.stopPropagation()}> + {this.colorPicker(curColor)} +
+
{ + e.stopPropagation(); this.colorPickerClosed = true; + })} /> +
} +
); - } - } - - - - /** - * Default - */ - @computed get defaultButton() { - const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); - const active: string = StrCast(this.rootDoc.dropDownOpen); - return ( -
-
- - {!this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
} -
-
- ); - } - - @computed get editableText() { - // Script for running the toggle - const script = ScriptCast(this.rootDoc.script); - // Function to run the script - const checkResult = script?.script.run({ value: "", _readOnly_: true }).result; - - const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result; - return ( -
- -
- script?.script.run({ value: "", _readOnly_: true }).result} SetValue={setValue} contents={checkResult} /> -
-
- ); - } - - render() { - const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); - const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : -
- {this.label} -
; + } + + @computed get toggleButton() { + // Determine the type of toggle button + const switchToggle: boolean = BoolCast(this.rootDoc.switchToggle); + const buttonText: string = StrCast(this.rootDoc.buttonText); + // Colors + const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + + // Button label + const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : +
+ {this.label} +
; + + if (switchToggle) { + return ( +
+ {buttonText ? buttonText : null} + +
+ ); + } else { + return ( +
+ + {label} +
+ ); + } + } - const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) : -
- {this.label} -
; - const buttonText = StrCast(this.rootDoc.buttonText); - // TODO:glr Add label of button type - let button = this.defaultButton; + /** + * Default + */ + @computed get defaultButton() { + const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + const active: string = StrCast(this.rootDoc.dropDownOpen); + return ( +
+
+ + {!this.label || !Doc.UserDoc()._showLabel ? (null) :
{this.label}
} +
+
+ ); + } - switch (this.type) { - case ButtonType.TextButton: - button = ( -
- - {buttonText ? -
- {buttonText} -
- : null} - {label} -
- ); - // button = - break; - case ButtonType.EditableText: - button = this.editableText; - break; - case ButtonType.NumberButton: - button = this.numberButton; - break; - case ButtonType.DropdownButton: - button = this.dropdownButton; - break; - case ButtonType.DropdownList: - button = this.dropdownListButton; - break; - case ButtonType.ColorButton: - button = this.colorButton; - break; - case ButtonType.ToolButton: - button = ( -
- - {label} -
- ); - break; - case ButtonType.ToggleButton: - button = this.toggleButton; - // button = - break; - case ButtonType.ClickButton: - button = ( -
- - {label} -
- ); - break; - case ButtonType.MenuButton: - const trailsIcon = ; - button = ( -
- {this.icon === "pres-trail" ? trailsIcon : } - {menuLabel} - -
- ); - break; - default: - break; - } - - return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button : - {StrCast(this.layoutDoc.toolTip)}
}> - {button} - ; - } + @computed get editableText() { + // Script for running the toggle + const script = ScriptCast(this.rootDoc.script); + // Function to run the script + const checkResult = script?.script.run({ value: "", _readOnly_: true }).result; + + const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result; + return ( +
+ +
+ script?.script.run({ value: "", _readOnly_: true }).result} SetValue={setValue} contents={checkResult} /> +
+
+ ); + } + + render() { + const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : +
+ {this.label} +
; + + const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) : +
+ {this.label} +
; + + const buttonText = StrCast(this.rootDoc.buttonText); + + // TODO:glr Add label of button type + let button = this.defaultButton; + + switch (this.type) { + case ButtonType.TextButton: + button = ( +
+ + {buttonText ? +
+ {buttonText} +
+ : null} + {label} +
+ ); + // button = + break; + case ButtonType.EditableText: + button = this.editableText; + break; + case ButtonType.NumberButton: + button = this.numberButton; + break; + case ButtonType.DropdownButton: + button = this.dropdownButton; + break; + case ButtonType.DropdownList: + button = this.dropdownListButton; + break; + case ButtonType.ColorButton: + button = this.colorButton; + break; + case ButtonType.ToolButton: + button = ( +
+ + {label} +
+ ); + break; + case ButtonType.ToggleButton: + button = this.toggleButton; + // button = + break; + case ButtonType.ClickButton: + button = ( +
+ + {label} +
+ ); + break; + case ButtonType.MenuButton: + const trailsIcon = ; + button = ( +
+ {this.icon === "pres-trail" ? trailsIcon : } + {menuLabel} + +
+ ); + break; + default: + break; + } + + return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button : + {StrCast(this.layoutDoc.toolTip)}
}> + {button} + ; + } } // toggle: Set overlay status of selected document ScriptingGlobals.add(function setView(view: string) { - const selected = SelectionManager.Docs().lastElement(); - selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed"); + const selected = SelectionManager.Docs().lastElement(); + selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed"); }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Docs().lastElement(); - if (checkResult) { - return selected?._backgroundColor ?? "transparent"; - } - if (selected) selected._backgroundColor = color; + const selected = SelectionManager.Docs().lastElement(); + if (checkResult) { + return selected?._backgroundColor ?? "transparent"; + } + if (selected) selected._backgroundColor = color; }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) { - if (checkResult) { - return Doc.SharingDoc().userColor; - } - Doc.SharingDoc().userColor = undefined; - Doc.GetProto(Doc.SharingDoc()).userColor = color; - Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate"); + if (checkResult) { + return Doc.SharingDoc().userColor; + } + Doc.SharingDoc().userColor = undefined; + Doc.GetProto(Doc.SharingDoc()).userColor = color; + Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate"); }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - if (checkResult && selected) { - if (NumCast(selected.Document.z) >= 1) return Colors.MEDIUM_BLUE; - return "transparent"; - } - selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed"); + const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; + if (checkResult && selected) { + if (NumCast(selected.Document.z) >= 1) return Colors.MEDIUM_BLUE; + return "transparent"; + } + selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed"); }); /** TEXT @@ -580,115 +580,115 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFont(font: string, checkResult?: boolean) { - SelectionManager.Docs().map(doc => doc._fontFamily = font); - const editorView = RichTextMenu.Instance.TextView?.EditorView; - if (checkResult) { - return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); - } - if (editorView) RichTextMenu.Instance.setFontFamily(font); - else Doc.UserDoc().fontFamily = font; + SelectionManager.Docs().map(doc => doc._fontFamily = font); + const editorView = RichTextMenu.Instance.TextView?.EditorView; + if (checkResult) { + return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); + } + if (editorView) RichTextMenu.Instance.setFontFamily(font); + else Doc.UserDoc().fontFamily = font; }); ScriptingGlobals.add(function getActiveTextInfo(info: "family" | "size" | "color" | "highlight") { - const editorView = RichTextMenu.Instance.TextView?.EditorView; - const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection(); - switch (info) { - case "family": return style?.activeFamilies[0]; - case "size": return style?.activeSizes[0]; - case "color": return style?.activeColors[0]; - case "highlight": return style?.activeHighlights[0]; - } + const editorView = RichTextMenu.Instance.TextView?.EditorView; + const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection(); + switch (info) { + case "family": return style?.activeFamilies[0]; + case "size": return style?.activeSizes[0]; + case "color": return style?.activeColors[0]; + case "highlight": return style?.activeHighlights[0]; + } }); ScriptingGlobals.add(function setAlignment(align: "left" | "right" | "center", checkResult?: boolean) { - const editorView = RichTextMenu.Instance?.TextView?.EditorView; - if (checkResult) { - return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : "transparent"; - } - if (editorView?.state) RichTextMenu.Instance.align(editorView, editorView.dispatch, align); - else Doc.UserDoc().textAlign = align; + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + if (checkResult) { + return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : "transparent"; + } + if (editorView?.state) RichTextMenu.Instance.align(editorView, editorView.dispatch, align); + else Doc.UserDoc().textAlign = align; }); ScriptingGlobals.add(function setBulletList(mapStyle: "bullet" | "decimal", checkResult?: boolean) { - const editorView = RichTextMenu.Instance?.TextView?.EditorView; - if (checkResult) { - const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); - if (active === mapStyle) return Colors.MEDIUM_BLUE; - return "transparent"; - } - if (editorView) { - const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); - editorView?.state && RichTextMenu.Instance.changeListType( - editorView.state.schema.nodes.ordered_list.create({ mapStyle: active === mapStyle ? "" : mapStyle })); - } + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + if (checkResult) { + const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); + if (active === mapStyle) return Colors.MEDIUM_BLUE; + return "transparent"; + } + if (editorView) { + const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); + editorView?.state && RichTextMenu.Instance.changeListType( + editorView.state.schema.nodes.ordered_list.create({ mapStyle: active === mapStyle ? "" : mapStyle })); + } }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFontColor(color?: string, checkResult?: boolean) { - const editorView = RichTextMenu.Instance?.TextView?.EditorView; + const editorView = RichTextMenu.Instance?.TextView?.EditorView; - if (checkResult) { - return editorView ? RichTextMenu.Instance.fontColor : Doc.UserDoc().fontColor; - } + if (checkResult) { + return editorView ? RichTextMenu.Instance.fontColor : Doc.UserDoc().fontColor; + } - if (editorView) color && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch); - else Doc.UserDoc().fontColor = color; + if (editorView) color && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch); + else Doc.UserDoc().fontColor = color; }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFontHighlight(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Docs().lastElement(); - const editorView = RichTextMenu.Instance.TextView?.EditorView; - - if (checkResult) { - return (selected ?? Doc.UserDoc())._fontHighlight; - } - if (selected) { - selected._fontColor = color; - if (color) { - editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch); - } - } - Doc.UserDoc()._fontHighlight = color; + const selected = SelectionManager.Docs().lastElement(); + const editorView = RichTextMenu.Instance.TextView?.EditorView; + + if (checkResult) { + return (selected ?? Doc.UserDoc())._fontHighlight; + } + if (selected) { + selected._fontColor = color; + if (color) { + editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch); + } + } + Doc.UserDoc()._fontHighlight = color; }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFontSize(size: string | number, checkResult?: boolean) { - const editorView = RichTextMenu.Instance?.TextView?.EditorView; - if (checkResult) { - return (editorView ? RichTextMenu.Instance.fontSize : StrCast(Doc.UserDoc().fontSize, "10px")).replace("px", ""); - } - if (typeof size === "number") size = size.toString(); - if (size && Number(size).toString() === size) size += "px"; - if (editorView) RichTextMenu.Instance.setFontSize(size); - else Doc.UserDoc()._fontSize = size; + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + if (checkResult) { + return (editorView ? RichTextMenu.Instance.fontSize : StrCast(Doc.UserDoc().fontSize, "10px")).replace("px", ""); + } + if (typeof size === "number") size = size.toString(); + if (size && Number(size).toString() === size) size += "px"; + if (editorView) RichTextMenu.Instance.setFontSize(size); + else Doc.UserDoc()._fontSize = size; }); ScriptingGlobals.add(function toggleBold(checkResult?: boolean) { - const editorView = RichTextMenu.Instance?.TextView?.EditorView; - if (checkResult) { - return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === "bold") ? Colors.MEDIUM_BLUE : "transparent"; - } - if (editorView) RichTextMenu.Instance?.toggleBold(); - else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === "bold" ? undefined : "bold"; + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + if (checkResult) { + return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === "bold") ? Colors.MEDIUM_BLUE : "transparent"; + } + if (editorView) RichTextMenu.Instance?.toggleBold(); + else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === "bold" ? undefined : "bold"; }); ScriptingGlobals.add(function toggleUnderline(checkResult?: boolean) { - const editorView = RichTextMenu.Instance?.TextView?.EditorView; - if (checkResult) { - return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === "underline") ? Colors.MEDIUM_BLUE : "transparent"; - } - if (editorView) RichTextMenu.Instance?.toggleUnderline(); - else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === "underline" ? undefined : "underline"; + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + if (checkResult) { + return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === "underline") ? Colors.MEDIUM_BLUE : "transparent"; + } + if (editorView) RichTextMenu.Instance?.toggleUnderline(); + else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === "underline" ? undefined : "underline"; }); ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) { - const editorView = RichTextMenu.Instance?.TextView?.EditorView; - if (checkResult) { - return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === "italics") ? Colors.MEDIUM_BLUE : "transparent"; - } - if (editorView) RichTextMenu.Instance?.toggleItalics(); - else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === "italics" ? undefined : "italics"; + const editorView = RichTextMenu.Instance?.TextView?.EditorView; + if (checkResult) { + return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === "italics") ? Colors.MEDIUM_BLUE : "transparent"; + } + if (editorView) RichTextMenu.Instance?.toggleItalics(); + else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === "italics" ? undefined : "italics"; }); @@ -701,66 +701,66 @@ ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) { **/ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) { - if (checkResult) { - return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ? - Colors.MEDIUM_BLUE : "transparent"; - } - if (["circle", "square", "line"].includes(tool)) { - if (GestureOverlay.Instance.InkShape === tool) { - Doc.UserDoc().activeInkTool = InkTool.None; - GestureOverlay.Instance.InkShape = InkTool.None; - } else { - Doc.UserDoc().activeInkTool = InkTool.Pen; - GestureOverlay.Instance.InkShape = tool; - } - } else if (tool) { // pen or eraser - if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) { + if (checkResult) { + return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ? + Colors.MEDIUM_BLUE : "transparent"; + } + if (["circle", "square", "line"].includes(tool)) { + if (GestureOverlay.Instance.InkShape === tool) { + Doc.UserDoc().activeInkTool = InkTool.None; + GestureOverlay.Instance.InkShape = InkTool.None; + } else { + Doc.UserDoc().activeInkTool = InkTool.Pen; + GestureOverlay.Instance.InkShape = tool; + } + } else if (tool) { // pen or eraser + if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) { + Doc.UserDoc().activeInkTool = InkTool.None; + } else { + Doc.UserDoc().activeInkTool = tool; + GestureOverlay.Instance.InkShape = ""; + } + } else { Doc.UserDoc().activeInkTool = InkTool.None; - } else { - Doc.UserDoc().activeInkTool = tool; - GestureOverlay.Instance.InkShape = ""; - } - } else { - Doc.UserDoc().activeInkTool = InkTool.None; - } + } }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setFillColor(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Docs().lastElement(); - if (checkResult) { - if (selected?.type === DocumentType.INK) { - return StrCast(selected.fillColor); - } - return ActiveFillColor(); - } - SetActiveFillColor(StrCast(color)); - SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.fillColor = color); + const selected = SelectionManager.Docs().lastElement(); + if (checkResult) { + if (selected?.type === DocumentType.INK) { + return StrCast(selected.fillColor); + } + return ActiveFillColor(); + } + SetActiveFillColor(StrCast(color)); + SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.fillColor = color); }); ScriptingGlobals.add(function setStrokeWidth(width: number, checkResult?: boolean) { - if (checkResult) { - const selected = SelectionManager.Docs().lastElement(); - if (selected?.type === DocumentType.INK) { - return NumCast(selected.strokeWidth); - } - return ActiveInkWidth(); - } - SetActiveInkWidth(width.toString()); - SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.strokeWidth = Number(width)); + if (checkResult) { + const selected = SelectionManager.Docs().lastElement(); + if (selected?.type === DocumentType.INK) { + return NumCast(selected.strokeWidth); + } + return ActiveInkWidth(); + } + SetActiveInkWidth(width.toString()); + SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.strokeWidth = Number(width)); }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setStrokeColor(color?: string, checkResult?: boolean) { - if (checkResult) { - const selected = SelectionManager.Docs().lastElement(); - if (selected?.type === DocumentType.INK) { - return StrCast(selected.color); - } - return ActiveInkColor(); - } - SetActiveInkColor(StrCast(color)); - SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.color = String(color)); + if (checkResult) { + const selected = SelectionManager.Docs().lastElement(); + if (selected?.type === DocumentType.INK) { + return StrCast(selected.color); + } + return ActiveInkColor(); + } + SetActiveInkColor(StrCast(color)); + SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.color = String(color)); }); @@ -768,28 +768,28 @@ ScriptingGlobals.add(function setStrokeColor(color?: string, checkResult?: boole * webSetURL **/ ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) { - const selected = SelectionManager.Views().lastElement(); - if (selected?.rootDoc.type === DocumentType.WEB) { - if (checkResult) { - return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href); - } - (selected.ComponentView as WebBox).submitURL(url); - //selected.rootDoc.data = new WebField(url); - } + const selected = SelectionManager.Views().lastElement(); + if (selected?.rootDoc.type === DocumentType.WEB) { + if (checkResult) { + return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href); + } + (selected.ComponentView as WebBox).submitURL(url); + //selected.rootDoc.data = new WebField(url); + } }); ScriptingGlobals.add(function webForward(checkResult?: boolean) { - const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox); - if (checkResult) { - return selected?.forward(checkResult) ? undefined : "lightGray"; - } - selected?.forward(); + const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox); + if (checkResult) { + return selected?.forward(checkResult) ? undefined : "lightGray"; + } + selected?.forward(); }); ScriptingGlobals.add(function webBack(checkResult?: boolean) { - const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox); - if (checkResult) { - return selected?.back(checkResult) ? undefined : "lightGray"; - } - selected?.back(); + const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox); + if (checkResult) { + return selected?.back(checkResult) ? undefined : "lightGray"; + } + selected?.back(); }); @@ -797,30 +797,30 @@ ScriptingGlobals.add(function webBack(checkResult?: boolean) { * toggleSchemaPreview **/ ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) { - const selected = SelectionManager.Docs().lastElement(); - if (checkResult && selected) { - const result: boolean = NumCast(selected.schemaPreviewWidth) > 0; - if (result) return Colors.MEDIUM_BLUE; - else return "transparent"; - } - else if (selected) { - if (NumCast(selected.schemaPreviewWidth) > 0) { - selected.schemaPreviewWidth = 200; - } else { - selected.schemaPreviewWidth = 0; - } - } + const selected = SelectionManager.Docs().lastElement(); + if (checkResult && selected) { + const result: boolean = NumCast(selected.schemaPreviewWidth) > 0; + if (result) return Colors.MEDIUM_BLUE; + else return "transparent"; + } + else if (selected) { + if (NumCast(selected.schemaPreviewWidth) > 0) { + selected.schemaPreviewWidth = 200; + } else { + selected.schemaPreviewWidth = 0; + } + } }); /** STACK * groupBy */ ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) { - SelectionManager.Docs().map(doc => doc._fontFamily = key); - const editorView = RichTextMenu.Instance.TextView?.EditorView; - if (checkResult) { - return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); - } - if (editorView) RichTextMenu.Instance.setFontFamily(key); - else Doc.UserDoc().fontFamily = key; + SelectionManager.Docs().map(doc => doc._fontFamily = key); + const editorView = RichTextMenu.Instance.TextView?.EditorView; + if (checkResult) { + return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); + } + if (editorView) RichTextMenu.Instance.setFontFamily(key); + else Doc.UserDoc().fontFamily = key; }); \ No newline at end of file diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index f4f33482e..bc1cea505 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -43,6 +43,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); } @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; } + @observable isShowingVideo = false; @action setIsShowingVideo(shown: boolean) { this.isShowingVideo = shown @@ -271,10 +272,31 @@ export class PresElementBox extends ViewBoxBaseComponent() { } } + @computed get recordingIsInOverlay() { + let isInOverlay = false + DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => { + if (doc.slides === this.rootDoc) { + isInOverlay = true + return + } + }) + return isInOverlay + } + @undoBatch @action - startRecording = (targetDoc: Doc, activeItem: Doc) => { + hideRecording = (targetDoc: Doc, activeItem: Doc) => { + console.log("hide recording") + DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => { + if (doc.slides === activeItem) { + Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc); + } + }) + } + @undoBatch + @action + startRecording = (targetDoc: Doc, activeItem: Doc) => { // Remove every recording that already exists in overlay view DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => { if (doc.slides !== null) { @@ -284,21 +306,24 @@ export class PresElementBox extends ViewBoxBaseComponent() { if (activeItem.recording) { // if we already have an existing recording + console.log("recording exists") Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null)); } else { + console.log("creating new recording") // if we dont have any recording const recording = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, title: "recording", system: true, cloneFieldFilter: new List(["system"]) }); + // attach the recording to the slide, and attach the slide to the recording recording.slides = activeItem activeItem.recording = recording + // TODO: Figure out exactly where we want the video to appear const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); recording.x = pt[0]; recording.y = pt[1]; Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording); } - } @computed @@ -375,13 +400,25 @@ export class PresElementBox extends ViewBoxBaseComponent() { onClick={() => this.updateView(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V
-
{"Start recording"}
}> -
this.startRecording(targetDoc, activeItem)} - style={{ fontWeight: 700 }}> - e.stopPropagation()} /> -
-
+ + {this.recordingIsInOverlay ? +
{"Hide Recording"}
}> +
this.hideRecording(targetDoc, activeItem)} + style={{ fontWeight: 700 }}> + e.stopPropagation()} /> +
+
: +
{"Start recording"}
}> +
this.startRecording(targetDoc, activeItem)} + style={{ fontWeight: 700 }}> + e.stopPropagation()} /> +
+
+ } + + {this.indexInPres === 0 ? (null) :
{activeItem.groupWithUp ? "Ungroup" : "Group with up"}
}>
activeItem.groupWithUp = !activeItem.groupWithUp} -- cgit v1.2.3-70-g09d2 From 4381f14cfc058c534d4117a61ece34c6db72da9d Mon Sep 17 00:00:00 2001 From: Jenny Yu Date: Tue, 3 May 2022 16:43:02 -0400 Subject: feat: close recording when deleting slides --- src/client/views/nodes/trails/PresElementBox.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index bc1cea505..23c80253c 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -234,6 +234,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { if (PresBox.Instance._selectedArray.has(this.rootDoc)) { PresBox.Instance._selectedArray.delete(this.rootDoc); } + this.hideRecording(); e.stopPropagation(); }); @@ -285,10 +286,10 @@ export class PresElementBox extends ViewBoxBaseComponent() { @undoBatch @action - hideRecording = (targetDoc: Doc, activeItem: Doc) => { + hideRecording = () => { console.log("hide recording") DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => { - if (doc.slides === activeItem) { + if (doc.slides === this.rootDoc) { Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc); } }) @@ -322,6 +323,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); recording.x = pt[0]; recording.y = pt[1]; + console.log(pt) Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording); } } @@ -404,7 +406,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { {this.recordingIsInOverlay ?
{"Hide Recording"}
}>
this.hideRecording(targetDoc, activeItem)} + onClick={this.hideRecording} style={{ fontWeight: 700 }}> e.stopPropagation()} />
-- cgit v1.2.3-70-g09d2