diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 4 | ||||
-rw-r--r-- | src/client/util/LinkManager.ts | 6 | ||||
-rw-r--r-- | src/client/views/LightboxView.tsx | 8 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackedTimeline.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/ScreenshotBox.tsx | 77 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 4 | ||||
-rw-r--r-- | src/fields/util.ts | 2 |
7 files changed, 70 insertions, 34 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 05e560f51..0fb32970a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -423,7 +423,7 @@ export class CurrentUserUtils { ((doc.emptyScript as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptyScreenshot === undefined) { - doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List<string>(["system"]) }); + doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _fitWidth: true, _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List<string>(["system"]) }); } if (doc.emptyAudio === undefined) { doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "audio recording", system: true, cloneFieldFilter: new List<string>(["system"]) }); @@ -453,7 +453,7 @@ export class CurrentUserUtils { { toolTip: "Tap to create a progressive slide", title: "Slide", icon: "file", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySlide as Doc, noviceMode: true }, { toolTip: "Tap to create a cat image in a new pane, drag for a cat image", title: "Image", icon: "cat", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyImage as Doc }, { toolTip: "Tap to create a comparison box in a new pane, drag for a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyComparison as Doc, noviceMode: true }, - { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc }, + { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc, noviceMode: true }, { toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true }, { toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc }, { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory))', drag: `Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true }, diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index bd27c9e56..159011516 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -135,14 +135,14 @@ export class LinkManager { // follows a link - if the target is on screen, it highlights/pans to it. - // if the target isn't onscreen, then it will open up the target in a tab, on the right, or in place + // if the target isn't onscreen, then it will open up the target in the lightbox, or in place // depending on the followLinkLocation property of the source (or the link itself as a fallback); public static FollowLink = (linkDoc: Opt<Doc>, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean, zoom: boolean = false) => { const batch = UndoManager.StartBatch("follow link click"); // open up target if it's not already in view ... const createViewFunc = (doc: Doc, followLoc: string, finished?: Opt<() => void>) => { const createTabForTarget = (didFocus: boolean) => new Promise<ViewAdjustment>(res => { - const where = LightboxView.LightboxDoc ? "lightbox" : StrCast(sourceDoc.followLinkLocation) || followLoc; + const where = LightboxView.LightboxDoc ? "lightbox" : StrCast(sourceDoc.followLinkLocation, followLoc); docViewProps.addDocTab(doc, where); setTimeout(() => { const targDocView = DocumentManager.Instance.getFirstDocumentView(doc); @@ -195,7 +195,7 @@ export class LinkManager { const containerDoc = Cast(target.annotationOn, Doc, null) || target; const targetContext = Cast(containerDoc?.context, Doc, null); const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; - DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished); + DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "lightbox"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished); } } else { finished?.(); diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 5715b62b0..84738112f 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -114,11 +114,11 @@ export class LightboxView extends React.Component<LightboxViewProps> { @action public static Next() { const doc = LightboxView._doc!; const target = LightboxView._docTarget = LightboxView._future?.pop(); - const docView = target && DocumentManager.Instance.getLightboxDocumentView(target); - if (docView && target) { - const l = DocUtils.MakeLinkToActiveAudio(target); + const targetDocView = target && DocumentManager.Instance.getLightboxDocumentView(target); + if (targetDocView && target) { + const l = DocUtils.MakeLinkToActiveAudio(targetDocView.ComponentView?.getAnchor?.() || target); l && (Cast(l.anchor2, Doc, null).backgroundColor = "lightgreen"); - docView.focus(target, { originalTarget: target, willZoom: true, scale: 0.9 }); + targetDocView.focus(target, { originalTarget: target, willZoom: true, scale: 0.9 }); if (LightboxView._history?.lastElement().target !== target) LightboxView._history?.push({ doc, target }); } else { if (!target && LightboxView.path.length) { diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index de75a3c4a..db02ab986 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -19,6 +19,7 @@ import "./CollectionStackedTimeline.scss"; import { Transform } from "../../util/Transform"; import { LinkManager } from "../../util/LinkManager"; import { computedFn } from "mobx-utils"; +import { LightboxView } from "../LightboxView"; type PanZoomDocument = makeInterface<[]>; const PanZoomDocument = makeInterface(); @@ -306,7 +307,7 @@ class StackedTimelineAnchor extends React.Component<StackedTinelineAnchorProps> componentDidMount() { this._disposer = reaction(() => this.props.currentTimecode(), (time) => { - if (DocListCast(this.props.mark.links).length && + if (!LightboxView.LightboxDoc && DocListCast(this.props.mark.links).length && time > NumCast(this.props.mark[this.props.startTag]) && time < NumCast(this.props.mark[this.props.endTag]) && this._lastTimecode < NumCast(this.props.mark[this.props.startTag])) { diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index dba730d12..d1da2fcd5 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -24,6 +24,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import "./ScreenshotBox.scss"; import { VideoBox } from "./VideoBox"; import { TraceMobx } from "../../../fields/util"; +import { FormattedTextBox } from "./formattedText/FormattedTextBox"; declare class MediaRecorder { constructor(e: any, options?: any); // whatever MediaRecorder has } @@ -40,6 +41,10 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S @observable _screenCapture = false; @computed get recordingStart() { return Cast(this.dataDoc[this.props.fieldKey + "-recordingStart"], DateField)?.date.getTime(); } + constructor(props: any) { + super(props); + this.setupDictation(); + } getAnchor = () => { const startTime = Cast(this.layoutDoc._currentTimecode, "number", null) || (this._videoRec ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined); return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, "_timecodeToShow", "_timecodeToHide", @@ -59,6 +64,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S } componentDidMount() { + this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = 0; this.props.setContentView?.(this); // this tells the DocumentView that this ScreenshotBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. } componentWillUnmount() { @@ -108,10 +114,12 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox this.dataDoc.type = DocumentType.VID; this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey); + this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined; + this.layoutDoc._fitWidth = undefined; this.dataDoc[this.props.fieldKey] = new VideoField(Utils.prepend(result.accessPaths.agnostic.client)); + this.props.addDocTab?.(Cast(this.dataDoc[this.fieldKey + "-dictation"], Doc, null), "add:bottom"); } else alert("video conversion failed"); }; - this.setupDictation(); this._audioRec.start(); this._videoRec.start(); this.dataDoc.mediaState = "recording"; @@ -126,6 +134,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S }); setupDictation = () => { + if (this.dataDoc[this.fieldKey + "-dictation"]) return; const dictationText = CurrentUserUtils.GetNewTextDoc("", NumCast(this.rootDoc.x), NumCast(this.rootDoc.y) + NumCast(this.layoutDoc._height) + 10, NumCast(this.layoutDoc._width), 2 * NumCast(this.layoutDoc._height)); @@ -133,32 +142,58 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S dictationTextProto.recordingSource = this.dataDoc; dictationTextProto.recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.props.fieldKey}-recordingStart"]`); dictationTextProto.mediaState = ComputedField.MakeFunction("self.recordingSource.mediaState"); - this.props.addDocument?.(dictationText) || this.props.addDocTab(dictationText, "add:bottom"); + this.dataDoc[this.fieldKey + "-dictation"] = dictationText; } contentFunc = () => [this.content]; + videoPanelHeight = () => NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"], 1) / NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"], 1) * this.props.PanelWidth(); + formattedPanelHeight = () => Math.max(0, this.props.PanelHeight() - this.videoPanelHeight()) render() { TraceMobx(); return <div className="videoBox" onContextMenu={this.specificContextMenu} style={{ width: "100%", height: "100%" }} > <div className="videoBox-viewer" > - <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} - PanelHeight={this.props.PanelHeight} - PanelWidth={this.props.PanelWidth} - focus={this.props.focus} - isSelected={this.props.isSelected} - isAnnotationOverlay={true} - select={emptyFunction} - active={returnFalse} - scaling={returnOne} - whenActiveChanged={emptyFunction} - removeDocument={returnFalse} - moveDocument={returnFalse} - addDocument={returnFalse} - CollectionView={undefined} - ScreenToLocalTransform={this.props.ScreenToLocalTransform} - renderDepth={this.props.renderDepth + 1} - ContainingCollectionDoc={this.props.ContainingCollectionDoc}> - {this.contentFunc} - </CollectionFreeFormView> + <div style={{ position: "relative", height: this.videoPanelHeight() }}> + <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} + PanelHeight={this.videoPanelHeight} + PanelWidth={this.props.PanelWidth} + focus={this.props.focus} + isSelected={this.props.isSelected} + isAnnotationOverlay={true} + select={emptyFunction} + active={returnFalse} + scaling={returnOne} + whenActiveChanged={emptyFunction} + removeDocument={returnFalse} + moveDocument={returnFalse} + addDocument={returnFalse} + CollectionView={undefined} + ScreenToLocalTransform={this.props.ScreenToLocalTransform} + renderDepth={this.props.renderDepth + 1} + ContainingCollectionDoc={this.props.ContainingCollectionDoc}> + {this.contentFunc} + </CollectionFreeFormView></div> + <div style={{ position: "relative", height: this.formattedPanelHeight() }}> + <FormattedTextBox {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} + Document={this.dataDoc[this.fieldKey + "-dictation"]} + fieldKey={"text"} + PanelHeight={this.formattedPanelHeight} + PanelWidth={this.props.PanelWidth} + focus={this.props.focus} + isSelected={this.props.isSelected} + isAnnotationOverlay={true} + select={emptyFunction} + active={returnFalse} + scaling={returnOne} + xMargin={25} + yMargin={10} + whenActiveChanged={emptyFunction} + removeDocument={returnFalse} + moveDocument={returnFalse} + addDocument={returnFalse} + CollectionView={undefined} + ScreenToLocalTransform={this.props.ScreenToLocalTransform} + renderDepth={this.props.renderDepth + 1} + ContainingCollectionDoc={this.props.ContainingCollectionDoc}> + </FormattedTextBox></div> </div> {!this.props.isSelected() ? (null) : <div className="screenshotBox-uiButtons"> <div className="screenshotBox-recorder" key="snap" onPointerDown={this.toggleRecording} > diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 5a60f9312..4e03589d6 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -182,7 +182,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD private createRealSummaryLink = (relative: string) => { const url = this.choosePath(Utils.prepend(relative)); - const width = this.layoutDoc._width || 0; + const width = this.layoutDoc._width || 1; const height = this.layoutDoc._height || 0; const imageSummary = Docs.Create.ImageDocument(url, { _nativeWidth: Doc.NativeWidth(this.layoutDoc), _nativeHeight: Doc.NativeHeight(this.layoutDoc), @@ -548,7 +548,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD contentFunc = () => [this.youtubeVideoId ? this.youtubeContent : this.content]; scaling = () => this.props.scaling?.() || 1; panelWidth = () => this.props.PanelWidth() * this.heightPercent / 100; - panelHeight = () => this.layoutDoc._fitWidth ? this.panelWidth() / Doc.NativeAspect(this.rootDoc) : this.props.PanelHeight() * this.heightPercent / 100; + panelHeight = () => this.layoutDoc._fitWidth ? this.panelWidth() / (Doc.NativeAspect(this.rootDoc) || 1) : this.props.PanelHeight() * this.heightPercent / 100; screenToLocalTransform = () => { const offset = (this.props.PanelWidth() - this.panelWidth()) / 2 / this.scaling(); return this.props.ScreenToLocalTransform().translate(-offset, 0).scale(100 / this.heightPercent); diff --git a/src/fields/util.ts b/src/fields/util.ts index 6c9c9d45c..ea91cc057 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -19,7 +19,7 @@ function _readOnlySetter(): never { throw new Error("Documents can't be modified in read-only mode"); } -const tracing = true; +const tracing = false; export function TraceMobx() { tracing && trace(); } |