diff options
| author | bobzel <zzzman@gmail.com> | 2020-08-23 16:26:28 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2020-08-23 16:26:28 -0400 |
| commit | f504934782b6458585148e3412b5fef975515931 (patch) | |
| tree | ba4f972597d5dcafbd6f1b108a142229c02fe0fe | |
| parent | 9caee7c75fcf535c398b40b18010acb677101686 (diff) | |
added settings for default text titles. fixed image audio annotatoins. fixed captions to not set title. added properties buttons for layout options and removed template layout button. fixed warnings.
28 files changed, 260 insertions, 204 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 36712ab3e..cce50e306 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -988,7 +988,7 @@ export namespace DocUtils { created = Docs.Create.StackingDocument(DocListCast(field), resolved); layout = CollectionView.LayoutString; } else { - created = Docs.Create.TextDocument("", { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved }); + created = Docs.Create.TextDocument("", { ...{ _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, _width: 200, _height: 25, _autoHeight: true }, ...resolved }); layout = FormattedTextBox.LayoutString; } if (created) { @@ -1048,7 +1048,7 @@ export namespace DocUtils { description: ":" + StrCast(note.title), event: undoBatch((args: { x: number, y: number }) => { const textDoc = Docs.Create.TextDocument("", { - _width: 200, x, y, _autoHeight: note._autoHeight !== false, + _width: 200, x, y, _autoHeight: note._autoHeight !== false, _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, title: StrCast(note.title) + "#" + (note.aliasCount = NumCast(note.aliasCount) + 1) }); textDoc.layoutKey = "layout_" + note.title; @@ -1175,7 +1175,7 @@ export namespace DocUtils { } const options = optionsCollection as Doc; const targetDoc = doc && Doc.GetProto(Cast(doc.rootDocument, Doc, null) || doc); - const docFind = `options.data.find(doc => doc.title === (this.rootDocument||this)["${enumeratedFieldKey}"])?`; + const docFind = `options.data?.find(doc => doc.title === (this.rootDocument||this)["${enumeratedFieldKey}"])?`; targetDoc && (targetDoc.backgroundColor = ComputedField.MakeFunction(docFind + `._backgroundColor || "white"`, undefined, { options })); targetDoc && (targetDoc.color = ComputedField.MakeFunction(docFind + `.color || "black"`, undefined, { options })); targetDoc && (targetDoc.borderRounding = ComputedField.MakeFunction(docFind + `.borderRounding`, undefined, { options })); diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 540540642..e66c15fcb 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -6,7 +6,6 @@ import { DocumentType } from "../documents/DocumentTypes"; import { Doc, Opt } from "../../fields/Doc"; import { List } from "../../fields/List"; import { Docs } from "../documents/Documents"; -import { CollectionViewType } from "../views/collections/CollectionView"; import { Cast, CastCtor } from "../../fields/Types"; import { listSpec } from "../../fields/Schema"; import { AudioField, ImageField } from "../../fields/URLField"; @@ -88,7 +87,7 @@ export namespace DictationManager { export const listen = async (options?: Partial<ListeningOptions>) => { let results: string | undefined; - const overlay = options !== undefined && options.useOverlay; + const overlay = options?.useOverlay; if (overlay) { DictationOverlay.Instance.dictationOverlayVisible = true; DictationOverlay.Instance.isListening = { interim: false }; @@ -100,11 +99,11 @@ export namespace DictationManager { Utils.CopyText(results); if (overlay) { DictationOverlay.Instance.isListening = false; - const execute = options && options.tryExecute; + const execute = options?.tryExecute; DictationOverlay.Instance.dictatedPhrase = execute ? results.toLowerCase() : results; DictationOverlay.Instance.dictationSuccess = execute ? await DictationManager.Commands.execute(results) : true; } - options && options.tryExecute && await DictationManager.Commands.execute(results); + options?.tryExecute && await DictationManager.Commands.execute(results); } } catch (e) { if (overlay) { @@ -129,12 +128,12 @@ export namespace DictationManager { } isListening = true; - const handler = options ? options.interimHandler : undefined; - const continuous = options ? options.continuous : undefined; + const handler = options?.interimHandler; + const continuous = options?.continuous; const indefinite = continuous && continuous.indefinite; - const language = options ? options.language : undefined; - const intra = options && options.delimiters ? options.delimiters.intra : undefined; - const inter = options && options.delimiters ? options.delimiters.inter : undefined; + const language = options?.language; + const intra = options?.delimiters?.intra; + const inter = options?.delimiters?.inter; recognizer.onstart = () => console.log("initiating speech recognition session..."); recognizer.interimResults = handler !== undefined; @@ -154,7 +153,7 @@ export namespace DictationManager { recognizer.onresult = (e: SpeechRecognitionEvent) => { current = synthesize(e, intra); let matchedTerminator: string | undefined; - if (options && options.terminators && (matchedTerminator = options.terminators.find(end => current ? current.trim().toLowerCase().endsWith(end.toLowerCase()) : false))) { + if (options?.terminators && (matchedTerminator = options.terminators.find(end => current ? current.trim().toLowerCase().endsWith(end.toLowerCase()) : false))) { current = matchedTerminator; recognizer.abort(); return complete(); diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index accb9c346..bc5e1e9d3 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -54,6 +54,7 @@ export default class SettingsManager extends React.Component<{}> { } @undoBatch selectUserMode = action((e: React.ChangeEvent) => Doc.UserDoc().noviceMode = (e.currentTarget as any)?.value === "Novice"); + @undoBatch changeShowTitle = action((e: React.ChangeEvent) => Doc.UserDoc().showTitle = (e.currentTarget as any).value); @undoBatch changeFontFamily = action((e: React.ChangeEvent) => Doc.UserDoc().fontFamily = (e.currentTarget as any).value); @undoBatch changeFontSize = action((e: React.ChangeEvent) => Doc.UserDoc().fontSize = (e.currentTarget as any).value); @undoBatch switchColor = action((color: ColorState) => Doc.UserDoc().activeCollectionBackground = String(color.hex)); @@ -90,13 +91,17 @@ export default class SettingsManager extends React.Component<{}> { {colorFlyout} </div> <div className="preferences-font"> - <div className="preferences-font-text">Default Font</div> + <div className="preferences-font-text">Font</div> <select className="font-select" onChange={this.changeFontFamily} value={StrCast(Doc.UserDoc().fontFamily, "Times New Roman")} > {fontFamilies.map(font => <option key={font} value={font} defaultValue={StrCast(Doc.UserDoc().fontFamily)}> {font} </option>)} </select> <select className="size-select" onChange={this.changeFontSize} value={StrCast(Doc.UserDoc().fontSize, "7pt")}> {fontSizes.map(size => <option key={size} value={size} defaultValue={StrCast(Doc.UserDoc().fontSize)}> {size} </option>)} </select> + <div> + Show title + <input type="checkbox" onChange={e => Doc.UserDoc().showTitle = !Doc.UserDoc().showTitle} checked={BoolCast(Doc.UserDoc().showTitle)} /> + </div> </div> </div>; } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 82ece7dc3..6e452e52d 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -24,6 +24,7 @@ import React = require("react"); import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { Tooltip } from '@material-ui/core'; import SharingManager from '../util/SharingManager'; +import { CurrentUserUtils } from '../util/CurrentUserUtils'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -217,6 +218,17 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV } @computed + get moreButton() { + const targetDoc = this.view0?.props.Document; + return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Open Properties Panel"}</div></>}> + <div className="documentButtonBar-linker" style={{ color: "white" }} onClick={action(e => + CurrentUserUtils.propertiesWidth = CurrentUserUtils.propertiesWidth > 0 ? 0 : 250)}> + <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="ellipsis-h" + /> + </div></Tooltip >; + } + + @computed get metadataButton() { const view0 = this.view0; return !view0 ? (null) : <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>}> @@ -304,8 +316,11 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV <div className="documentButtonBar-button"> {this.pinButton} </div> - <div className="documentButtonBar-button"> + {/* <div className="documentButtonBar-button"> {this.shareButton} + </div> */} + <div className="documentButtonBar-button"> + {this.moreButton} </div> {/* <div className="documentButtonBar-button" style={{ display: !considerPush ? "none" : "" }}> {this.considerGoogleDocsPush} diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index ec3e754fb..b96802f06 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -227,7 +227,10 @@ export class EditableView extends React.Component<EditableProps> { ref={this._ref} style={{ display: this.props.display, minHeight: "17px", whiteSpace: "nowrap", height: `${this.props.height ? this.props.height : "auto"}`, maxHeight: `${this.props.maxHeight}` }} onClick={this.onClick} placeholder={this.props.placeholder}> - {this.props.highlight === undefined || this.props.positions === undefined || this.props.bing === undefined ? <span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize, color: this.props.contents ? "black" : "grey" }}>{this.props.contents ? this.props.contents?.valueOf() : this.props.placeholder?.valueOf()}</span> + {this.props.highlight === undefined || this.props.positions === undefined || this.props.bing === undefined ? + <span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize }}>{//}, color: this.props.contents ? "black" : "grey" }}>{ + this.props.contents ? this.props.contents?.valueOf() : this.props.placeholder?.valueOf()} + </span> : this.returnHighlights()} </div> ); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ccb051f6d..f8be58f8d 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -182,7 +182,7 @@ export class MainView extends React.Component { fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp, fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, faBuffer, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl, - fa.faWindowMinimize, fa.faWindowRestore); + fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faClosedCaptioning); this.initEventListeners(); this.initAuthenticationRouters(); } diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 0eee46275..5d8f30354 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -92,6 +92,7 @@ export class PreviewCursor extends React.Component<{}> { _width: 500, limitHeight: 400, _autoHeight: true, + _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, x: newPoint[0], y: newPoint[1], title: "-pasted text-" diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss index 8d9d56c9e..d63eb874c 100644 --- a/src/client/views/PropertiesButtons.scss +++ b/src/client/views/PropertiesButtons.scss @@ -43,6 +43,13 @@ $linkGap : 3px; cursor: pointer; } } +.propertiesButtons-linkButton-empty.toggle-on { + background-color: white; + color: black; +} +.propertiesButtons-linkButton-empty.toggle-off { + color: white; +} .propertiesButtons { margin-top: 3px; diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index bcb492c49..ecd0ee37e 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -219,18 +219,11 @@ export class PropertiesButtons extends React.Component<{}, {}> { const isPinned = targetDoc && Doc.isDocPinned(targetDoc); return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div>} placement="top"> <div> - <div className="propertiesButtons-linker" - style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white" }} - onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}> + <div className={`propertiesButtons-linkButton-empty toggle-${isPinned ? "on" : "off"}`} onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}> <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin" /> </div> - <div className="propertiesButtons-title" - // style={{ - // backgroundColor: Doc.isDocPinned(targetDoc) ? "white" : "black", - // color: Doc.isDocPinned(targetDoc) ? "black" : "white" - // }} - >{Doc.isDocPinned(targetDoc) ? "Unpin" : "Pin"}</div> + <div className="propertiesButtons-title">{Doc.isDocPinned(targetDoc) ? "Unpin" : "Pin"}</div> </div> </Tooltip>; } @@ -375,17 +368,12 @@ export class PropertiesButtons extends React.Component<{}, {}> { return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{`${this.selectedDoc?.lockedPosition ? "Unlock" : "Lock"} " Position"`}</div>} placement="top"> <div> - <div className={"propertiesButtons-linkButton-empty"} onPointerDown={this.onLock} - style={{ backgroundColor: BoolCast(this.selectedDoc?.lockedPosition) ? "white" : "" }} > + <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" - // style={{ - // backgroundColor: BoolCast(this.selectedDoc?.lockedPosition) ? "white" : "black", - // color: BoolCast(this.selectedDoc?.lockedPosition) ? "black" : "white" - // }} >Position </div> </div> </Tooltip>; @@ -426,12 +414,88 @@ export class PropertiesButtons extends React.Component<{}, {}> { SelectionManager.DeselectAll(); } + @undoBatch + @action + setDictation = () => { + this.selectedDoc && (this.selectedDoc._showAudio = !this.selectedDoc._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>; + } + + + @undoBatch + @action + setTitle = () => { + this.selectedDoc && (this.selectedDoc._showTitle = this.selectedDoc._showTitle === undefined ? "title" : undefined); + } + + @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 ? "on" : "off"}`} onPointerDown={this.setTitle}> + <FontAwesomeIcon className="propertiesButtons-icon" icon="text-width" size="lg" /> + </div> + <div className="propertiesButtons-title"> Title </div> + </div> + </Tooltip>; + } + + @undoBatch + @action + setCaption = () => { + this.selectedDoc && (this.selectedDoc._showCaption = this.selectedDoc._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>; + } + + @undoBatch + @action + setChrome = () => { + this.selectedDoc && (this.selectedDoc._chromeStatus = this.selectedDoc._chromeStatus === "disabled" ? "enabled" : "disabled"); + } + + @computed + get chromeButton() { + const targetDoc = this.selectedDoc; + return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Show Editing UI"}</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> + <div className="propertiesButtons-title"> Controls </div> + </div> + </Tooltip>; + } + @computed get sharingButton() { const targetDoc = this.selectedDoc; const docView = this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined; - return !targetDoc ? (null) : <Tooltip - title={<><div className="dash-tooltip">{"Share Document"}</div></>} placement="top"> + return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"Share Document"}</div>} placement="top"> <div> <div className={"propertiesButtons-linkButton-empty"} onPointerDown={() => this.selectedDocumentView && SharingManager.Instance.open(docView, this.selectedDoc)}> <FontAwesomeIcon className="propertiesButtons-icon" icon="users" size="lg" /> @@ -561,19 +625,10 @@ export class PropertiesButtons extends React.Component<{}, {}> { 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"} - style={{ backgroundColor: this.selectedDoc?.useClusters ? "white" : "" }} - onPointerDown={this.changeClusters}> - {<FontAwesomeIcon className="documentdecorations-icon" - color={this.selectedDoc?.useClusters ? "black" : "white"} - icon="braille" size="lg" />} + <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc.userClusters ? "on" : "off"}`} onPointerDown={this.changeClusters}> + <FontAwesomeIcon className="documentdecorations-icon" icon="braille" size="lg" /> </div> - <div className="propertiesButtons-title" - // style={{ - // backgroundColor: this.selectedDoc?.useClusters ? "white" : "black", - // color: this.selectedDoc?.useClusters ? "black" : "white" - // }} - > clusters </div> + <div className="propertiesButtons-title" > clusters </div> </div> </Tooltip>; } @@ -594,19 +649,10 @@ export class PropertiesButtons extends React.Component<{}, {}> { 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"} - style={{ backgroundColor: this.selectedDoc?._fitToBox ? "white" : "" }} - onPointerDown={this.changeFitToBox}> - {<FontAwesomeIcon className="documentdecorations-icon" - color={this.selectedDoc?._fitToBox ? "black" : "white"} - icon="expand" size="lg" />} + <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" - // style={{ - // backgroundColor: this.selectedDoc?._fitToBox ? "white" : "black", - // color: this.selectedDoc?._fitToBox ? "black" : "white" - // }} - > {this.selectedDoc?._fitToBox ? "unfit" : "fit"} </div> + <div className="propertiesButtons-title"> {this.selectedDoc?._fitToBox ? "unfit" : "fit"} </div> </div> </Tooltip>; } @@ -690,9 +736,9 @@ export class PropertiesButtons extends React.Component<{}, {}> { const collectionAcl = GetEffectiveAcl(this.selectedDocumentView?.props.ContainingCollectionDoc?.[DataSym]); return <div><div className="propertiesButtons" style={{ paddingBottom: "5.5px" }}> - <div className="propertiesButtons-button"> + {/* <div className="propertiesButtons-button"> {this.templateButton} - </div> + </div> */} {/* <div className="propertiesButtons-button"> {this.metadataButton} </div> */} @@ -706,8 +752,20 @@ export class PropertiesButtons extends React.Component<{}, {}> { {this.copyButton} </div> <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: isText || isImage ? "" : "none" }}> + {this.dictationButton} + </div> <div className="propertiesButtons-button"> {this.downloadButton} </div> diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index e4ba45648..870af03aa 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -116,9 +116,9 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { const addedTypes = 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) => - templateMenu.push(<TemplateToggle key={template.Name} template={template} checked={checked} toggle={this.toggleTemplate} />)); - templateMenu.push(<OtherToggle key={"audio"} name={"Audio"} checked={firstDoc._showAudio ? true : false} toggle={this.toggleAudio} />); + //this.props.templates.forEach((checked, template) => + // templateMenu.push(<TemplateToggle key={template.Name} 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={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== "disabled"} toggle={this.toggleChrome} />); templateMenu.push(<OtherToggle key={"default"} name={"Default"} checked={templateName === "layout"} toggle={this.toggleDefault} />); addedTypes.concat(noteTypes).map(template => template.treeViewChecked = this.templateIsUsed(firstDoc, template)); diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index c772dcfe7..1c96f69bf 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -140,7 +140,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr addDocument = (value: string, shiftDown?: boolean) => { this._createAliasSelected = false; const key = StrCast(this.props.parent.props.Document._pivotField); - const newDoc = Docs.Create.TextDocument(value, { _autoHeight: true, _width: 200, title: value }); + const newDoc = Docs.Create.TextDocument(value, { _autoHeight: true, _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, _width: 200, title: value }); newDoc[key] = this.getValue(this.props.heading); const docs = this.props.parent.childDocList; return docs ? (docs.splice(0, 0, newDoc) ? true : false) : this.props.parent.props.addDocument(newDoc); diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index ede75fba8..0a206a6c6 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -136,7 +136,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC addDocument = (value: string, shiftDown?: boolean) => { if (!value) return false; const key = StrCast(this.props.parent.props.Document._pivotField); - const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, title: value, _autoHeight: true }); + const newDoc = Docs.Create.TextDocument(value, { _height: 18, _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, _width: 200, title: value, _autoHeight: true }); newDoc[key] = this.getValue(this.props.heading); const maxHeading = this.props.docList.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; @@ -269,7 +269,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC ContextMenu.Instance.addItem({ description: "Containers ...", subitems: layoutItems, icon: "eye" }); ContextMenu.Instance.setDefaultItem("::", (name: string): void => { Doc.GetProto(this.props.parent.props.Document)[name] = ""; - const created = Docs.Create.TextDocument("", { title: name, _width: 250, _autoHeight: true }); + const created = Docs.Create.TextDocument("", { title: name, _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, _width: 250, _autoHeight: true }); if (created) { if (this.props.parent.Document.isTemplateDoc) { Doc.MakeMetadataFieldTemplate(created, this.props.parent.props.Document); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 71e891045..cb3f486bb 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -284,7 +284,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: this.addDocument(Docs.Create.WebDocument(href, { ...options, title: href })); } } else if (text) { - this.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 100, _height: 25 })); + this.addDocument(Docs.Create.TextDocument(text, { ...options, _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, _width: 100, _height: 25 })); } return; } @@ -460,7 +460,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: completed?.(); } else { if (text && !text.includes("https://")) { - UndoManager.RunInBatch(() => this.addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 })), "drop"); + UndoManager.RunInBatch(() => this.addDocument(Docs.Create.TextDocument(text, { ...options, _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, title: text.substring(0, 20), _width: 400, _height: 315 })), "drop"); } } disposer(); diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index 7de0b14ac..4dafa4ac4 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -363,7 +363,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch createRow = action(() => { - this.props.addDocument(Docs.Create.TextDocument("", { title: "", _width: 100, _height: 30 })); + this.props.addDocument(Docs.Create.TextDocument("", { title: "", _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, _width: 100, _height: 30 })); this._focusedCell = { row: this.childDocs.length, col: this._focusedCell.col }; }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 0c0f6ca58..206d04cf7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1045,7 +1045,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } else if (viewDef.type === "div") { return [x, y].some(val => val === undefined) ? undefined : { - ele: <div className="collectionFreeform-customDiv" title={viewDef.payload?.join(" ")} key={"div" + x + y + z} onClick={e => this.onViewDefDivClick(e, viewDef)} + ele: <div className="collectionFreeform-customDiv" title={viewDef.payload?.join(" ")} key={"div" + x + y + z + viewDef.payload} onClick={e => this.onViewDefDivClick(e, viewDef)} style={{ width, height, backgroundColor: color, transform }} />, bounds: viewDef }; @@ -1597,18 +1597,15 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF const vfWidth: number = PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-width-indexed"]); const vfTop: number = PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-top-indexed"]); const vfHeight: number = PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-height-indexed"]); - return ( - <> - {!activeItem.editZoomProgressivize ? (null) : <div id="resizable" className="resizable" onPointerDown={this.onPointerDown} style={{ width: vfWidth, height: vfHeight, top: vfTop, left: vfLeft, position: 'absolute' }}> - <div className='resizers'> - <div id="resizer-tl" className='resizer top-left' onPointerDown={this.onPointerDown}></div> - <div id="resizer-tr" className='resizer top-right' onPointerDown={this.onPointerDown}></div> - <div id="resizer-bl" className='resizer bottom-left' onPointerDown={this.onPointerDown}></div> - <div id="resizer-br" className='resizer bottom-right' onPointerDown={this.onPointerDown}></div> - </div> - </div>} - </> - ); + return !activeItem.editZoomProgressivize ? (null) : + <div id="resizable" key="zoomProgressivize" className="resizable" onPointerDown={this.onPointerDown} style={{ width: vfWidth, height: vfHeight, top: vfTop, left: vfLeft, position: 'absolute' }}> + <div className='resizers'> + <div id="resizer-tl" className='resizer top-left' onPointerDown={this.onPointerDown}></div> + <div id="resizer-tr" className='resizer top-right' onPointerDown={this.onPointerDown}></div> + <div id="resizer-bl" className='resizer bottom-left' onPointerDown={this.onPointerDown}></div> + <div id="resizer-br" className='resizer bottom-right' onPointerDown={this.onPointerDown}></div> + </div> + </div>; } } @@ -1622,30 +1619,30 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF @computed get presPaths() { const presPaths = "presPaths" + (this.props.presPaths ? "" : "-hidden"); - return !(PresBox.Instance) ? (null) : (<> - {!this.props.presPaths ? (null) : <><div>{PresBox.Instance.order}</div> - <svg className={presPaths}> - <defs> - <marker id="arrow" markerWidth="3" overflow="visible" markerHeight="3" refX="5" refY="5" orient="auto" markerUnits="strokeWidth"> - <path d="M0,0 L0,6 L9,3 z" fill="#69a6db" /> - </marker> - <marker id="square" markerWidth="3" markerHeight="3" overflow="visible" - refX="5" refY="5" orient="auto" markerUnits="strokeWidth"> - <path d="M 5,1 L 9,5 5,9 1,5 z" fill="#69a6db" /> - </marker> - <marker id="markerSquare" markerWidth="7" markerHeight="7" refX="4" refY="4" - orient="auto" overflow="visible"> - <rect x="1" y="1" width="5" height="5" fill="#69a6db" /> - </marker> - - <marker id="markerArrow" markerWidth="5" markerHeight="5" refX="2" refY="7" - orient="auto" overflow="visible"> - <path d="M2,2 L2,13 L8,7 L2,2" fill="#69a6db" /> - </marker> - </defs>; - {PresBox.Instance.paths} - </svg></>} - </>); + return !PresBox.Instance || !this.props.presPaths ? (null) : <> + <div key="presorder">{PresBox.Instance.order}</div> + <svg key="svg" className={presPaths}> + <defs> + <marker id="arrow" markerWidth="3" overflow="visible" markerHeight="3" refX="5" refY="5" orient="auto" markerUnits="strokeWidth"> + <path d="M0,0 L0,6 L9,3 z" fill="#69a6db" /> + </marker> + <marker id="square" markerWidth="3" markerHeight="3" overflow="visible" + refX="5" refY="5" orient="auto" markerUnits="strokeWidth"> + <path d="M 5,1 L 9,5 5,9 1,5 z" fill="#69a6db" /> + </marker> + <marker id="markerSquare" markerWidth="7" markerHeight="7" refX="4" refY="4" + orient="auto" overflow="visible"> + <rect x="1" y="1" width="5" height="5" fill="#69a6db" /> + </marker> + + <marker id="markerArrow" markerWidth="5" markerHeight="5" refX="2" refY="7" + orient="auto" overflow="visible"> + <path d="M2,2 L2,13 L8,7 L2,2" fill="#69a6db" /> + </marker> + </defs> + {PresBox.Instance.paths} + </svg> + </>; } render() { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 0918e8389..3a9f31bef 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -130,6 +130,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque const tbox = Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize), _fontFamily: StrCast(Doc.UserDoc().fontFamily), + _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, title: "-typed text-" }); const template = FormattedTextBox.DefaultLayout; @@ -493,7 +494,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque d.page = -1; return d; }); - const summary = Docs.Create.TextDocument("", { x: bounds.left + bounds.width / 2, y: bounds.top + bounds.height / 2, _width: 200, _height: 200, _fitToBox: true, _showSidebar: true, title: "overview" }); + const summary = Docs.Create.TextDocument("", { x: bounds.left + bounds.width / 2, y: bounds.top + bounds.height / 2, _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, _width: 200, _height: 200, _fitToBox: true, _showSidebar: true, title: "overview" }); const portal = Doc.MakeAlias(summary); Doc.GetProto(summary)[Doc.LayoutFieldKey(summary) + "-annotations"] = new List<Doc>(selected); Doc.GetProto(summary).layout_portal = CollectionView.LayoutString(Doc.LayoutFieldKey(summary) + "-annotations"); diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index 278f3b964..e3ced887d 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -303,7 +303,6 @@ margin-left: auto; .permissions-select { - z-index: 1; border: none; background-color: inherit; width: 75px; @@ -734,7 +733,7 @@ background: #eeeeee; border-top: 1px solid; border-left: 1px solid; - + &:hover { border: 0.75px solid rgb(122, 28, 28); } diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 50597f2eb..e128f6aab 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -184,7 +184,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const noviceReqFields = ["author", "creationDate"]; const noviceLayoutFields = ["curPage"]; const noviceKeys = [...Array.from(Object.keys(ids)).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("ACL") && key !== "UseCors")), - ...noviceReqFields, ...noviceLayoutFields] + ...noviceReqFields, ...noviceLayoutFields]; for (const key of noviceKeys.sort()) { const contents = this.selectedDoc[key]; if (key[0] === "#") { @@ -200,7 +200,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div style={{ whiteSpace: "nowrap", overflowX: "hidden" }}>{value}</div> </div>); } else { - let contentElement = <EditableView key="editableView" + const contentElement = <EditableView key="editableView" contents={value} height={13} fontSize={10} diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 70ebca5e7..4e279c659 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -304,7 +304,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { (e: PointerEvent, doubleTap?: boolean) => { if (doubleTap) { undoBatch(action(() => { - const text = Docs.Create.TextDocument("", { _width: 150, _height: 50 }); + const text = Docs.Create.TextDocument("", { _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, _width: 150, _height: 50 }); FormattedTextBox.SelectOnLoad = text[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed Doc.AddDocToList(this.props.Document, this.props.fieldKey, text); this.setLayoutList(this.addLayoutItem(this.savedLayoutList, this.makeLayoutItem(text, this.screenToCell(e.clientX, e.clientY)))); diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 8ecde959f..519b78add 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -93,7 +93,6 @@ export class LinkMenu extends React.Component<Props> { } render() { - console.log("computed", this.position.x, this.position.b); const sourceDoc = this.props.docView.props.Document; const groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); return <div className="linkMenu" ref={this._linkMenuRef} > diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 5c8cb5e35..7b9a32dbe 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -109,12 +109,14 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD this._linkPlayDisposer?.(); this._scrubbingDisposer?.(); } + + @action componentDidMount() { if (!this.dataDoc.markerAmount) { this.dataDoc.markerAmount = 0; } - runInAction(() => this.audioState = this.path ? "paused" : undefined); + this.audioState = this.path ? "paused" : undefined; this._linkPlayDisposer = reaction(() => this.layoutDoc.scrollToLinkID, scrollLinkId => { if (scrollLinkId) { @@ -285,7 +287,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD // creates a text document for dictation onFile = (e: any) => { const newDoc = Docs.Create.TextDocument("", { - title: "", _chromeStatus: "disabled", + _showTitle: Doc.UserDoc().showTitle ? "title" : undefined, title: "", _chromeStatus: "disabled", x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y) + NumCast(this.props.Document._height) + 10, _width: NumCast(this.props.Document._width), _height: 2 * NumCast(this.props.Document._height) }); diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index e6b8928d4..2dd3bba91 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -133,6 +133,8 @@ bottom: 0; width: 100%; transform-origin: bottom left; + opacity: 0.1; + transition: opacity 0.5s; } } @@ -144,4 +146,9 @@ display:inline-block; } } + > .documentView-styleWrapper { + > .documentView-captionWrapper { + opacity: 1; + } + } }
\ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bf42f30fe..db6d30aac 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -771,7 +771,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" }); } moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); - Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()) && moreItems.push({ description: "Toggle Always Show Link End", event: () => Doc.UserDoc()["documentLinksButton-hideEnd"] = !Doc.UserDoc()["documentLinksButton-hideEnd"], icon: "eye" }); + Doc.AreProtosEqual(this.props.Document, Cast(Doc.UserDoc()["sidebar-userDoc"], Doc, null)) && moreItems.push({ description: "Toggle Always Show Link End", event: () => Doc.UserDoc()["documentLinksButton-hideEnd"] = !Doc.UserDoc()["documentLinksButton-hideEnd"], icon: "eye" }); } const collectionAcl = GetEffectiveAcl(this.props.ContainingCollectionDoc?.[DataSym]); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index dd3914df7..5f31f8c8d 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -111,23 +111,17 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD }).then(function (stream) { gumStream = stream; recorder = new MediaRecorder(stream); - recorder.ondataavailable = async function (e: any) { - const formData = new FormData(); - formData.append("file", e.data); - const res = await fetch(Utils.prepend("/uploadFormData"), { - method: 'POST', - body: formData - }); - const files = await res.json(); - const url = Utils.prepend(files[0].path); - // upload to server with known URL - const audioDoc = Docs.Create.AudioDocument(url, { title: "audio test", _width: 200, _height: 32 }); - audioDoc.treeViewExpandedView = "layout"; - const audioAnnos = Cast(this.dataDoc[this.fieldKey + "-audioAnnotations"], listSpec(Doc)); - if (audioAnnos === undefined) { - this.dataDoc[this.fieldKey + "-audioAnnotations"] = new List([audioDoc]); - } else { - audioAnnos.push(audioDoc); + recorder.ondataavailable = async (e: any) => { + const [{ result }] = await Networking.UploadFilesToServer(e.data); + if (!(result instanceof Error)) { + const audioDoc = Docs.Create.AudioDocument(Utils.prepend(result.accessPaths.agnostic.client), { title: "audio test", _width: 200, _height: 32 }); + audioDoc.treeViewExpandedView = "layout"; + const audioAnnos = Cast(self.dataDoc[self.fieldKey + "-audioAnnotations"], listSpec(Doc)); + if (audioAnnos === undefined) { + self.dataDoc[self.fieldKey + "-audioAnnotations"] = new List([audioDoc]); + } else { + audioAnnos.push(audioDoc); + } } }; runInAction(() => self._audioState = 2); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index d30ea03b1..ba59c2df7 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -1459,7 +1459,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> tags.push(<div style={{ position: 'absolute', display: doc.displayMovement ? "block" : "none" }}>{this.checkMovementLists(doc, doc["x-indexed"], doc["y-indexed"])}</div>); } tags.push( - <div className="progressivizeButton" onPointerLeave={() => { if (NumCast(targetDoc.currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0; }} onPointerOver={() => { if (NumCast(targetDoc.currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0.5; }} onClick={e => { this.toggleDisplayMovement(doc); e.stopPropagation(); }} style={{ backgroundColor: doc.displayMovement ? "#aedff8" : "#c8c8c8", top: NumCast(doc.y), left: NumCast(doc.x) }}> + <div className="progressivizeButton" key={index} onPointerLeave={() => { if (NumCast(targetDoc.currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0; }} onPointerOver={() => { if (NumCast(targetDoc.currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0.5; }} onClick={e => { this.toggleDisplayMovement(doc); e.stopPropagation(); }} style={{ backgroundColor: doc.displayMovement ? "#aedff8" : "#c8c8c8", top: NumCast(doc.y), left: NumCast(doc.x) }}> <div className="progressivizeButton-prev"><FontAwesomeIcon icon={"caret-left"} size={"lg"} onClick={e => { e.stopPropagation(); this.prevAppearFrame(doc, index); }} /></div> <div className="progressivizeButton-frame">{doc.appearFrame}</div> <div className="progressivizeButton-next"><FontAwesomeIcon icon={"caret-right"} size={"lg"} onClick={e => { e.stopPropagation(); this.nextAppearFrame(doc, index); }} /></div> diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index afdd8fea2..160f4ba72 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -32,8 +32,8 @@ .formattedTextBox-dictation { height: 12px; width: 10px; - top: 0px; - left: 0px; + bottom: 5px; + right: 8px; position: absolute; } } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 7a6d263f9..b473ad425 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -100,7 +100,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp private _pause: boolean = false; @computed get _recording() { return this.dataDoc.audioState === "recording"; } - set _recording(value) { this.dataDoc.audioState = value ? "recording" : undefined; } + set _recording(value) { + this.dataDoc.audioState = value ? "recording" : undefined; + } @observable private _entered = false; @@ -350,7 +352,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp updateTitle = () => { if ((this.props.Document.isTemplateForField === "text" || !this.props.Document.isTemplateForField) && // only update the title if the data document's data field is changing - StrCast(this.dataDoc.title).startsWith("-") && this._editorView && !this.dataDoc["title-custom"]) { + StrCast(this.dataDoc.title).startsWith("-") && this._editorView && !this.dataDoc["title-custom"] && + Doc.LayoutFieldKey(this.rootDoc) === this.fieldKey) { let node = this._editorView.state.doc; while (node.firstChild && node.firstChild.type.name !== "text") node = node.firstChild; const str = node.textContent; @@ -383,7 +386,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp let tr = this._editorView.state.tr; const flattened: TextSelection[] = []; res.map(r => r.map(h => flattened.push(h))); - console.log("Search:" + this.rootDoc.title + " " + this._searchIndex + " => " + (this._searchIndex + 1 > flattened.length - 1 ? 0 : this._searchIndex + 1)); this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex; if (backward === true) { if (this._searchIndex > 1) { @@ -658,7 +660,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const newBullets: Doc[] = this.recursiveProgressivize(1, list)[0]; mainBulletList.push.apply(mainBulletList, newBullets); } - console.log(mainBulletList.length); const title = Docs.Create.TextDocument(StrCast(this.rootDoc.title), { title: "Title", _width: 800, _height: 70, x: 20, y: -10, _fontSize: '20pt', backgroundColor: "rgba(0,0,0,0)", appearFrame: 0, _fontWeight: 700 }); mainBulletList.push(title); const doc = Docs.Create.FreeformDocument(mainBulletList, { @@ -713,7 +714,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp recordDictation = () => { DictationManager.Controls.listen({ - interimHandler: this.setCurrentBulletContent, + interimHandler: this.setDictationContent, continuous: { indefinite: false }, }).then(results => { if (results && [DictationManager.Controls.Infringed].includes(results)) { @@ -724,22 +725,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } stopDictation = (abort: boolean) => { DictationManager.Controls.stop(!abort); }; - recordBullet = async () => { - const completedCue = "end session"; - const results = await DictationManager.Controls.listen({ - interimHandler: this.setCurrentBulletContent, - continuous: { indefinite: false }, - terminators: [completedCue, "bullet", "next"] - }); - if (results && [DictationManager.Controls.Infringed, completedCue].includes(results)) { - DictationManager.Controls.stop(); - return; - } - this.nextBullet(this._editorView!.state.selection.to); - setTimeout(this.recordBullet, 2000); - } - - setCurrentBulletContent = (value: string) => { + setDictationContent = (value: string) => { if (this._editorView) { const state = this._editorView.state; const now = Date.now(); @@ -754,33 +740,17 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } } } - const recordingStart = DateCast(this.props.Document.recordingStart).date.getTime(); - this._break = false; - value = "" + (mark.attrs.modified * 1000 - recordingStart) / 1000 + value; const from = state.selection.from; - const inserted = state.tr.insertText(value).addMark(from, from + value.length + 1, mark); - this._editorView.dispatch(inserted.setSelection(TextSelection.create(inserted.doc, from, from + value.length + 1))); - } - } - - nextBullet = (pos: number) => { - if (this._editorView) { - const frag = Fragment.fromArray(this.newListItems(2)); - if (this._editorView.state.doc.resolve(pos).depth >= 2) { - const slice = new Slice(frag, 2, 2); - let state = this._editorView.state; - this._editorView.dispatch(state.tr.step(new ReplaceStep(pos, pos, slice))); - pos += 4; - state = this._editorView.state; - this._editorView.dispatch(state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos, pos))); + this._break = false; + if (this.props.Document.recordingStart) { + const recordingStart = DateCast(this.props.Document.recordingStart)?.date.getTime(); + value = "" + (mark.attrs.modified * 1000 - recordingStart) / 1000 + value; } + const tr = state.tr.insertText(value).addMark(from, from + value.length + 1, mark); + this._editorView.dispatch(tr.setSelection(TextSelection.create(tr.doc, from, from + value.length + 1))); } } - private newListItems = (count: number) => { - return numberRange(count).map(x => schema.nodes.list_item.create(undefined, schema.nodes.paragraph.create())); - } - _keymap: any = undefined; _rules: RichTextRules | undefined; @computed get config() { @@ -903,21 +873,23 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.setupEditor(this.config, this.props.fieldKey); this._disposers.search = reaction(() => Doc.IsSearchMatch(this.rootDoc), - search => { - search ? this.highlightSearchTerms([Doc.SearchQuery()], search.searchMatch < 0) : this.unhighlightSearchTerms(); - }, + search => search ? this.highlightSearchTerms([Doc.SearchQuery()], search.searchMatch < 0) : this.unhighlightSearchTerms(), { fireImmediately: Doc.IsSearchMatchUnmemoized(this.rootDoc) ? true : false }); - this._disposers.record = reaction(() => this._recording, - () => { - if (this._recording) { - setTimeout(action(() => { - this.stopDictation(true); - setTimeout(() => this.recordDictation(), 500); - }), 500); - } else setTimeout(() => this.stopDictation(true), 0); - } - ); + this._disposers.selected = reaction(() => this.props.isSelected(), action(() => this._recording = false)); + + if (!this.props.dontRegisterView) { + this._disposers.record = reaction(() => this._recording, + () => { + if (this._recording) { + setTimeout(action(() => { + this.stopDictation(true); + setTimeout(() => this.recordDictation(), 500); + }), 500); + } else setTimeout(() => this.stopDictation(true), 0); + } + ); + } this._disposers.scrollToRegion = reaction( () => StrCast(this.layoutDoc.scrollToLinkID), async (scrollToLinkID) => { @@ -1410,7 +1382,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const self = this; return new Plugin({ view(newView) { - self.props.isSelected(true) && (RichTextMenu.Instance.view = newView); + self.props.isSelected(true) && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView); return self.menuPlugin = new RichTextMenuPlugin({ editorProps: this.props }); } }); @@ -1432,7 +1404,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp public static HadSelection: boolean = false; onBlur = (e: any) => { FormattedTextBox.HadSelection = window.getSelection()?.toString() !== ""; - //DictationManager.Controls.stop(false); this.endUndoTypingBatch(); this.doLinkOnDeselect(); @@ -1545,13 +1516,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp width: "100%", height: this.props.height ? this.props.height : this.layoutDoc._autoHeight && this.props.renderDepth ? "max-content" : undefined, background: Doc.UserDoc().renderStyle === "comic" ? "transparent" : this.props.background ? this.props.background : StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], this.props.hideOnLeave ? "rgba(0,0,0 ,0.4)" : ""), - opacity: this.props.hideOnLeave ? (this._entered ? 1 : 0.1) : 1, color: this.props.color ? this.props.color : StrCast(this.layoutDoc[this.props.fieldKey + "-color"], this.props.hideOnLeave ? "white" : "inherit"), pointerEvents: interactive ? undefined : "none", fontSize: Cast(this.layoutDoc._fontSize, "string", null), fontWeight: Cast(this.layoutDoc._fontWeight, "number", null), fontFamily: StrCast(this.layoutDoc._fontFamily, "inherit"), - transition: "opacity 1s" }} onContextMenu={this.specificContextMenu} onKeyDown={this.onKeyPress} @@ -1615,14 +1584,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} /> </div>} {!this.layoutDoc._showAudio ? (null) : - <div className="formattedTextBox-dictation" - onPointerDown={e => { - runInAction(() => this._recording = !this._recording); - setTimeout(() => this._editorView!.focus(), 500); - e.stopPropagation(); - }} > + <div className="formattedTextBox-dictation" onClick={action(e => this._recording = !this._recording)} > <FontAwesomeIcon className="formattedTextBox-audioFont" - style={{ color: this._recording ? "red" : "blue", opacity: this._recording ? 1 : 0.5, display: this.props.isSelected() ? "" : "none" }} icon={"microphone"} size="sm" /> + style={{ + color: this._recording ? "red" : "blue", + transitionDelay: "0.6s", + opacity: this._recording ? 1 : 0.25, + }} + icon={"microphone"} size="sm" /> </div>} </div> </div> diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index e93fc86b5..bed6c83b4 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -442,7 +442,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight panelHeight = () => this.props.PanelHeight(); - selectElement = (doc: Doc) => { /* this.gotoDocument(this.childDocs.indexOf(doc), NumCasst(this.layoutDoc._itemIndex)); */ } + selectElement = (doc: Doc) => { /* this.gotoDocument(this.childDocs.indexOf(doc), NumCasst(this.layoutDoc._itemIndex)); */ }; returnHeight = () => 31 + 31 * 6; returnLength = () => Math.min(window.innerWidth, 51 + 205 * Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []).length); |
