diff options
Diffstat (limited to 'src/client/views/PropertiesButtons.tsx')
-rw-r--r-- | src/client/views/PropertiesButtons.tsx | 590 |
1 files changed, 98 insertions, 492 deletions
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index bf72dbdba..fbcd55c47 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -1,557 +1,163 @@ -import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from '@material-ui/core'; -import { action, computed, observable, runInAction } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../fields/Doc"; +import { Doc, Opt } from "../../fields/Doc"; import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; -import { Cast, NumCast, StrCast } from "../../fields/Types"; -import { ImageField } from '../../fields/URLField'; -import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; -import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; -import { GooglePhotos } from '../apis/google_docs/GooglePhotosClientUtils'; -import { Docs, DocUtils } from '../documents/Documents'; +import { BoolCast, StrCast } from "../../fields/Types"; +import { DocUtils } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { SelectionManager } from '../util/SelectionManager'; import { undoBatch } from '../util/UndoManager'; -import { CollectionDockingView } from './collections/CollectionDockingView'; -import { GoogleRef } from "./nodes/formattedText/FormattedTextBox"; +import { CollectionViewType } from './collections/CollectionView'; +import { InkingStroke } from './InkingStroke'; +import { DocumentView } from './nodes/DocumentView'; import './PropertiesButtons.scss'; import React = require("react"); -import { CollectionViewType } from './collections/CollectionView'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; - -const cloud: IconProp = "cloud-upload-alt"; -const fetch: IconProp = "sync-alt"; - enum UtilityButtonState { Default, OpenRight, OpenExternally } - @observer export class PropertiesButtons extends React.Component<{}, {}> { - private _pullAnimating = false; - private _pushAnimating = false; - private _pullColorAnimating = false; - - @observable private pushIcon: IconProp = "arrow-alt-circle-up"; - @observable private pullIcon: IconProp = "arrow-alt-circle-down"; - @observable private pullColor: string = "white"; - @observable public isAnimatingFetch = false; - @observable public isAnimatingPulse = false; - - @observable private openHover: UtilityButtonState = UtilityButtonState.Default; - @observable public static Instance: PropertiesButtons; - public static hasPushedHack = false; - public static hasPulledHack = false; - - - @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; } - @computed get selectedDocumentView() { - if (SelectionManager.Views().length) { - return SelectionManager.Views()[0]; - } else return undefined; - } - @computed get onClick() { return this.selectedDoc?.onClickBehavior ? this.selectedDoc?.onClickBehavior : "nothing"; } + @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || SelectionManager.Views().lastElement()?.rootDoc; } - public startPullOutcome = action((success: boolean) => { - if (!this._pullAnimating) { - this._pullAnimating = true; - this.pullIcon = success ? "check-circle" : "stop-circle"; - setTimeout(() => runInAction(() => { - this.pullIcon = "arrow-alt-circle-down"; - this._pullAnimating = false; - }), 1000); - } - }); - - public startPushOutcome = action((success: boolean) => { - this.isAnimatingPulse = false; - if (!this._pushAnimating) { - this._pushAnimating = true; - this.pushIcon = success ? "check-circle" : "stop-circle"; - setTimeout(() => runInAction(() => { - this.pushIcon = "arrow-alt-circle-up"; - this._pushAnimating = false; - }), 1000); - } - }); - - public setPullState = action((unchanged: boolean) => { - this.isAnimatingFetch = false; - if (!this._pullColorAnimating) { - this._pullColorAnimating = true; - this.pullColor = unchanged ? "lawngreen" : "red"; - setTimeout(this.clearPullColor, 1000); - } - }); - - private clearPullColor = action(() => { - this.pullColor = "white"; - this._pullColorAnimating = false; - }); - - @computed - get considerGoogleDocsPush() { + propertyToggleBtn = (label: string, property: string, tooltip: (on?: any) => string, icon: (on: boolean) => string, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void) => { const targetDoc = this.selectedDoc; - const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined; - const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none"; - return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div>} placement="top"> - <div> - <div - className="propertiesButtons-linker" - style={{ animation }} - onClick={async () => { - await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(); - !published && runInAction(() => this.isAnimatingPulse = true); - PropertiesButtons.hasPushedHack = false; - targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1; - }}> - <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "lg" : "sm"} /> + const onPropToggle = (dv: Opt<DocumentView>, doc: Doc, prop: string) => (dv?.layoutDoc || doc)[prop] = (dv?.layoutDoc || doc)[prop] ? undefined : true; + return !targetDoc ? (null) : + <Tooltip title={<div className={`dash-tooltip`}>{tooltip(targetDoc?.[property])} </div>} placement="top"> + <div> + <div className={`propertiesButtons-linkButton-empty toggle-${StrCast(targetDoc[property]).includes(":hover") ? "hover" : targetDoc[property] ? "on" : "off"}`} + onPointerDown={e => e.stopPropagation()} + onClick={undoBatch(() => { + if (SelectionManager.Views().length) { + SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property)); + } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property); + })} > + <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon={icon(BoolCast(targetDoc?.[property])) as any} /> + </div> + <div className="propertiesButtons-title">{label}</div> </div> - <div className="propertiesButtons-title">Google</div> - </div> - </Tooltip>; + </Tooltip>; } - - @computed - get considerGoogleDocsPull() { - const targetDoc = this.selectedDoc; - const dataDoc = targetDoc && Doc.GetProto(targetDoc); - const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none"; - - const title = (() => { - switch (this.openHover) { - default: - case UtilityButtonState.Default: return `${!dataDoc?.googleDocUnchanged ? "Pull from" : "Fetch"} Google Docs`; - case UtilityButtonState.OpenRight: return "Open in Right Split"; - case UtilityButtonState.OpenExternally: return "Open in new Browser Tab"; - } - })(); - - return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip - title={<><div className="dash-tooltip">{title}</div></>} placement="top"> - <div> - <div className="propertiesButtons-linker" - style={{ backgroundColor: this.pullColor }} - onPointerEnter={action(e => { - e.altKey && (this.openHover = UtilityButtonState.OpenExternally); - e.shiftKey && (this.openHover = UtilityButtonState.OpenRight); - })} - onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)} - onClick={async e => { - const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`; - if (e.shiftKey) { - e.preventDefault(); - let googleDoc = await Cast(dataDoc.googleDoc, Doc); - if (!googleDoc) { - const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, useCors: false }; - googleDoc = Docs.Create.WebDocument(googleDocUrl, options); - dataDoc.googleDoc = googleDoc; - } - CollectionDockingView.AddSplit(googleDoc, "right"); - } else if (e.altKey) { - e.preventDefault(); - window.open(googleDocUrl); - } else { - this.clearPullColor(); - PropertiesButtons.hasPulledHack = false; - targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1; - dataDoc.googleDocUnchanged && runInAction(() => this.isAnimatingFetch = true); - } - }}> - <FontAwesomeIcon className="documentdecorations-icon" size="lg" color="black" - style={{ WebkitAnimation: animation, MozAnimation: animation }} - icon={(() => { - switch (this.openHover) { - default: - case UtilityButtonState.Default: return dataDoc.googleDocUnchanged === false ? (this.pullIcon as any) : fetch; - case UtilityButtonState.OpenRight: return "arrow-alt-circle-right"; - case UtilityButtonState.OpenExternally: return "share"; - } - })()} - /> - </div> - <div className="propertiesButtons-title" style={{ backgroundColor: "white", color: "black" }}>Fetch</div> - </div> - </Tooltip>; + @computed get lockButton() { + return this.propertyToggleBtn("No\xA0Drag", "_lockedPosition", on => `${on ? "Unlock" : "Lock"} position to prevent dragging`, on => "thumbtack"); } - - @action @undoBatch - onLock = () => { - SelectionManager.Views().forEach(dv => dv.docView?.toggleLockPosition()); + @computed get dictationButton() { + return this.propertyToggleBtn("Dictate", "_showAudio", on => `${on ? "Hide" : "Show"} dictation/recording controls`, on => "microphone"); } - - @computed - get lockButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip - title={<div className="dash-tooltip">{`${this.selectedDoc?._lockedPosition ? "Unlock" : "Lock"} Position`}</div>} placement="top"> - <div> - <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._lockedPosition ? "on" : "off"}`} onPointerDown={this.onLock} > - <FontAwesomeIcon className="documentdecorations-icon" size="lg" - color={this.selectedDoc?._lockedPosition ? "black" : "white"} - icon={this.selectedDoc?._lockedPosition ? "unlock" : "lock"} /> - </div> - <div className="propertiesButtons-title" - >Position </div> - </div> - </Tooltip>; + @computed get maskButton() { + return this.propertyToggleBtn("Mask", "isInkMask", on => on ? "Make plain ink" : "Make highlight mask", on => "paint-brush", (dv, doc) => InkingStroke.toggleMask(dv?.layoutDoc || doc)); } - - @computed - get downloadButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip - title={<div className="dash-tooltip">{"Download Document"}</div>} placement="top"> - <div> - <div className={"propertiesButtons-linkButton-empty"} onPointerDown={() => this.selectedDoc && Doc.Zip(this.selectedDoc)}> - <FontAwesomeIcon className="propertiesButtons-icon" icon="download" size="lg" /> - </div> - <div className="propertiesButtons-title"> downld </div> - </div> - </Tooltip>; + @computed get clustersButton() { + return this.propertyToggleBtn("Clusters", "_useClusters", on => `${on ? "Hide" : "Show"} clusters`, on => "braille"); } - - @undoBatch - setDictation = () => SelectionManager.Views().forEach(dv => dv.rootDoc._showAudio = !dv.rootDoc._showAudio) - - @computed - get dictationButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Dictation Controls"}</div>} placement="top"> - <div> - <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._showAudio ? "on" : "off"}`} onPointerDown={this.setDictation}> - <FontAwesomeIcon className="propertiesButtons-icon" icon="microphone" size="lg" /> - </div> - <div className="propertiesButtons-title"> Dictate </div> - </div> - </Tooltip>; + @computed get panButton() { + return this.propertyToggleBtn("Lock\xA0View", "_lockedTransform", on => `${on ? "Unlock" : "Lock"} panning of view`, on => "lock"); } - - - @undoBatch - @action - setTitle = () => { - SelectionManager.Views().forEach(dv => dv.rootDoc._showTitle = !dv.rootDoc._showTitle ? "title" : dv.rootDoc._showTitle === "title" ? "title:hover" : undefined); + @computed get fitContentButton() { + return this.propertyToggleBtn("View All", "_fitToBox", on => `${on ? "Don't" : ""} fit content to container visible area`, on => "eye"); } - - @computed - get titleButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Title Header"}</div>} placement="top"> - <div> - <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._showTitle === "title" ? "on" : StrCast(targetDoc._showTitle).includes(":hover") ? "hover" : "off"}`} onPointerDown={this.setTitle}> - <FontAwesomeIcon className="propertiesButtons-icon" icon="text-width" size="lg" /> - </div> - <div className="propertiesButtons-title"> Title </div> - </div> - </Tooltip>; + @computed get fitWidthButton() { + return this.propertyToggleBtn("Fit\xA0Width", "_fitWidth", on => `${on ? "Don't" : ""} fit content to width of container`, on => "arrows-alt-h"); } - - @undoBatch - @action - setCaption = () => { - SelectionManager.Views().forEach(dv => { - dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined; - console.log("caption = " + dv.rootDoc._showCaption); - }); + @computed get captionButton() { + return this.propertyToggleBtn("Caption", "_showCaption", on => `${on ? "Hide" : "Show"} caption footer`, on => "closed-captioning", (dv, doc) => (dv?.rootDoc || doc)._showCaption = (dv?.rootDoc || doc)._showCaption === undefined ? "caption" : undefined); } - - @computed - get captionButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Caption Footer"}</div>} placement="top"> - <div> - <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._showCaption ? "on" : "off"}`} onPointerDown={this.setCaption}> - <FontAwesomeIcon className="propertiesButtons-icon" icon="closed-captioning" size="lg" /> - </div> - <div className="propertiesButtons-title"> Caption </div> - </div> - </Tooltip>; + @computed get chromeButton() { + return this.propertyToggleBtn("Controls", "_chromeStatus", on => `${on === "enabled" ? "Hide" : "Show"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeStatus = (dv?.rootDoc || doc)._chromeStatus === undefined ? "enabled" : undefined); } - - @undoBatch - @action - setChrome = () => { - SelectionManager.Views().forEach(dv => dv.rootDoc._chromeStatus = dv.rootDoc._chromeStatus === "disabled" ? "enabled" : "disabled"); + @computed get titleButton() { + return this.propertyToggleBtn("Title", "_showTitle", on => "Switch between title styles", on => "text-width", (dv, doc) => (dv?.rootDoc || doc)._showTitle = !(dv?.rootDoc || doc)._showTitle ? "title" : (dv?.rootDoc || doc)._showTitle === "title" ? "title:hover" : undefined); } @computed - get chromeButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Editing UI"}</div>} placement="top"> + get onClickButton() { + return !this.selectedDoc ? (null) : <Tooltip title={<div className="dash-tooltip">Choose onClick behavior</div>} placement="top"> <div> - <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._chromeStatus === "enabled" ? "on" : "off"}`} onPointerDown={this.setChrome}> - <FontAwesomeIcon className="propertiesButtons-icon" icon="edit" size="lg" /> + <div className="propertiesButtons-linkFlyout"> + <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.onClickFlyout}> + <div className={"propertiesButtons-linkButton-empty"} onPointerDown={e => e.stopPropagation()} > + <FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="lg" /> + </div> + </Flyout> </div> - <div className="propertiesButtons-title"> Controls </div> + <div className="propertiesButtons-title"> onclick </div> </div> </Tooltip>; } - @computed - get onClickButton() { - if (this.selectedDoc) { - return <Tooltip title={<><div className="dash-tooltip">Choose onClick behavior</div></>} placement="top"> - <div> - <div className="propertiesButtons-linkFlyout"> - <Flyout anchorPoint={anchorPoints.LEFT_TOP} - content={this.onClickFlyout}> - <div className={"propertiesButtons-linkButton-empty"} onPointerDown={e => e.stopPropagation()} > - {<FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="lg" />} - </div> - </Flyout> - </div> - <div className="propertiesButtons-title"> onclick </div> - </div> - </Tooltip>; - } else { - return null; - } - } - @undoBatch @action handleOptionChange = (e: any) => { - const value = e.target.value; this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value); - - SelectionManager.Views().forEach(dv => { - dv.docView?.noOnClick(); - switch (value) { - case "enterPortal": dv.docView?.makeIntoPortal(); break; - case "toggleDetail": dv.docView?.toggleDetail(); break; - case "linkInPlace": dv.docView?.toggleFollowLink("inPlace", true, false); break; - case "linkOnRight": dv.docView?.toggleFollowLink("add:right", false, false); break; + SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => { + docView.noOnClick(); + switch (e.target.value) { + case "enterPortal": docView.makeIntoPortal(); break; + case "toggleDetail": docView.toggleDetail(); break; + case "linkInPlace": docView.toggleFollowLink("inPlace", true, false); break; + case "linkOnRight": docView.toggleFollowLink("add:right", false, false); break; } }); } - @undoBatch @action + @undoBatch editOnClickScript = () => { - if (this.selectedDoc) { - if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick")); - else DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick"); - } + if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick")); + else this.selectedDoc && DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick"); } @computed get onClickFlyout() { - return <div><form> - <div className="radio"> - <label> - <input type="radio" value="nothing" - checked={this.onClick === 'nothing'} - onChange={this.handleOptionChange} /> - Select Document - </label> - </div> - <div className="radio"> - <label> - <input type="radio" value="enterPortal" - checked={this.onClick === 'enterPortal'} - onChange={this.handleOptionChange} /> - Enter Portal - </label> - </div> - <div className="radio"> - <label> - <input type="radio" value="toggleDetail" - checked={this.onClick === 'toggleDetail'} - onChange={this.handleOptionChange} /> - Toggle Detail - </label> - </div> - <div className="radio"> - <label> - <input type="radio" value="linkInPlace" - checked={this.onClick === 'linkInPlace'} - onChange={this.handleOptionChange} /> - Follow Link - </label> - </div> - <div className="radio"> - <label> - <input type="radio" value="linkOnRight" - checked={this.onClick === 'linkOnRight'} - onChange={this.handleOptionChange} /> - Open Link on Right - </label> - </div> - </form> + const makeLabel = (value: string, label: string) => <div className="radio"> + <label> + <input type="radio" value={value} checked={(this.selectedDoc?.onClickBehavior ?? "nothing") === value} onChange={this.handleOptionChange} /> + {label} + </label> + </div>; + return <div> + <form> + {makeLabel("nothing", "Select Document")} + {makeLabel("enterPortal", "Enter Portal")} + {makeLabel("toggleDetail", "Toggle Detail")} + {makeLabel("linkInPlace", "Follow Link")} + {makeLabel("linkOnRight", "Open Link on Right")} + </form> {Doc.UserDoc().noviceMode ? (null) : <div onPointerDown={this.editOnClickScript} className="onClickFlyout-editScript"> Edit onClick Script</div>} </div>; } - @computed - get googlePhotosButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip - title={<><div className="dash-tooltip">{"Export to Google Photos"}</div></>} placement="top"> - <div> - <div className={"propertiesButtons-linkButton-empty"} - onPointerDown={() => this.selectedDoc && GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDoc }).then(console.log)}> - {<FontAwesomeIcon className="documentdecorations-icon" icon="cloud-upload-alt" size="lg" />} - </div> - <div className="propertiesButtons-title"> google </div> - </div> - </Tooltip>; - } - - @computed - get clustersButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip - title={<><div className="dash-tooltip">{this.selectedDoc?._useClusters ? "Stop Showing Clusters" : "Show Clusters"}</div></>} placement="top"> - <div> - <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._useClusters ? "on" : "off"}`} onPointerDown={this.changeClusters}> - <FontAwesomeIcon className="documentdecorations-icon" icon="braille" size="lg" /> - </div> - <div className="propertiesButtons-title" > clusters </div> - </div> - </Tooltip>; - } - - @action @undoBatch - changeFitToBox = () => { - if (this.selectedDoc) { - if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitToBox = !dv.rootDoc._fitToBox); - else this.selectedDoc._fitToBox = !this.selectedDoc._fitToBox; - } - } - - @action @undoBatch - changeFitWidth = () => { - if (this.selectedDoc) { - if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitWidth = !dv.rootDoc._fitWidth); - else this.selectedDoc._fitWidth = !this.selectedDoc._fitWidth; - } - } - - @action @undoBatch - changeClusters = () => { - if (this.selectedDoc) { - if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._useClusters = !dv.rootDoc._useClusters); - else this.selectedDoc._useClusters = !this.selectedDoc._useClusters; - } - } - - @computed - get fitContentButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip - title={<><div className="dash-tooltip">{this.selectedDoc?._fitToBox ? "Stop Fitting Content" : "Fit Content"}</div></>} placement="top"> - <div> - <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._fitToBox ? "on" : "off"}`} onPointerDown={this.changeFitToBox}> - <FontAwesomeIcon className="documentdecorations-icon" icon="expand" size="lg" /> - </div> - <div className="propertiesButtons-title"> {this.selectedDoc?._fitToBox ? "unfit" : "fit"} </div> - </div> - </Tooltip>; - } - - @computed - get fitWidthButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip - title={<><div className="dash-tooltip">{this.selectedDoc?._fitWidth ? "Stop Fitting Width" : "Fit Width"}</div></>} placement="top"> - <div> - <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._fitWidth ? "on" : "off"}`} onPointerDown={this.changeFitWidth}> - <FontAwesomeIcon className="documentdecorations-icon" icon="arrows-alt-h" size="lg" /> - </div> - <div className="propertiesButtons-title"> {this.selectedDoc?._fitWidth ? "unfit" : "fit"} </div> - </div> - </Tooltip>; - } - - @undoBatch - @action - private makeMask = () => { - if (this.selectedDoc) { - this.selectedDoc._backgroundColor = "rgba(0,0,0,0.7)"; - this.selectedDoc.mixBlendMode = "hard-light"; - this.selectedDoc.color = "#9b9b9bff"; - this.selectedDoc._stayInCollection = true; - this.selectedDoc.isInkMask = true; - } - } - - @computed - get maskButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : <Tooltip - title={<><div className="dash-tooltip">Make Mask</div></>} placement="top"> - <div> - <div className={"propertiesButtons-linkButton-empty"} onPointerDown={this.makeMask}> - <FontAwesomeIcon className="documentdecorations-icon" color="white" icon="paint-brush" size="lg" /> - </div> - <div className="propertiesButtons-title"> mask </div> - </div> - </Tooltip>; - } - render() { - if (!this.selectedDoc) return (null); - - const layoutField = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)]; + const layoutField = this.selectedDoc?.[Doc.LayoutFieldKey(this.selectedDoc)]; const isText = layoutField instanceof RichTextField; - const isImage = layoutField instanceof ImageField; const isInk = layoutField instanceof InkField; - const isCollection = this.selectedDoc.type === DocumentType.COL; - const isFreeForm = this.selectedDoc._viewType === CollectionViewType.Freeform; - const considerPull = isText && this.considerGoogleDocsPull; - const considerPush = isText && this.considerGoogleDocsPush; - - return <div className="propertiesButtons" style={{ paddingBottom: "5.5px" }}> - <div className="propertiesButtons-button"> - {this.titleButton} - </div> - <div className="propertiesButtons-button"> - {this.captionButton} - </div> - <div className="propertiesButtons-button" style={{ display: isCollection ? "" : "none" }}> - {this.chromeButton} - </div> - <div className="propertiesButtons-button"> - {this.lockButton} - </div> - <div className="propertiesButtons-button"> - {this.dictationButton} - </div> - <div className="propertiesButtons-button"> - {this.onClickButton} - </div> - <div className="propertiesButtons-button" style={{ display: !considerPush ? "none" : "" }}> - {this.considerGoogleDocsPush} - </div> - <div className="propertiesButtons-button" style={{ display: !considerPull ? "none" : "" }}> - {this.considerGoogleDocsPull} - </div> - <div className="propertiesButtons-button" style={{ display: !isImage ? "none" : "" }}> - {this.googlePhotosButton} - </div> - - <div className="propertiesButtons-button" style={{ display: !isFreeForm ? "none" : "" }}> - {this.clustersButton} - </div> - <div className="propertiesButtons-button" style={{ display: !isFreeForm && !isText ? "none" : "" }}> - {this.fitContentButton} - </div> - <div className="propertiesButtons-button"> - {this.fitWidthButton} - </div> - <div className="propertiesButtons-button" style={{ display: !isInk ? "none" : "" }}> - {this.maskButton} - </div> - </div>; - } -} + const isCollection = this.selectedDoc?.type === DocumentType.COL; + const isFreeForm = this.selectedDoc?._viewType === CollectionViewType.Freeform; + const toggle = (ele: JSX.Element | null, style?: React.CSSProperties) => <div className="propertiesButtons-button" style={style}> {ele} </div>; + + return !this.selectedDoc ? (null) : + <div className="propertiesButtons"> + {toggle(this.titleButton)} + {toggle(this.captionButton)} + {toggle(this.chromeButton, { display: isCollection ? "" : "none" })} + {toggle(this.lockButton)} + {toggle(this.dictationButton)} + {toggle(this.onClickButton)} + {toggle(this.clustersButton, { display: !isFreeForm ? "none" : "" })} + {toggle(this.panButton, { display: !isFreeForm ? "none" : "" })} + {toggle(this.fitContentButton, { display: !isFreeForm && !isText ? "none" : "" })} + {toggle(this.fitWidthButton)} + {toggle(this.maskButton, { display: !isInk ? "none" : "" })} + </div>; + } +}
\ No newline at end of file |