diff options
-rw-r--r-- | src/client/views/InkingStroke.tsx | 15 | ||||
-rw-r--r-- | src/client/views/PropertiesButtons.scss | 1 | ||||
-rw-r--r-- | src/client/views/PropertiesButtons.tsx | 393 | ||||
-rw-r--r-- | src/client/views/TemplateMenu.tsx | 9 | ||||
-rw-r--r-- | src/client/views/collections/CollectionMasonryViewFieldRow.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 6 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 15 |
8 files changed, 91 insertions, 354 deletions
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 31279338f..34cdb50e3 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -33,12 +33,13 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]); } - private makeMask = () => { - this.props.Document.mixBlendMode = "hard-light"; - this.props.Document.color = "#9b9b9bff"; - //this.props.Document._stayInCollection = true; - this.props.Document.isInkMask = true; - } + public static toggleMask = action((inkDoc: Doc) => { + inkDoc.isInkMask = !inkDoc.isInkMask; + inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined; + inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined; + inkDoc.color = "#9b9b9bff"; + inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined; + }) public _prevX = 0; public _prevY = 0; @@ -205,7 +206,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume const cm = ContextMenu.Instance; if (cm) { !Doc.UserDoc().noviceMode && cm.addItem({ description: "Recognize Writing", event: this.analyzeStrokes, icon: "paint-brush" }); - cm.addItem({ description: "Make Mask", event: this.makeMask, icon: "paint-brush" }); + cm.addItem({ description: "Toggle Mask", event: () => InkingStroke.toggleMask(this.rootDoc), icon: "paint-brush" }); cm.addItem({ description: "Edit Points", event: action(() => formatInstance._controlBtn = !formatInstance._controlBtn), icon: "paint-brush" }); //cm.addItem({ description: "Format Shape...", event: this.formatShape, icon: "paint-brush" }); } diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss index ba212da7f..29d2bfcb7 100644 --- a/src/client/views/PropertiesButtons.scss +++ b/src/client/views/PropertiesButtons.scss @@ -63,6 +63,7 @@ $linkGap : 3px; display: flex; flex-direction: row; flex-wrap: wrap; + padding-bottom: 5.5px; } .onClickFlyout-editScript { diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index e93abb67a..15214b692 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -1,264 +1,92 @@ -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, Opt } from "../../fields/Doc"; import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; -import { BoolCast, 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 { CollectionViewType } from './collections/CollectionView'; +import { InkingStroke } from './InkingStroke'; import { DocumentView } from './nodes/DocumentView'; -import { GoogleRef } from "./nodes/formattedText/FormattedTextBox"; import './PropertiesButtons.scss'; import React = require("react"); 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; - - public static hasPushedHack = false; - public static hasPulledHack = false; - @observable public static Instance: PropertiesButtons; - @observable private openHover = UtilityButtonState.Default; - @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; - - @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; } - @computed get selectedDocumentView() { return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; } - @computed get onClick() { return this.selectedDoc?.onClickBehavior ? this.selectedDoc?.onClickBehavior : "nothing"; } - - 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() { - 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"} /> - </div> - <div className="propertiesButtons-title">Google</div> - </div> - </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, 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 selectedDoc() { return SelectionManager.SelectedSchemaDoc() || SelectionManager.Views().lastElement()?.rootDoc; } - @action - makeMask = (inkDoc: Doc) => { - inkDoc.isInkMask = !inkDoc.isInkMask; - inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined; - inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined; - inkDoc.color = "#9b9b9bff"; - inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined; - } - propToggleBtn = (label: string, property: string, tooltip: (on?: any) => string, icon: (on: boolean) => string, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void) => { + 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 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={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} /> + 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={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">{label}</div> - </div> - </Tooltip>; + </Tooltip>; } @computed get lockButton() { - return this.propToggleBtn("Position", "_lockedPosition", on => `${on ? "Unlock" : "Lock"} XY location on freeform view`, on => on ? "unlock" : "lock"); - } - @computed get panButton() { - return this.propToggleBtn("Pan", "_lockedTransform", on => `${on ? "Unlock" : "Lock"} panning of view`, on => on ? "unlock" : "lock"); + return this.propertyToggleBtn("No\xA0Drag", "_lockedPosition", on => `${on ? "Unlock" : "Lock"} position to prevent dragging`, on => "thumbtack"); } @computed get dictationButton() { - return this.propToggleBtn("Dictate", "_showAudio", on => `${on ? "Hide" : "Show"} dictation/recording controls`, () => "microphone"); + return this.propertyToggleBtn("Dictate", "_showAudio", on => `${on ? "Hide" : "Show"} dictation/recording controls`, on => "microphone"); } @computed get maskButton() { - return this.propToggleBtn("Mask", "isInkMask", on => on ? "Make plain ink" : "Make highlight mask", () => "paint-brush", (dv, doc) => this.makeMask(dv?.layoutDoc || doc)); + 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 clustersButton() { - return this.propToggleBtn("Clusters", "_useClusters", on => `${on ? "Hide" : "Show"} clusters`, () => "braille"); + return this.propertyToggleBtn("Clusters", "_useClusters", on => `${on ? "Hide" : "Show"} clusters`, on => "braille"); + } + @computed get panButton() { + return this.propertyToggleBtn("Lock\xA0View", "_lockedTransform", on => `${on ? "Unlock" : "Lock"} panning of view`, on => "lock"); } @computed get fitContentButton() { - return this.propToggleBtn("Fit All", "_fitToBox", on => `${on ? "Don't" : ""} fit content to container visible area`, on => on ? "expand-arrows-alt" : "compress-arrows-alt"); + return this.propertyToggleBtn("View All", "_fitToBox", on => `${on ? "Don't" : ""} fit content to container visible area`, on => "eye"); } @computed get fitWidthButton() { - return this.propToggleBtn("Fit Wid", "_fitWidth", on => `${on ? "Don't" : ""} fit content to width of container`, on => on ? "arrows-alt-h" : "arrows-alt-h"); + return this.propertyToggleBtn("Fit\xA0Width", "_fitWidth", on => `${on ? "Don't" : ""} fit content to width of container`, on => "arrows-alt-h"); } @computed get captionButton() { - return this.propToggleBtn("Caption", "_showCaption", on => `${on ? "Hide" : "Show"} caption footer`, on => "closed-captioning", (dv, doc) => (dv?.rootDoc || doc)._showCaption = (dv?.rootDoc || doc)._showCaption === undefined ? "caption" : undefined); + 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 chromeButton() { - return this.propToggleBtn("Controls", "_chromeStatus", on => `${on === "enabled" ? "Hide" : "Show"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeStatus = (dv?.rootDoc || doc)._chromeStatus === undefined ? "enabled" : undefined); + 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); } @computed get titleButton() { - return this.propToggleBtn("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 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>; + 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 onClickButton() { - return !this.selectedDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">Choose onClick behavior</div></>} placement="top"> + return !this.selectedDoc ? (null) : <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}> + <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" />} + <FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="lg" /> </div> </Flyout> </div> @@ -271,7 +99,6 @@ export class PropertiesButtons extends React.Component<{}, {}> { @action handleOptionChange = (e: any) => { this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value); - SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => { docView.noOnClick(); switch (e.target.value) { @@ -283,133 +110,53 @@ export class PropertiesButtons extends React.Component<{}, {}> { }); } - @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>; - } - 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" style={{ display: isFreeForm ? "" : "none" }}> - {this.panButton} - </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 diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 162a2ebb8..9f04e8a6e 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -45,7 +45,7 @@ class OtherToggle extends React.Component<{ checked: boolean, name: string, togg export interface TemplateMenuProps { docViews: DocumentView[]; - templates?: Map<string, boolean>; + templates: Map<string, boolean>; } @@ -81,7 +81,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { @action toggleChrome = (): void => { this.props.docViews.map(dv => Doc.Layout(dv.layoutDoc)).forEach(layout => - layout._chromeStatus = (layout._chromeStatus !== undefined ? undefined : StrCast(layout._replacedChrome, "enabled"))); + layout._chromeStatus = (layout._chromeStatus ? undefined : StrCast(layout._replacedChrome, "enabled"))); } // todo: add brushes to brushMap to save with a style name @@ -115,11 +115,11 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { const addedTypes = Doc.UserDoc().noviceMode ? [] : DocListCast(Cast(Doc.UserDoc()["template-buttons"], Doc, null)?.data); const layout = Doc.Layout(firstDoc); const templateMenu: Array<JSX.Element> = []; - this.props.templates?.forEach((checked, template) => + this.props.templates.forEach((checked, template) => templateMenu.push(<TemplateToggle key={template} template={template} checked={checked} toggle={this.toggleTemplate} />)); templateMenu.push(<OtherToggle key={"audio"} name={"Audio"} checked={firstDoc._showAudio ? true : false} toggle={this.toggleAudio} />); templateMenu.push(<OtherToggle key={"default"} name={"Default"} checked={templateName === "layout"} toggle={this.toggleDefault} />); - !Doc.UserDoc().noviceMode && templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== undefined} toggle={this.toggleChrome} />); + !Doc.UserDoc().noviceMode && templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== "disabled"} toggle={this.toggleChrome} />); addedTypes.concat(noteTypes).map(template => template.treeViewChecked = this.templateIsUsed(firstDoc, template)); this._addedKeys && Array.from(this._addedKeys).filter(key => !noteTypes.some(nt => nt.title === key)).forEach(template => templateMenu.push( <OtherToggle key={template} name={template} checked={templateName === template} toggle={e => this.toggleLayout(e, template)} />)); @@ -140,7 +140,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { rootSelected={returnFalse} onCheckedClick={this.scriptField} onChildClick={this.scriptField} - setHeight={returnFalse} dropAction={undefined} active={returnTrue} parentActive={returnFalse} diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 2013b3f43..46bfd841e 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -253,7 +253,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr const rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap)))); const style = this.props.parent; const chromeStatus = this.props.parent.props.Document._chromeStatus; - const showChrome = (chromeStatus !== 'view-mode' && chromeStatus !== 'disabled'); + const showChrome = (chromeStatus !== 'view-mode' && chromeStatus); const stackPad = showChrome ? `0px ${this.props.parent.xMargin}px` : `${this.props.parent.yMargin}px ${this.props.parent.xMargin}px 0px ${this.props.parent.xMargin}px `; return this.collapsed ? (null) : <div style={{ position: "relative" }}> diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index f3c1c4464..e3d7118e9 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -63,7 +63,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, @computed get gridGap() { return NumCast(this.layoutDoc._gridGap, 10); } @computed get isStackingView() { return (this.props.viewType ?? this.layoutDoc._viewType) === CollectionViewType.Stacking; } @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; } - @computed get showAddAGroup() { return (this.pivotField && (this.chromeStatus !== 'view-mode' && this.chromeStatus !== 'disabled')); } + @computed get showAddAGroup() { return (this.pivotField && (this.chromeStatus !== 'view-mode' && this.chromeStatus)); } @computed get columnWidth() { return Math.min(this.props.PanelWidth() /* / NumCast(this.layoutDoc._viewScale, 1)*/ - 2 * this.xMargin, this.isStackingView ? Number.MAX_VALUE : this.layoutDoc._columnWidth === -1 ? this.props.PanelWidth() - 2 * this.xMargin : NumCast(this.layoutDoc._columnWidth, 250)); @@ -539,7 +539,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}> <EditableView {...editableViewProps} /> </div>} - {/* {this.chromeStatus === 'disabled' || !this.props.isSelected() ? (null) : + {/* {!this.chromeStatus || !this.props.isSelected() ? (null) : <Switch onChange={this.onToggle} onClick={this.onToggle} diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 75ec6cd1a..389b449b5 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -300,7 +300,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC marginTop: NumCast(this.props.parent.yMargin, 5), width: (style.columnWidth) / ((uniqueHeadings.length + - ((this.props.parent.chromeStatus !== 'view-mode' && this.props.parent.chromeStatus !== 'disabled') ? 1 : 0)) || 1) + ((this.props.parent.chromeStatus !== 'view-mode' && this.props.parent.chromeStatus) ? 1 : 0)) || 1) }}> <div className={"collectionStackingView-collapseBar" + (this.props.headingObject.collapsed === true ? " active" : "")} onClick={this.collapseSection}></div> {/* the default bucket (no key value) has a tooltip that describes what it is. @@ -359,7 +359,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC {this.props.parent.children(this.props.docList, uniqueHeadings.length)} {singleColumn ? (null) : this.props.parent.columnDragger} </div> - {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled' && type !== DocumentType.PRES) ? + {(chromeStatus !== 'view-mode' && chromeStatus && type !== DocumentType.PRES) ? <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton" style={{ width: style.columnWidth / style.numGroupColumns, marginBottom: 10 }}> <EditableView @@ -385,7 +385,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC return ( <div className={"collectionStackingViewFieldColumn" + (SnappingManager.GetIsDragging() ? "Dragging" : "")} key={heading} style={{ - width: `${100 / ((uniqueHeadings.length + ((chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, + width: `${100 / ((uniqueHeadings.length + ((chromeStatus !== 'view-mode' && chromeStatus) ? 1 : 0)) || 1)}%`, height: undefined, // DraggingManager.GetIsDragging() ? "100%" : undefined, background: this._background }} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 77dfd126e..d22f6cfdc 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1203,19 +1203,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp prosediv && (prosediv.keeplocation = undefined); const pos = this._editorView?.state.selection.$from.pos || 1; keeplocation && setTimeout(() => this._editorView?.dispatch(this._editorView?.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos)))); - const coords = !Number.isNaN(this._downX) ? { left: this._downX, top: this._downY, bottom: this._downY, right: this._downX } : this._editorView?.coordsAtPos(pos); - - // jump rich text menu to this textbox - const bounds = this._ref.current?.getBoundingClientRect(); - if (bounds && this.layoutDoc._chromeStatus && RichTextMenu.Instance) { - const x = Math.min(Math.max(bounds.left, 0), window.innerWidth - RichTextMenu.Instance.width); - let y = Math.min(Math.max(0, bounds.top - RichTextMenu.Instance.height - 50), window.innerHeight - RichTextMenu.Instance.height); - if (coords && coords.left > x && coords.left < x + RichTextMenu.Instance.width && coords.top > y && coords.top < y + RichTextMenu.Instance.height + 50) { - y = Math.min(bounds.bottom, window.innerHeight - RichTextMenu.Instance.height); - } - this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props); - setTimeout(() => window.document.activeElement === this.ProseRef?.children[0] && RichTextMenu.Instance.jumpTo(x, y), 250); - } + + this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props); } onPointerWheel = (e: React.WheelEvent): void => { // if a text note is selected and scrollable, stop event to prevent, say, outer collection from zooming. |