aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx27
-rw-r--r--src/client/views/nodes/VideoBox.tsx17
2 files changed, 38 insertions, 6 deletions
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index b29abf083..c694e17fb 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -2,7 +2,7 @@ import React = require('react');
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
-import { Doc, DocListCast, StrListCast } from '../../../fields/Doc';
+import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
@@ -23,11 +23,13 @@ import { AudioWaveform } from '../AudioWaveform';
import { CollectionSubView } from '../collections/CollectionSubView';
import { Colors } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
-import { DocAfterFocusFunc, DocFocusFunc, DocumentView, DocumentViewProps } from '../nodes/DocumentView';
+import { DocAfterFocusFunc, DocFocusFunc, DocumentView, DocumentViewProps, DocumentViewSharedProps } from '../nodes/DocumentView';
import { LabelBox } from '../nodes/LabelBox';
import './CollectionStackedTimeline.scss';
import { VideoBox } from '../nodes/VideoBox';
import { ImageField } from '../../../fields/URLField';
+import { StyleProp } from '../StyleProvider';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
export type CollectionStackedTimelineProps = {
Play: () => void;
@@ -693,6 +695,7 @@ interface StackedTimelineAnchorProps {
width: number;
height: number;
toTimeline: (screen_delta: number, width: number) => number;
+ styleProvider?: (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => any;
playLink: (linkDoc: Doc) => void;
setTime: (time: number) => void;
startTag: string;
@@ -803,6 +806,25 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
return [resetTitle];
};
+ innerStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
+ if (property === StyleProp.Decorations && doc && NumCast(doc.timecodeToHide) - NumCast(doc.timecodeToShow) < 0.0002) {
+ return (
+ <div className="styleProvider-lock">
+ <FontAwesomeIcon
+ icon={'camera'}
+ style={{ color: 'red' }}
+ onClick={e => {
+ LinkFollower.FollowLink(undefined, doc, props as DocumentViewSharedProps, e.altKey);
+ e.stopPropagation();
+ }}
+ size="lg"
+ />
+ </div>
+ );
+ }
+ return this.props.styleProvider?.(doc, props, property);
+ };
+
// renders anchor LabelBox
renderInner = computedFn(function (this: StackedTimelineAnchor, mark: Doc, script: undefined | (() => ScriptField), doublescript: undefined | (() => ScriptField), screenXf: () => Transform, width: () => number, height: () => number) {
const anchor = observable({ view: undefined as any });
@@ -819,6 +841,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
ref={action((r: DocumentView | null) => (anchor.view = r))}
Document={mark}
DataDoc={undefined}
+ styleProvider={this.innerStyleProvider}
renderDepth={this.props.renderDepth + 1}
LayoutTemplate={undefined}
LayoutTemplateString={LabelBox.LayoutStringWithTitle('data', this.computeTitle())}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index aabe3eb25..4bcd79641 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -948,6 +948,14 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
);
};
+ scrollFocus = (doc: Doc, smooth: boolean) => {
+ if (doc !== this.rootDoc) {
+ const showTime = Cast(doc._timecodeToShow, 'number', null);
+ showTime !== undefined && setTimeout(() => this.Seek(showTime), 100);
+ return 0.1;
+ }
+ };
+
// renders CollectionStackedTimeline
@computed get renderTimeline() {
return (
@@ -981,15 +989,15 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
</div>
);
}
+ @computed get isCropped() {
+ return this.dataDoc.videoCrop; // bcz: hack to identify a cropped video
+ }
// renders annotation layer
@computed get annotationLayer() {
return <div className="videoBox-annotationLayer" style={{ transition: this.transition, height: `${this.heightPercent}%` }} ref={this._annotationLayer} />;
}
- @computed get isCropped() {
- return this.dataDoc.viewScaleMin; // bcz: hack to identify a cropped video
- }
crop = (region: Doc | undefined, addCrop?: boolean) => {
if (!region) return;
const cropping = Doc.MakeCopy(region, true);
@@ -997,7 +1005,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
Doc.GetProto(region).lockedPosition = true;
Doc.GetProto(region).title = 'region:' + this.rootDoc.title;
Doc.GetProto(region).isPushpin = true;
- region._timecodeToHide = region._timecodeToShow;
+ region._timecodeToHide = NumCast(region._timecodeToShow) + 0.0001;
this.addDocument(region);
const anchx = NumCast(cropping.x);
const anchy = NumCast(cropping.y);
@@ -1021,6 +1029,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
croppingProto.data = ObjectField.MakeCopy(this.rootDoc[this.fieldKey] as ObjectField);
croppingProto['data-nativeWidth'] = anchw;
croppingProto['data-nativeHeight'] = anchh;
+ croppingProto.videoCrop = true;
croppingProto.currentTimecode = this.layoutDoc._currentTimecode;
croppingProto.viewScale = viewScale;
croppingProto.viewScaleMin = viewScale;