From ae27dd1689ae1716591aab094e6d41f3a0160fef Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 4 Jan 2024 13:11:22 -0500 Subject: fixed ffmpeg for uploading videos. fixed getView() to take focus options so that if a sidebar or timeline has to be opened, the didMove flag can be set properly. added video snapshot frame to top menu. fixed using '^' to stop and start a selection region on timelines. --- src/client/views/GlobalKeyHandler.ts | 8 +- src/client/views/UndoStack.tsx | 10 +- .../views/collections/CollectionDockingView.tsx | 2 +- .../collections/CollectionStackedTimeline.tsx | 40 ++++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- .../collectionLinear/CollectionLinearView.tsx | 2 +- src/client/views/global/globalScripts.ts | 11 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 9 +- src/client/views/nodes/DocumentView.tsx | 9 +- src/client/views/nodes/MapBox/MapBox.tsx | 9 +- .../views/nodes/MapboxMapBox/MapboxContainer.tsx | 9 +- src/client/views/nodes/PDFBox.tsx | 7 +- src/client/views/nodes/VideoBox.scss | 6 +- src/client/views/nodes/VideoBox.tsx | 158 +++------------------ src/client/views/nodes/WebBox.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 7 +- 16 files changed, 101 insertions(+), 192 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 77b831e51..d134d9e7b 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -128,10 +128,12 @@ export class KeyManager { var doDeselect = true; if (SnappingManager.IsDragging) { DragManager.AbortDrag(); - } else if (CollectionDockingView.Instance?.HasFullScreen) { + } + if (CollectionDockingView.Instance?.HasFullScreen) { CollectionDockingView.Instance?.CloseFullScreen(); - } else if (CollectionStackedTimeline.SelectingRegion) { - CollectionStackedTimeline.SelectingRegion = undefined; + } + if (CollectionStackedTimeline.SelectingRegions.size) { + CollectionStackedTimeline.StopSelecting(); doDeselect = false; } else { doDeselect = !ContextMenu.Instance.closeMenu(); diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx index ea038250e..068143225 100644 --- a/src/client/views/UndoStack.tsx +++ b/src/client/views/UndoStack.tsx @@ -8,19 +8,13 @@ import { SettingsManager } from '../util/SettingsManager'; import { UndoManager } from '../util/UndoManager'; import './UndoStack.scss'; -interface UndoStackProps { - width?: number; - height?: number; - inline?: boolean; -} +interface UndoStackProps {} @observer export class UndoStack extends React.Component { - @observable static HideInline: boolean = false; - @observable static Expand: boolean = false; render() { const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userVariantColor; const color = UndoManager.batchCounter.get() ? 'black' : SettingsManager.userColor; - return this.props.inline && UndoStack.HideInline ? null : ( + return (
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index c46f54c70..874cdffd9 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -615,7 +615,7 @@ ScriptingGlobals.add( // prettier-ignore switch (doc) { case '': return OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' }); - case "": return OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' }); + case "": return OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: 'Undo stack' }); } Doc.AddToMyOverlay(doc); } diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index d99b4f9de..22a67c501 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -56,8 +56,11 @@ export enum TrimScope { @observer export class CollectionStackedTimeline extends CollectionSubView() { - @observable static SelectingRegion: CollectionStackedTimeline | undefined = undefined; - @observable public static CurrentlyPlaying: DocumentView[] = []; + public static SelectingRegions: Set = new Set(); + public static StopSelecting() { + this.SelectingRegions.forEach(action(region => (region._selectingRegion = false))); + this.SelectingRegions.clear(); + } constructor(props: any) { super(props); makeObservable(this); @@ -69,6 +72,8 @@ export class CollectionStackedTimeline extends CollectionSubView (CollectionStackedTimeline.SelectingRegion = undefined)); + if (this._selectingRegion) { + runInAction(() => (this._selectingRegion = false)); + CollectionStackedTimeline.SelectingRegions.delete(this); } } @@ -154,6 +160,15 @@ export class CollectionStackedTimeline extends CollectionSubView this.childDocList?.some(item => item === doc); + + getView = async (doc: Doc, options: DocFocusOptions): Promise> => + new Promise>(res => { + if (doc.hidden) options.didMove = !(doc.hidden = false); + const findDoc = (finish: (dv: DocumentView) => void) => DocumentManager.Instance.AddViewRenderedCb(doc, dv => finish(dv)); + findDoc(dv => res(dv)); + }); + anchorStart = (anchor: Doc) => NumCast(anchor._timecodeToShow, NumCast(anchor[this._props.startTag])); anchorEnd = (anchor: Doc, val: any = null) => NumCast(anchor._timecodeToHide, NumCast(anchor[this._props.endTag], val) ?? null); @@ -191,14 +206,16 @@ export class CollectionStackedTimeline extends CollectionSubView ({ - level: this.getLevel(anchor, overlaps), - anchor, + const drawAnchors = this.childLayoutPairs.map(pair => ({ + level: this.getLevel(pair.layout, overlaps), + anchor: pair.layout, })); const maxLevel = overlaps.reduce((m, o) => Math.max(m, o.level), 0) + 2; return this.clipDuration === 0 ? null : ( diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a3cedb9a0..8268a47d8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -321,9 +321,9 @@ export class CollectionFreeFormView extends CollectionSubView> => + getView = async (doc: Doc, options: DocFocusOptions): Promise> => new Promise>(res => { - if (doc.hidden && this._lightboxDoc !== doc) doc.hidden = false; + if (doc.hidden && this._lightboxDoc !== doc) options.didMove = !(doc.hidden = false); const findDoc = (finish: (dv: DocumentView) => void) => DocumentManager.Instance.AddViewRenderedCb(doc, dv => finish(dv)); findDoc(dv => res(dv)); }); diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index f1fb68003..d105b04f7 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -147,7 +147,7 @@ export class CollectionLinearView extends CollectionSubView() { switch (doc.layout) { case '': return this.getLinkUI(); case '': return this.getCurrentlyPlayingUI(); - case '': return ; + case '': return ; case '': return Doc.UserDoc().isBranchingMode ? : null; } diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 989dd1db0..e57ef4871 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -19,6 +19,7 @@ import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocum import { DocumentView } from '../nodes/DocumentView'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; import { WebBox } from '../nodes/WebBox'; +import { VideoBox } from '../nodes/VideoBox'; ScriptingGlobals.add(function IsNoneSelected() { return SelectionManager.Views.length <= 0; @@ -390,14 +391,16 @@ ScriptingGlobals.add(function webForward(checkResult?: boolean) { } selected?.forward(); }); -ScriptingGlobals.add(function webBack(checkResult?: boolean) { +ScriptingGlobals.add(function webBack() { const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox; - if (checkResult) { - return selected?.back(checkResult) ? undefined : 'lightGray'; - } selected?.back(); }); +ScriptingGlobals.add(function videoSnapshot() { + const selected = SelectionManager.Views.lastElement()?.ComponentView as VideoBox; + selected?.Snapshot(); +}); + /** Schema * toggleSchemaPreview **/ diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 76cc010f6..5a55ca764 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -20,7 +20,7 @@ import { SidebarAnnos } from '../../SidebarAnnos'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { AnchorMenu } from '../../pdf/AnchorMenu'; import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup'; -import { DocumentView } from '../DocumentView'; +import { DocFocusOptions, DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { PinProps } from '../trails'; import './DataVizBox.scss'; @@ -228,8 +228,11 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { () => UndoManager.RunInBatch(this.toggleSidebar, 'toggle sidebar') ); }; - getView = async (doc: Doc) => { - if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(); + getView = async (doc: Doc, options: DocFocusOptions) => { + if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) { + options.didMove = true; + this.toggleSidebar(); + } return new Promise>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); }; @computed get sidebarWidthPercent() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7f1e547e4..6cc61ec62 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -43,7 +43,6 @@ import { GestureOverlay } from '../GestureOverlay'; import { LightboxView } from '../LightboxView'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { StyleProp } from '../StyleProvider'; -import { UndoStack } from '../UndoStack'; import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; import { DocumentContentsView, ObserverJsxParser } from './DocumentContentsView'; import { DocumentLinksButton } from './DocumentLinksButton'; @@ -119,7 +118,7 @@ export interface DocComponentView { restoreView?: (viewSpec: Doc) => boolean; scrollPreview?: (docView: DocumentView, doc: Doc, focusSpeed: number, options: DocFocusOptions) => Opt; // returns the duration of the focus brushView?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number, holdTime: number) => void; // highlight a region of a view (used by freeforms) - getView?: (doc: Doc) => Promise>; // returns a nested DocumentView for the specified doc or undefined + getView?: (doc: Doc, options: DocFocusOptions) => Promise>; // returns a nested DocumentView for the specified doc or undefined addDocTab?: (doc: Doc, where: OpenWhere) => boolean; // determines how to add a document - used in following links to open the target ina local lightbox addDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; // add a document (used only by collections) select?: (ctrlKey: boolean, shiftKey: boolean) => void; @@ -520,11 +519,7 @@ export class DocumentViewInternal extends DocComponent { if (DocumentView.LongPress) { - if (this.Document.undoIgnoreFields) { - runInAction(() => (UndoStack.HideInline = !UndoStack.HideInline)); - } else { - this._props.select(false); - } + this._props.select(false); } }, 1000); if (!GestureOverlay.DownDocView) GestureOverlay.DownDocView = this._props.DocumentView(); diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 41befbbfe..3575b21e4 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -27,7 +27,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocC import { SidebarAnnos } from '../../SidebarAnnos'; import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; import { Colors } from '../../global/globalEnums'; -import { DocumentView } from '../DocumentView'; +import { DocFocusOptions, DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; import { PinProps, PresBox } from '../trails'; @@ -504,8 +504,11 @@ export class MapBox extends ViewBoxAnnotatableComponent { - if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(); + getView = async (doc: Doc, options: DocFocusOptions) => { + if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) { + this.toggleSidebar(); + options.didMove = true; + } return new Promise>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); }; /* diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx index 8b22a1531..ea8496c99 100644 --- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx +++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx @@ -20,7 +20,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocC import { SidebarAnnos } from '../../SidebarAnnos'; import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; import { Colors } from '../../global/globalEnums'; -import { DocumentView } from '../DocumentView'; +import { DocFocusOptions, DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { MapAnchorMenu } from '../MapBox/MapAnchorMenu'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; @@ -374,8 +374,11 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent { - if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(); + getView = async (doc: Doc, options: DocFocusOptions) => { + if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) { + this.toggleSidebar(); + options.didMove = true; + } return new Promise>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); }; /* diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 55a459a5c..959d5d88d 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -224,8 +224,11 @@ export class PDFBox extends ViewBoxAnnotatableComponent { - if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false); + getView = async (doc: Doc, options: DocFocusOptions) => { + if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) { + options.didMove = true; + this.toggleSidebar(false); + } return new Promise>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); }; diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss index ae923ad60..460155446 100644 --- a/src/client/views/nodes/VideoBox.scss +++ b/src/client/views/nodes/VideoBox.scss @@ -180,9 +180,9 @@ } } -video::-webkit-media-controls { - display: none !important; -} +// video::-webkit-media-controls { +// display: none !important; +// } input[type='range'] { -webkit-appearance: none; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index ce73d9f37..fb42286af 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -1,9 +1,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction, untracked } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { basename } from 'path'; import * as React from 'react'; -import { Doc, StrListCast } from '../../../fields/Doc'; +import { Doc, Opt, StrListCast } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; @@ -12,23 +12,20 @@ import { AudioField, ImageField, VideoField } from '../../../fields/URLField'; import { emptyFunction, formatTime, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; -import { Networking } from '../../Network'; import { DocumentManager } from '../../util/DocumentManager'; import { FollowLinkScript } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { ReplayMovements } from '../../util/ReplayMovements'; -import { SelectionManager } from '../../util/SelectionManager'; -import { SnappingManager } from '../../util/SnappingManager'; import { undoBatch } from '../../util/UndoManager'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { StyleProp } from '../StyleProvider'; -import { DocFocusOptions, DocumentView, OpenWhere } from './DocumentView'; +import { DocFocusOptions, DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { RecordingBox } from './RecordingBox'; import { PinProps, PresBox } from './trails'; @@ -40,7 +37,7 @@ import './VideoBox.scss'; * Supporting Components: CollectionStackedTimeline * * VideoBox is a node that supports the playback of video files in Dash. - * When a video file or YouTube video is importeed into Dash, it is immediately rendered as a VideoBox document. + * When a video file is importeed into Dash, it is immediately rendered as a VideoBox document. * CollectionStackedTimline handles AudioBox and VideoBox shared behavior, but VideoBox handles playing, pausing, etc because it contains