aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/CurrentUserUtils.ts4
-rw-r--r--src/client/util/LinkManager.ts6
-rw-r--r--src/client/views/LightboxView.tsx8
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx3
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx77
-rw-r--r--src/client/views/nodes/VideoBox.tsx4
-rw-r--r--src/fields/util.ts2
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();
}