diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/AudioBox.scss | 279 | ||||
| -rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 6 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 21 | ||||
| -rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 6 | ||||
| -rw-r--r-- | src/client/views/nodes/WebBox.tsx | 27 | ||||
| -rw-r--r-- | src/client/views/nodes/button/FontIconBox.scss | 16 | ||||
| -rw-r--r-- | src/client/views/nodes/button/FontIconBox.tsx | 63 | ||||
| -rw-r--r-- | src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx | 10 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.scss | 1 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 15 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/RichTextMenu.tsx | 14 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 8 |
13 files changed, 290 insertions, 178 deletions
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index 93ad7ebcd..cf9d97128 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -49,8 +49,10 @@ pointer-events: all; width: 100%; height: 100%; + position: inherit; + display: flex; position: relative; - } + cursor: default; .audiobox-record { pointer-events: none; @@ -94,116 +96,213 @@ padding: 5px; } } + .audiobox-buttons { + display: flex; + width: 100%; + align-items: center; + height: 100%; - .audiobox-controls { - width: 100%; - height: 100%; - position: relative; - display: flex; - background: $dark-gray; + .audiobox-dictation { + position: relative; + width: 30px; + height: 100%; + align-items: center; + display: inherit; + background: $medium-gray; + left: 0px; + color: $dark-gray; - .audiobox-dictation { - position: absolute; - width: 40px; - height: 100%; - align-items: center; - display: inherit; - background: $medium-gray; - left: 0px; + &:hover { + color: $black; + cursor: pointer; + } + } } - .audiobox-player { - margin-top: auto; - margin-bottom: auto; - width: 100%; - position: relative; - padding-right: 5px; - display: flex; - flex-direction: column; - justify-content: center; + .audiobox-control, + .audiobox-control-interactive { + top: 0; + max-height: 32px; + width: 100%; + display: inline-block; + pointer-events: none; + } + + .audiobox-control-interactive { + pointer-events: all; + } - .audiobox-buttons { + .audiobox-record-interactive, + .audiobox-record { + pointer-events: all; + cursor: pointer; + width: 100%; + height: 100%; position: relative; - margin-top: auto; - margin-bottom: auto; - width: 30px; - height: 30px; - border-radius: 50%; - background-color: $dark-gray; - color: $white; display: flex; + flex-direction: row; align-items: center; justify-content: center; - left: 5px; - &:hover { - background-color: $black; - } + gap: 10px; + color: white; + font-weight: bold; + } - svg { - width: 100%; - position: absolute; - border-width: "thin"; - border-color: "white"; - } - } + .audiobox-record { + pointer-events: none; + } - .audiobox-dictation { - position: relative; + .recording { margin-top: auto; margin-bottom: auto; - width: 25px; + width: 100%; + height: 100%; + position: relative; + padding-right: 5px; + display: flex; + flex-direction: row; + justify-content: center; align-items: center; - display: inherit; - background: $medium-gray; - } + gap: 7px; + background-color: $medium-blue; + padding: 10px; + + .time { + position: relative; + height: 100%; + width: 100%; + font-size: 16px; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + font-weight: bold; + } + + .buttons { + cursor: pointer; + position: relative; + margin-top: auto; + margin-bottom: auto; + width: 25px; + width: 25px; + padding: 5px; + color: $dark-gray; + + &:hover { + color: $black; + } + } + } - .audiobox-timeline { - position: absolute; + .audiobox-controls { width: 100%; - z-index: 1000; - overflow: hidden; - border-right: 5px solid black; - } + height: 100%; + position: relative; + display: flex; + background: $dark-gray; - .audioBox-total-time, - .audioBox-current-time { - position: absolute; - font-size: $small-text; - top: 100%; - color: $white; - } - .audioBox-current-time { - left: 42px; - } + .audiobox-dictation { + position: absolute; + width: 40px; + height: 100%; + align-items: center; + display: inherit; + background: $medium-gray; + left: 0px; + } - .audioBox-total-time { - right: 2px; - } + .audiobox-player { + margin-top: auto; + margin-bottom: auto; + width: 100%; + position: relative; + padding-right: 5px; + display: flex; + flex-direction: column; + justify-content: center; + + .audiobox-buttons { + position: relative; + margin-top: auto; + margin-bottom: auto; + width: 30px; + height: 30px; + border-radius: 50%; + background-color: $dark-gray; + color: $white; + display: flex; + align-items: center; + justify-content: center; + left: 5px; + + &:hover { + background-color: $black; + } + + svg { + width: 100%; + position: absolute; + border-width: "thin"; + border-color: "white"; + } + } + + .audiobox-dictation { + position: relative; + margin-top: auto; + margin-bottom: auto; + width: 25px; + align-items: center; + display: inherit; + background: $medium-gray; + } + + .audiobox-timeline { + position: absolute; + width: 100%; + z-index: 1000; + overflow: hidden; + border-right: 5px solid black; + } + + .audioBox-total-time, + .audioBox-current-time { + position: absolute; + font-size: $small-text; + top: 100%; + color: $white; + } + + .audioBox-current-time { + left: 42px; + } + + .audioBox-total-time { + right: 2px; + } + } } - } } @media only screen and (max-device-width: 480px) { - .audiobox-dictation { - font-size: 5em; - display: flex; - width: 100; - justify-content: center; - flex-direction: column; - align-items: center; - } + .audiobox-dictation { + font-size: 5em; + display: flex; + width: 100; + justify-content: center; + flex-direction: column; + align-items: center; + } - .audiobox-container .audiobox-record, - .audiobox-container-interactive .audiobox-record { - font-size: 3em; - } + .audiobox-container .audiobox-record, + .audiobox-container-interactive .audiobox-record { + font-size: 3em; + } - .audiobox-container .audiobox-controls .audiobox-player .audiobox-buttons, - .audiobox-container .audiobox-controls .audiobox-player .audiobox-dictation, - .audiobox-container-interactive - .audiobox-controls - .audiobox-player - .audiobox-buttons { - width: 70px; - } -} + .audiobox-container .audiobox-controls .audiobox-player .audiobox-buttons, + .audiobox-container .audiobox-controls .audiobox-player .audiobox-dictation, + .audiobox-container-interactive .audiobox-controls .audiobox-player .audiobox-buttons { + width: 70px; + } +}
\ No newline at end of file diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 05dd64b68..cdb37bf92 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -605,10 +605,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent< <div className="audiobox-dictation" onClick={this.onFile}> <FontAwesomeIcon style={{ - width: "30px", - background: !this.layoutDoc.dontAutoPlayFollowedLinks - ? Colors.LIGHT_BLUE - : "rgba(0,0,0,0)", + width: "30px" }} icon="file-alt" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} @@ -642,6 +639,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent< className={`audiobox-record${interactive}`} style={{ backgroundColor: Colors.DARK_GRAY }} > + <FontAwesomeIcon icon="microphone" /> RECORD </div> )} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a2d2f17b6..193befa5d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -13,7 +13,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Ty import { AudioField } from "../../../fields/URLField"; import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util'; import { MobileInterface } from '../../../mobile/MobileInterface'; -import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark } from "../../../Utils"; +import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark, simulateMouseClick } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; @@ -49,6 +49,7 @@ import { RadialMenu } from './RadialMenu'; import { ScriptingBox } from "./ScriptingBox"; import { PresBox } from './trails/PresBox'; import React = require("react"); +import { IconProp } from "@fortawesome/fontawesome-svg-core"; const { Howl } = require('howler'); interface Window { @@ -153,7 +154,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps { NativeWidth?: () => number; NativeHeight?: () => number; LayoutTemplate?: () => Opt<Doc>; - contextMenuItems?: () => { script: ScriptField, label: string }[]; + contextMenuItems?: () => { script: ScriptField, filter?: ScriptField, label: string, icon: string }[]; onClick?: () => ScriptField; onDoubleClick?: () => ScriptField; onPointerDown?: () => ScriptField; @@ -535,6 +536,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps } onPointerMove = (e: PointerEvent): void => { + if (e.cancelBubble) return; if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool))) return; if (e.cancelBubble && this.props.isDocumentActive?.()) { document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView) @@ -669,11 +671,23 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps const cm = ContextMenu.Instance; if (!cm || (e as any)?.nativeEvent?.SchemaHandled) return; + if (e?.buttons === 2) { + const onDisplay = () => setTimeout(() => { + DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. + setTimeout(() => { + const ele = document.elementFromPoint(e.clientX, e.clientY); + simulateMouseClick(ele, e.clientX, e.clientY, e.screenX, e.screenY); + }); + }); + cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15, undefined, undefined, onDisplay); + return; + } + const customScripts = Cast(this.props.Document.contextMenuScripts, listSpec(ScriptField), []); StrListCast(this.Document.contextMenuLabels).forEach((label, i) => cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ documentView: this, this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" })); this.props.contextMenuItems?.().forEach(item => - item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" })); + item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: item.icon as IconProp })); if (!this.props.Document.isFolder) { const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); @@ -775,7 +789,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15); - DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. } rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 38deb4a73..b41bfd3ea 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -144,9 +144,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const funcs: ContextMenuProps[] = []; funcs.push({ description: "Rotate Clockwise 90", event: this.rotate, icon: "expand-arrows-alt" }); funcs.push({ description: `Show ${this.layoutDoc._showFullRes ? "Dynamic Res" : "Full Res"}`, event: this.resolution, icon: "expand-arrows-alt" }); + funcs.push({ description: "Copy path", event: () => Utils.CopyText(this.choosePath(field.url)), icon: "expand-arrows-alt" }); if (!Doc.UserDoc().noviceMode) { funcs.push({ description: "Export to Google Photos", event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: "caret-square-right" }); - funcs.push({ description: "Copy path", event: () => Utils.CopyText(field.url.href), icon: "expand-arrows-alt" }); const existingAnalyze = ContextMenu.Instance?.findByDescription("Analyzers..."); const modes: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : []; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 9706d73c7..ce851b830 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -226,10 +226,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps specificContextMenu = (e: React.MouseEvent): void => { const funcs: ContextMenuProps[] = []; - funcs.push({ description: "Copy path", event: () => this.pdfUrl && Utils.CopyText(this.pdfUrl.url.pathname), icon: "expand-arrows-alt" }); - funcs.push({ description: "Toggle Fit Width " + (this.Document._fitWidth ? "Off" : "On"), event: () => this.Document._fitWidth = !this.Document._fitWidth, icon: "expand-arrows-alt" }); - funcs.push({ description: "Toggle Annotation View ", event: () => this.Document._showSidebar = !this.Document._showSidebar, icon: "expand-arrows-alt" }); - funcs.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); + funcs.push({ description: "Copy path", event: () => this.pdfUrl && Utils.CopyText(Utils.prepend("") + this.pdfUrl.url.pathname), icon: "expand-arrows-alt" }); + //funcs.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 7e46d8433..19135b6dd 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -69,13 +69,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps constructor(props: any) { super(props); - if (true) {// his.webField) { - Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(this.dataDoc) || 850); - Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(this.dataDoc) || this.Document[HeightSym]() / this.Document[WidthSym]() * 850); - } - if (this.layoutDoc[this.fieldKey + "-contentWidth"] === undefined) { - this.layoutDoc[this.fieldKey + "-contentWidth"] = Doc.NativeWidth(this.layoutDoc); - } + // if (true) {// his.webField) { + // Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(this.dataDoc) || 850); + // Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(this.dataDoc) || this.Document[HeightSym]() / this.Document[WidthSym]() * 850); + // } } async componentDidMount() { @@ -323,13 +320,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps if (future === undefined) this.dataDoc[this.fieldKey + "-future"] = new List<string>([this._url]); else this.dataDoc[this.fieldKey + "-future"] = new List<string>([...future, this._url]); this.dataDoc[this.fieldKey] = new WebField(new URL(history.pop()!)); + console.log(this._urlHash); return true; } return false; } static urlHash = (s: string) => { - return s.split('').reduce((a: any, b: any) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a; }, 0); + return Math.abs(s.split('').reduce((a: any, b: any) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a; }, 0)); } @action @@ -397,8 +395,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps const cm = ContextMenu.Instance; const funcs: ContextMenuProps[] = []; funcs.push({ description: (this.layoutDoc.useCors ? "Don't Use" : "Use") + " Cors", event: () => this.layoutDoc.useCors = !this.layoutDoc.useCors, icon: "snowflake" }); - funcs.push({ description: (this.layoutDoc[this.fieldKey + "-contentWidth"] ? "Unfreeze" : "Freeze") + " Content Width", event: () => this.layoutDoc[this.fieldKey + "-contentWidth"] = this.layoutDoc[this.fieldKey + "-contentWidth"] ? undefined : Doc.NativeWidth(this.layoutDoc), icon: "snowflake" }); - funcs.push({ description: "Toggle Annotation View ", event: () => this.Document._showSidebar = !this.Document._showSidebar, icon: "expand-arrows-alt" }); + funcs.push({ + description: (!this.layoutDoc.allowReflow ? "Allow" : "Prevent") + " Reflow", event: () => { + const nw = !this.layoutDoc.allowReflow ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this.props.scaling?.() || 1); + this.layoutDoc.allowReflow = !nw; + if (nw) { + Doc.SetInPlace(this.layoutDoc, this.fieldKey + "-nativeWidth", nw, true); + } + }, icon: "snowflake" + }); cm.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); } @@ -487,7 +492,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @computed get content() { return <div className={"webBox-cont" + (!this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.props.isContentActive() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")} - style={{ width: NumCast(this.layoutDoc[this.fieldKey + "-contentWidth"]) || `${100 / (this.props.scaling?.() || 1)}%`, }}> + style={{ width: !this.layoutDoc.allowReflow ? NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]) || `100%` : "100%", }}> {this.urlContent} </div>; } diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss index a2da35fe1..079c767b9 100644 --- a/src/client/views/nodes/button/FontIconBox.scss +++ b/src/client/views/nodes/button/FontIconBox.scss @@ -342,14 +342,18 @@ } &.editableText { - cursor: pointer; - background: transparent; + cursor: text; + display: flex; + flex-direction: row; + gap: 5px; + padding-left: 10px; + justify-content: flex-start; + color: black; + background-color: $light-gray; + padding: 5px; + padding-left: 10px; width: 100%; height: 100%; - - &:hover { - background-color: $close-red; - } } &.drpDownBtn { diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index b1d74261b..9d1ef937f 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -26,12 +26,10 @@ import { SetActiveInkColor, ActiveFillColor, SetActiveFillColor, ActiveInkWidth, import { StyleProp } from '../../StyleProvider'; import { FieldView, FieldViewProps } from '.././FieldView'; import { RichTextMenu } from '../formattedText/RichTextMenu'; -import { TextButton } from './textButton'; -import { ToggleButton } from './toggleButton'; +import { Utils } from '../../../../Utils'; import { IButtonProps } from './ButtonInterface'; import { FontIconBadge } from './FontIconBadge'; import './FontIconBox.scss'; -import { undo } from 'prosemirror-history'; import { WebBox } from '../WebBox'; const FontIconSchema = createSchema({ icon: "string", @@ -246,7 +244,6 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon let text: string | undefined; let dropdown = true; let icon: IconProp = "caret-down"; - let noneSelected: boolean = false; if (script === 'setView') { const selected = SelectionManager.Docs().lastElement(); @@ -301,7 +298,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon <div className={`menuButton ${this.type} ${active}`} style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : "flex" }} onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}> - {dropdown || noneSelected ? (null) : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />} + {dropdown ? (null) : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />} <div className="menuButton-dropdown-header"> {text && text[0].toUpperCase() + text.slice(1)} </div> @@ -334,23 +331,14 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon const scriptCheck: string = script + "(undefined, true)"; const boolResult = ScriptField.MakeScript(scriptCheck)?.script.run().result; - let stroke: boolean = false; - let strokeIcon: any; - // if (script === "setStrokeColor") { - // stroke = true; - // const checkWidth = ScriptField.MakeScript("setStrokeWidth(0, true)")?.script.run().result; - // const width = 20 + (checkWidth / 100) * 70; - // const height = 20 + (checkWidth / 100) * 70; - // strokeIcon = (<div style={{ borderRadius: "100%", width: width + '%', height: height + '%', backgroundColor: boolResult ? boolResult : "#FFFFFF" }} />); - // } - const colorOptions: string[] = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', "transparent"]; const colorBox = (func: (color: ColorState) => void) => <SketchPicker - disableAlpha={!stroke} - onChange={func} color={boolResult ? boolResult : "#FFFFFF"} + disableAlpha={false} + onChange={func} + color={boolResult ? boolResult : "#FFFFFF"} presetColors={colorOptions} />; const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}> @@ -364,21 +352,16 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon </div>; const click = (value: ColorState) => { - const hex: string = value.hex; - const s = ScriptField.MakeScript(script + '("' + hex + '", false)'); - if (s) { - undoBatch(() => s.script.run().result)(); - } + const s = ScriptField.MakeScript(script + '("' + Utils.colorString(value) + '", false)'); + s && undoBatch(() => s.script.run().result)(); }; return ( <div className={`menuButton ${this.type} ${active}`} style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }} onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen} onPointerDown={e => e.stopPropagation()}> - {stroke ? strokeIcon : <><FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} /> - <div className="colorButton-color" - style={{ backgroundColor: boolResult ? boolResult : "#FFFFFF" }} - ></div></>} + <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} /> + <div className="colorButton-color" style={{ backgroundColor: boolResult ? boolResult : "#FFFFFF" }} /> {label} {/* {dropdownCaret} */} {this.rootDoc.dropDownOpen ? @@ -499,7 +482,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon backgroundColor: backgroundColor, icon: this.icon, color: color - } + }; const buttonText = StrCast(this.rootDoc.buttonText); @@ -522,7 +505,6 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon // button = <TextButton {...buttonProps}></TextButton> break; case ButtonType.EditableText: - console.log("Editable text"); button = this.editableText; break; case ButtonType.NumberButton: @@ -592,7 +574,6 @@ Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: bo const selected = SelectionManager.Docs().lastElement(); if (checkResult) { if (selected) { - console.log("[Background] (selected): " + StrCast(selected._backgroundColor)); return selected._backgroundColor; } else { return "#FFFFFF"; @@ -605,6 +586,9 @@ Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: bo // toggle: Set overlay status of selected document Scripting.addGlobal(function setHeaderColor(color?: string, checkResult?: boolean) { + if (checkResult) { + return Doc.SharingDoc().userColor; + } Doc.SharingDoc().userColor = undefined; Doc.GetProto(Doc.SharingDoc()).userColor = color; Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate"); @@ -685,14 +669,12 @@ Scripting.addGlobal(function setBulletList(mapStyle: "bullet" | "decimal", check const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); - console.log(active, mapStyle); if (active === mapStyle) return Colors.MEDIUM_BLUE; else return "transparent"; } if (editorView) { const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle(); if (active === mapStyle) { - console.log("set bullet list"); editorView?.state && RichTextMenu.Instance.changeListType(editorView.state.schema.nodes.ordered_list.create({ mapStyle: "" })); } else { editorView?.state && RichTextMenu.Instance.changeListType(editorView.state.schema.nodes.ordered_list.create({ mapStyle: mapStyle })); @@ -707,10 +689,8 @@ Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) if (checkResult) { if (selected) { - console.log("[Font color] (selected): " + StrCast(selected._fontColor)); return selected._fontColor; } else { - console.log("[Font color] (global): " + StrCast(Doc.UserDoc()._fontColor)); return Doc.UserDoc()._fontColor; } } @@ -760,12 +740,16 @@ Scripting.addGlobal(function setFontSize(size: string, checkResult?: boolean) { Scripting.addGlobal(function toggleBold(checkResult?: boolean) { if (checkResult) { - if (Doc.UserDoc().bold) return Colors.MEDIUM_BLUE; + const editorView = RichTextMenu.Instance.TextView?.EditorView; + if (editorView) { + const bold: boolean = editorView?.state && RichTextMenu.Instance.getBoldStatus(); + if (bold) return Colors.MEDIUM_BLUE; + else return "transparent"; + } else return "transparent"; } const editorView = RichTextMenu.Instance.TextView?.EditorView; if (editorView) { - console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleBold(editorView, true); } SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.bold = !doc.bold); @@ -775,12 +759,10 @@ Scripting.addGlobal(function toggleBold(checkResult?: boolean) { Scripting.addGlobal(function toggleUnderline(checkResult?: boolean) { if (checkResult) { - if (Doc.UserDoc().underline) return Colors.MEDIUM_BLUE; - else return "transparent"; + return "transparent"; } const editorView = RichTextMenu.Instance.TextView?.EditorView; if (editorView) { - console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleUnderline(editorView, true); } SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.underline = !doc.underline); @@ -790,12 +772,10 @@ Scripting.addGlobal(function toggleUnderline(checkResult?: boolean) { Scripting.addGlobal(function toggleItalic(checkResult?: boolean) { if (checkResult) { - if (Doc.UserDoc().italic) return Colors.MEDIUM_BLUE; - else return "transparent"; + return "transparent"; } const editorView = RichTextMenu.Instance.TextView?.EditorView; if (editorView) { - console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleItalic(editorView, true); } SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.italic = !doc.italic); @@ -909,7 +889,6 @@ Scripting.addGlobal(function webBack() { **/ Scripting.addGlobal(function toggleSchemaPreview(checkResult?: boolean) { const selected = SelectionManager.Docs().lastElement(); - console.log(selected && selected.title); if (checkResult && selected) { const result: boolean = NumCast(selected.schemaPreviewWidth) > 0; if (result) return Colors.MEDIUM_BLUE; diff --git a/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx b/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx index 1809f4e2e..235495250 100644 --- a/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx +++ b/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx @@ -14,8 +14,7 @@ export class ColorDropdown extends Component<IButtonProps> { const scriptCheck: string = script + "(undefined, true)"; const boolResult = ScriptField.MakeScript(scriptCheck)?.script.run().result; - let stroke: boolean = false; - let strokeIcon: any; + const stroke: boolean = false; // if (script === "setStrokeColor") { // stroke = true; // const checkWidth = ScriptField.MakeScript("setStrokeWidth(0, true)")?.script.run().result; @@ -55,10 +54,9 @@ export class ColorDropdown extends Component<IButtonProps> { style={{ color: this.props.color, borderBottomLeftRadius: active ? 0 : undefined }} onClick={() => this.props.rootDoc.dropDownOpen = !this.props.rootDoc.dropDownOpen} onPointerDown={e => e.stopPropagation()}> - {stroke ? strokeIcon : <><FontAwesomeIcon className={`fontIconBox-icon-${this.props.type}`} icon={this.props.icon} color={this.props.color} /> - <div className="colorButton-color" - style={{ backgroundColor: boolResult ? boolResult : "#FFFFFF" }} - ></div></>} + <FontAwesomeIcon className={`fontIconBox-icon-${this.props.type}`} icon={this.props.icon} color={this.props.color} /> + <div className="colorButton-color" + style={{ backgroundColor: boolResult ? boolResult : "#FFFFFF" }} /> {label} {/* {dropdownCaret} */} {this.props.rootDoc.dropDownOpen ? diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 4134e3c67..27817f317 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -71,6 +71,7 @@ audiotag:hover { //top: calc(50% - 17.5px); // use this to center vertically -- make sure it looks okay for slide views width: 17px; height: 17px; + font-size: 11px; border-radius: 3px; color: white; background: $medium-gray; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index e7a44f113..acc2892d8 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -214,6 +214,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @action setupAnchorMenu = () => { AnchorMenu.Instance.Status = "marquee"; + + AnchorMenu.Instance.OnClick = (e: PointerEvent) => { + !this.layoutDoc.showSidebar && this.toggleSidebar(); + this._sidebarRef.current?.anchorMenuClick(this.getAnchor()); + }; AnchorMenu.Instance.Highlight = action((color: string, isLinkButton: boolean) => { this._editorView?.state && RichTextMenu.Instance.setHighlight(color, this._editorView, this._editorView?.dispatch); return undefined; @@ -818,11 +823,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._disposers.breakupDictation = reaction(() => DocumentManager.Instance.RecordingEvent, this.breakupDictation); this._disposers.autoHeight = reaction(() => this.autoHeight, autoHeight => autoHeight && this.tryUpdateScrollHeight()); this._disposers.scrollHeight = reaction(() => ({ scrollHeight: this.scrollHeight, autoHeight: this.autoHeight, width: NumCast(this.layoutDoc._width) }), - ({ width, scrollHeight, autoHeight }) => width && autoHeight && this.resetNativeHeight(scrollHeight) + ({ width, scrollHeight, autoHeight }) => { + width && autoHeight && this.resetNativeHeight(scrollHeight); + }, { fireImmediately: true } ); this._disposers.componentHeights = reaction( // set the document height when one of the component heights changes and autoHeight is on () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, autoHeight: this.autoHeight, marginsHeight: this.autoHeightMargins }), - ({ sidebarHeight, textHeight, autoHeight, marginsHeight }) => autoHeight && this.props.setHeight(marginsHeight + Math.max(sidebarHeight, textHeight))); + ({ sidebarHeight, textHeight, autoHeight, marginsHeight }) => { + autoHeight && this.props.setHeight(marginsHeight + Math.max(sidebarHeight, textHeight)); + }, { fireImmediately: true }); this._disposers.links = reaction(() => DocListCast(this.Document.links), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks newLinks => { this._cachedLinks.forEach(l => !newLinks.includes(l) && this.RemoveLinkFromDoc(l)); @@ -1156,7 +1165,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp selectOnLoad && this._editorView!.focus(); // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. if (this._editorView && !this._editorView.state.storedMarks?.some(mark => mark.type === schema.marks.user_mark)) { - this._editorView.state.storedMarks = [...(this._editorView!.state.storedMarks ?? []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })]; + this._editorView.state.storedMarks = [...(this._editorView.state.storedMarks ?? []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })]; } } diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 3919fbf94..86f2810ab 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -142,6 +142,18 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { } } + getBoldStatus() { + if (this.view && this.TextView.props.isSelected(true)) { + const path = (this.view.state.selection.$from as any).path; + for (let i = path.length - 3; i < path.length && i >= 0; i -= 3) { + if (path[i]?.type === this.view.state.schema.nodes.paragraph || path[i]?.type === this.view.state.schema.nodes.heading) { + console.log(path[i].attrs); + return path[i].attrs.strong; + } + } + } + } + // finds font sizes and families in selection getActiveAlignment() { if (this.view && this.TextView.props.isSelected(true)) { @@ -208,7 +220,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { const found = new Set<Mark>(); const { from, to } = state.selection as TextSelection; state.doc.nodesBetween(from, to, (node) => node.marks.forEach(m => found.add(m))); - console.log("Marks: " + found); return found; } @@ -590,7 +601,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { @undoBatch makeLinkToURL = (target: string, lcoation: string) => { ((this.view as any)?.TextView as FormattedTextBox).makeLinkAnchor(undefined, "onRadd:rightight", target, target); - console.log((this.view as any)?.TextView); } @undoBatch diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 1abe26c20..add84ff83 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -401,11 +401,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> LightboxView.SetLightboxDoc(targetDoc); } else if (curDoc.presMovement === PresMovement.Pan && targetDoc) { LightboxView.SetLightboxDoc(undefined); - await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection); // documents open in new tab instead of on right + await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true); // documents open in new tab instead of on right } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) { LightboxView.SetLightboxDoc(undefined); //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection); // documents open in new tab instead of on right + await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true); // documents open in new tab instead of on right } // After navigating to the document, if it is added as a presPinView then it will // adjust the pan and scale to that of the pinView when it was added. @@ -413,8 +413,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> // if targetDoc is not displayed but one of its aliases is, then we need to modify that alias, not the original target this.navigateToView(targetDoc, activeItem); } - // TODO: Add progressivize for navigating web (storing websites for given frames) - } /** @@ -1220,7 +1218,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <input className="presBox-input" type="number" value={duration} onChange={action((e) => this.setDurationTime(e.target.value))} /> s - </div> + </div> <div className="ribbon-propertyUpDown"> <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), 1000))}> <FontAwesomeIcon icon={"caret-up"} /> |
