From 264292f75d17c19e65bc4707b10a713b64510cf1 Mon Sep 17 00:00:00 2001 From: yunahi <60233430+yunahi@users.noreply.github.com> Date: Thu, 1 Oct 2020 18:41:45 +0900 Subject: fixed resize/rotate --- src/client/views/InkStrokeProperties.ts | 46 ++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'src/client/views/InkStrokeProperties.ts') diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index ad5c70fb1..b04ac8610 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -7,6 +7,8 @@ import { Cast, NumCast } from "../../fields/Types"; import { DocumentType } from "../documents/DocumentTypes"; import { SelectionManager } from "../util/SelectionManager"; import { undoBatch } from "../util/UndoManager"; +import { DocumentView } from "./nodes/DocumentView"; +import { returnVal } from "../../Utils"; export class InkStrokeProperties { static Instance: InkStrokeProperties | undefined; @@ -14,6 +16,7 @@ export class InkStrokeProperties { private _lastFill = "#D0021B"; private _lastLine = "#D0021B"; private _lastDash = "2"; + private _inkDocs: { x: number, y: number, width: number, height: number }[] = []; @observable _lock = false; @observable _controlBtn = false; @@ -190,12 +193,20 @@ export class InkStrokeProperties { doc._height = (bottom - top); doc._width = (right - left); + } index++; } })); } + @undoBatch + @action + resetPoints = () => { + + } + + @undoBatch @action control = (xDiff: number, yDiff: number, controlNum: number) => { @@ -218,31 +229,36 @@ export class InkStrokeProperties { (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2) || ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1)) ) { - newPoints.push({ X: ink[i].X - (xDiff * inkView.props.ScreenToLocalTransform().Scale), Y: ink[i].Y - (yDiff * inkView.props.ScreenToLocalTransform().Scale) }); + newPoints.push({ X: ink[i].X - (xDiff), Y: ink[i].Y - (yDiff) }); } else { newPoints.push({ X: ink[i].X, Y: ink[i].Y }); } } + const oldHeight = doc._height; + const oldWidth = doc._width; const oldx = doc.x; const oldy = doc.y; - const xs = ink.map(p => p.X); - const ys = ink.map(p => p.Y); - const left = Math.min(...xs); - const top = Math.min(...ys); + const oldxs = ink.map(p => p.X); + const oldys = ink.map(p => p.Y); + const oldleft = Math.min(...oldxs); + const oldtop = Math.min(...oldys); + const oldright = Math.max(...oldxs); + const oldbottom = Math.max(...oldys); Doc.GetProto(doc).data = new InkField(newPoints); - const xs2 = newPoints.map(p => p.X); - const ys2 = newPoints.map(p => p.Y); - const left2 = Math.min(...xs2); - const top2 = Math.min(...ys2); - const right2 = Math.max(...xs2); - const bottom2 = Math.max(...ys2); - doc._height = (bottom2 - top2); - doc._width = (right2 - left2); + const newxs = newPoints.map(p => p.X); + const newys = newPoints.map(p => p.Y); + const newleft = Math.min(...newxs); + const newtop = Math.min(...newys); + const newright = Math.max(...newxs); + const newbottom = Math.max(...newys); + //if points move out of bounds + doc._height = (newbottom - newtop) * inkView.props.ScreenToLocalTransform().Scale; + doc._width = (newright - newleft) * inkView.props.ScreenToLocalTransform().Scale; - doc.x = oldx - (left - left2); - doc.y = oldy - (top - top2); + doc.x = oldx - (oldleft - newleft) * inkView.props.ScreenToLocalTransform().Scale; + doc.y = oldy - (oldtop - newtop) * inkView.props.ScreenToLocalTransform().Scale; } } -- cgit v1.2.3-70-g09d2 From 7a1af910d1c4804cdc702000f8a278f5dd13999b Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 11 Jan 2021 13:21:48 -0500 Subject: cleanup of ink stroke changes --- src/client/views/DocumentDecorations.tsx | 8 ++++---- src/client/views/InkStrokeProperties.ts | 34 +++++++++++--------------------- 2 files changed, 16 insertions(+), 26 deletions(-) (limited to 'src/client/views/InkStrokeProperties.ts') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2f4126a1e..744683a0f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -271,10 +271,10 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b const right = Math.max(...xs); const bottom = Math.max(...ys); - doc._height = (bottom - top) * element.props.ScreenToLocalTransform().Scale; - doc._width = (right - left) * element.props.ScreenToLocalTransform().Scale; - // doc._height = (bottom - top); - // doc._width = (right - left); + // doc._height = (bottom - top) * element.props.ScreenToLocalTransform().Scale; + // doc._width = (right - left) * element.props.ScreenToLocalTransform().Scale; + doc._height = (bottom - top); + doc._width = (right - left); } diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index df0f354cd..73591c6a6 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -7,8 +7,6 @@ import { Cast, NumCast } from "../../fields/Types"; import { DocumentType } from "../documents/DocumentTypes"; import { SelectionManager } from "../util/SelectionManager"; import { undoBatch } from "../util/UndoManager"; -import { DocumentView } from "./nodes/DocumentView"; -import { returnVal } from "../../Utils"; export class InkStrokeProperties { static Instance: InkStrokeProperties | undefined; @@ -216,35 +214,28 @@ export class InkStrokeProperties { if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { const ink = Cast(doc.data, InkField)?.inkData; if (ink) { - const newPoints: { X: number, Y: number }[] = []; const order = controlNum % 4; for (var i = 0; i < ink.length; i++) { - if (controlNum === i || - (order === 0 && i === controlNum + 1) || - (order === 0 && controlNum !== 0 && i === controlNum - 2) || - (order === 0 && controlNum !== 0 && i === controlNum - 1) || - (order === 3 && i === controlNum - 1) || - (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 1) || - (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2) - || ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1)) - ) { - newPoints.push({ X: ink[i].X - (xDiff), Y: ink[i].Y - (yDiff) }); - } - else { - newPoints.push({ X: ink[i].X, Y: ink[i].Y }); - } + newPoints.push( + (controlNum === i || + (order === 0 && i === controlNum + 1) || + (order === 0 && controlNum !== 0 && i === controlNum - 2) || + (order === 0 && controlNum !== 0 && i === controlNum - 1) || + (order === 3 && i === controlNum - 1) || + (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 1) || + (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2) || + ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1)) + ) ? + { X: ink[i].X - xDiff, Y: ink[i].Y - yDiff } : + { X: ink[i].X, Y: ink[i].Y }) } - const oldHeight = doc._height; - const oldWidth = doc._width; const oldx = doc.x; const oldy = doc.y; const oldxs = ink.map(p => p.X); const oldys = ink.map(p => p.Y); const oldleft = Math.min(...oldxs); const oldtop = Math.min(...oldys); - const oldright = Math.max(...oldxs); - const oldbottom = Math.max(...oldys); Doc.GetProto(doc).data = new InkField(newPoints); const newxs = newPoints.map(p => p.X); const newys = newPoints.map(p => p.Y); @@ -259,7 +250,6 @@ export class InkStrokeProperties { doc.x = oldx - (oldleft - newleft) * inkView.props.ScreenToLocalTransform().Scale; doc.y = oldy - (oldtop - newtop) * inkView.props.ScreenToLocalTransform().Scale; - } } } -- cgit v1.2.3-70-g09d2 From a8545c5f31200d2d58696223c5050cbf9cf553ae Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 11 Jan 2021 13:35:56 -0500 Subject: from last --- src/client/views/InkStrokeProperties.ts | 8 -------- src/client/views/nodes/PresBox.tsx | 19 ++++--------------- 2 files changed, 4 insertions(+), 23 deletions(-) (limited to 'src/client/views/InkStrokeProperties.ts') diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index 73591c6a6..fcc6b9da0 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -191,20 +191,12 @@ export class InkStrokeProperties { doc._height = (bottom - top); doc._width = (right - left); - } index++; } })); } - @undoBatch - @action - resetPoints = () => { - - } - - @undoBatch @action control = (xDiff: number, yDiff: number, controlNum: number) => { diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index fb3598a04..271a7274f 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -774,33 +774,22 @@ export class PresBox extends ViewBoxBaseComponent if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0); else this.updateCurrentPresentation(context); - - if (this.targetDoc.isInkMask) { if (this.activeItem.y !== undefined && this.activeItem.x !== undefined && this.targetDoc.y !== undefined && this.targetDoc.y !== undefined) { const timer = (ms: number) => new Promise(res => this._presTimer = setTimeout(res, ms)); - - const ydiff = this.activeItem.y - this.targetDoc.y; - const xdiff = this.activeItem.x - this.targetDoc.x; - const time = 10; - - const yOffset = ydiff / time; - const xOffset = xdiff / time; + const ydiff = NumCast(this.activeItem.y) - NumCast(this.targetDoc.y); + const xdiff = NumCast(this.activeItem.x) - NumCast(this.targetDoc.x); for (let i = 0; i < time; i++) { - const newy = Number(this.targetDoc.y) + yOffset; - const newx = Number(this.targetDoc.x) + xOffset; - this.targetDoc.y = newy; - this.targetDoc.x = newx; + this.targetDoc.x = NumCast(this.targetDoc.x) + xdiff / time; + this.targetDoc.y = NumCast(this.targetDoc.y) + ydiff / time; await timer(0.1); } - } - } } -- cgit v1.2.3-70-g09d2 From ba3bcbbf3f0ce8769acb6e84ac3aa8ac3a5c9694 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 15 Jan 2021 15:27:16 -0500 Subject: fixed more issues with audio Box - simplified decorations when selected. fixed dragging when not selected. added esc to stop dragging. --- src/client/views/DocumentDecorations.tsx | 54 ++++++------ src/client/views/GlobalKeyHandler.ts | 4 + src/client/views/InkStrokeProperties.ts | 2 +- src/client/views/collections/TreeView.tsx | 5 +- src/client/views/nodes/AudioBox.scss | 1 - src/client/views/nodes/AudioBox.tsx | 140 +++++++++++------------------- src/client/views/nodes/DocumentView.tsx | 2 +- 7 files changed, 91 insertions(+), 117 deletions(-) (limited to 'src/client/views/InkStrokeProperties.ts') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index c2de78d09..e1b9fe8aa 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -569,7 +569,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b ); - const openIcon = !canOpen ? (null) : Open in Tab (ctrl: as alias, shift: in new collection)} placement="top">
{ e.preventDefault(); e.stopPropagation(); }} onPointerDown={this.onMaximizeDown}> + const openIcon = !canOpen ? (null) : Open in Tab (ctrl: as alias, shift: in new collection)
} placement="top">
{ e.preventDefault(); e.stopPropagation(); }} onPointerDown={this.onMaximizeDown}> {SelectionManager.Views().length === 1 ? : "..."}
; @@ -613,31 +613,35 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b }}> {closeIcon} {bounds.r - bounds.x < 100 ? null : titleArea} - {SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) : - {`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}} placement="top"> -
- -
-
} - {openIcon} -
e.preventDefault()} /> -
e.preventDefault()} /> -
e.preventDefault()} /> -
e.preventDefault()} /> -
-
e.preventDefault()} /> -
e.preventDefault()} /> -
e.preventDefault()} /> -
e.preventDefault()} /> - {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) : - tap to select containing document
} placement="top"> -
e.preventDefault()}> - -
} -
+ {SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) : + {`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}
} placement="top"> +
+ +
+ } + {openIcon} +
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> +
+
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> + + {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) : + tap to select containing document
} placement="top"> +
e.preventDefault()}> + +
} + + } +
e.preventDefault()}>{useRotation && "⟲"}
-
{seldoc?.Document.type === DocumentType.FONTICON ? (null) :
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index c38842c4f..8a07c5321 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -27,6 +27,7 @@ import { SnappingManager } from "../util/SnappingManager"; import { SearchBox } from "./search/SearchBox"; import { random } from "lodash"; import { DocumentView } from "./nodes/DocumentView"; +import { AudioBox } from "./nodes/AudioBox"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -121,6 +122,9 @@ export class KeyManager { DragManager.AbortDrag(); } else if (CollectionDockingView.Instance.HasFullScreen) { CollectionDockingView.Instance.CloseFullScreen(); + } else if (AudioBox.SelectingRegion) { + AudioBox.SelectingRegion = undefined; + doDeselect = false; } else { doDeselect = !ContextMenu.Instance.closeMenu(); } diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index fcc6b9da0..ce7f3d8d9 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -220,7 +220,7 @@ export class InkStrokeProperties { ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1)) ) ? { X: ink[i].X - xDiff, Y: ink[i].Y - yDiff } : - { X: ink[i].X, Y: ink[i].Y }) + { X: ink[i].X, Y: ink[i].Y }); } const oldx = doc.x; const oldy = doc.y; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index a61a9e43c..c4934cf45 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -379,7 +379,8 @@ export class TreeView extends React.Component { TraceMobx(); const expandKey = this.treeViewExpandedView; if (["links", "annotations", this.fieldKey].includes(expandKey)) { - const remDoc = (doc: Doc | Doc[]) => this.remove(doc, expandKey); + const key = expandKey === "annotations" ? this.fieldKey + "-annotations" : expandKey; + const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key); const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => { // if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't), // then the modification would be done here @@ -391,7 +392,7 @@ export class TreeView extends React.Component { docs.sort((a, b) => NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1); docs.forEach((d, i) => d.zIndex = i); } - const added = Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true); + const added = Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); added && (doc.context = this.doc.context); return added; }; diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index 36cc22d79..93cdbbb09 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -4,7 +4,6 @@ height: 100%; position: inherit; display: flex; - pointer-events: all; position: relative; cursor: default; diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 9f8bdcd57..c3c876b75 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -3,17 +3,17 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import axios from "axios"; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; +import { computedFn } from "mobx-utils"; import Waveform from "react-audio-waveform"; import { DateField } from "../../../fields/DateField"; import { Doc, DocListCast, Opt } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; -import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; import { createSchema, listSpec, makeInterface } from "../../../fields/Schema"; import { ComputedField, ScriptField } from "../../../fields/ScriptField"; -import { Cast, DateCast, NumCast } from "../../../fields/Types"; +import { Cast, NumCast } from "../../../fields/Types"; import { AudioField, nullAudio } from "../../../fields/URLField"; -import { emptyFunction, formatTime, numberRange, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils"; +import { emptyFunction, formatTime, numberRange, returnFalse, setupMoveUpEvents, Utils } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { Networking } from "../../Network"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; @@ -29,7 +29,6 @@ import { DocumentView } from "./DocumentView"; import { FieldView, FieldViewProps } from './FieldView'; import { FormattedTextBoxComment } from "./formattedText/FormattedTextBoxComment"; import { LinkDocPreview } from "./LinkDocPreview"; -import { computedFn } from "mobx-utils"; declare class MediaRecorder { // whatever MediaRecorder has @@ -47,7 +46,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent = []; _audioRef = React.createRef(); _timeline: Opt; - _duration = 0; _markerStart: number = 0; _currMarker: any; - @observable _selectRegionVisible: boolean = false; + @observable static SelectingRegion: AudioBox | undefined = undefined; + @observable static _scrubTime = 0; @observable _markerEnd: number = 0; @observable _position: number = 0; @observable _waveHeight: Opt = this.layoutDoc._height; - @observable private _paused: boolean = false; - @observable private static _scrubTime = 0; + @observable _paused: boolean = false; @computed get audioState(): undefined | "recording" | "paused" | "playing" { return this.dataDoc.audioState as (undefined | "recording" | "paused" | "playing"); } set audioState(value) { this.dataDoc.audioState = value; } public static SetScrubTime = action((timeInMillisFrom1970: number) => { AudioBox._scrubTime = 0; AudioBox._scrubTime = timeInMillisFrom1970; }); @computed get recordingStart() { return Cast(this.dataDoc[this.props.fieldKey + "-recordingStart"], DateField)?.date.getTime(); } @computed get audioDuration() { return NumCast(this.dataDoc.duration); } - async slideTemplate() { return (await Cast((await Cast(Doc.UserDoc().slidesBtn, Doc) as Doc).dragFactory, Doc) as Doc); } + @computed get markerDocs() { return DocListCast(this.dataDoc[this.annotationKey]); } + @computed get links() { return DocListCast(this.dataDoc.links); } + @computed get pauseTime() { return this._pauseEnd - this._pauseStart; } // total time paused to update the correct time constructor(props: Readonly) { super(props); @@ -103,7 +99,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent { - const time = this._ele?.currentTime || Cast(this.props.Document._currentTimecode, "number", null) || (this.audioState === "recording" ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined); - return time ? this.createMarker(time) : this.rootDoc; + return this.createMarker(this._ele?.currentTime || Cast(this.props.Document._currentTimecode, "number", null) || (this.audioState === "recording" ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined)); } @action componentDidMount() { - if (!this.dataDoc.markerAmount) { - this.dataDoc.markerAmount = 0; - } this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. this.audioState = this.path ? "paused" : undefined; @@ -156,7 +148,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent { - console.log(doc); this.links.filter(l => l.anchor1 === doc || l.anchor2 === doc).forEach(l => { const { la1, la2 } = this.getLinkData(l); const startTime = NumCast(la1.audioStart, NumCast(la2.audioStart, null)); @@ -165,9 +156,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent { clearTimeout(this._play); - this._duration = endTime - seekTimeInSeconds; if (Number.isNaN(this._ele?.duration)) { setTimeout(() => this.playFrom(seekTimeInSeconds, endTime), 500); } else if (this._ele && AudioBox.Enabled) { @@ -231,7 +219,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent this.audioState = "playing"); if (endTime !== this.audioDuration) { - this._play = setTimeout(() => this.pause(), (this._duration) * 1000); // use setTimeout to play a specific duration + this._play = setTimeout(() => this.pause(), (endTime - seekTimeInSeconds) * 1000); // use setTimeout to play a specific duration } } else { this.pause(); @@ -350,7 +338,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent { const rect = this._timeline?.getBoundingClientRect();// (e.target as any).getBoundingClientRect(); - if (rect && e.target !== this._audioRef.current) { + if (rect && e.target !== this._audioRef.current && this.active()) { const wasPaused = this.audioState === "paused"; this._ele!.currentTime = this.layoutDoc._currentTimecode = (e.clientX - rect.x) / rect.width * this.audioDuration; wasPaused && this.pause(); - this.props.select(false); const toTimeline = (screen_delta: number) => screen_delta / rect.width * this.audioDuration; this._markerStart = this._markerEnd = toTimeline(e.clientX - rect.x); + AudioBox.SelectingRegion = this; setupMoveUpEvents(this, e, action(e => { - this._selectRegionVisible = true; this._markerEnd = toTimeline(e.clientX - rect.x); if (this._markerEnd < this._markerStart) { const tmp = this._markerStart; @@ -392,16 +372,20 @@ export class AudioBox extends ViewBoxAnnotatableComponent { - (Math.abs(movement[0]) > 15) && this.createMarker(this._markerStart, toTimeline(e.clientX - rect.x)); - this._selectRegionVisible = false; + AudioBox.SelectingRegion === this && (Math.abs(movement[0]) > 15) && this.createMarker(this._markerStart, toTimeline(e.clientX - rect.x)); + AudioBox.SelectingRegion = undefined; }), - e => e.shiftKey && this.createMarker(this._ele!.currentTime) - ); + e => { + this.props.select(false); + e.shiftKey && this.createMarker(this._ele!.currentTime); + } + , this.props.isSelected(true) || this._isChildActive); } } @action - createMarker(audioStart: number, audioEnd?: number) { + createMarker(audioStart?: number, audioEnd?: number) { + if (audioStart === undefined) return this.rootDoc; const marker = Docs.Create.LabelDocument({ title: ComputedField.MakeFunction(`"#" + formatToTime(self.audioStart) + "-" + formatToTime(self.audioEnd)`) as any, useLinkSmallAnchor: true, hideLinkButton: true, audioStart, audioEnd, _showSidebar: false, @@ -448,56 +432,35 @@ export class AudioBox extends ViewBoxAnnotatableComponent { - const increment = this.audioDuration / AudioBox.NUMBER_OF_BUCKETS; - this._count = []; - for (let i = 0; i < AudioBox.NUMBER_OF_BUCKETS; i++) { - this._count.push([increment * i, 0]); - } - } - // makes sure no markers overlaps each other by setting the correct position and width - isOverlap = (m: any) => { - if (this._first) { - this._first = false; - this.markers(); - } - let max = 0; + getLevel = (m: any, placed: { audioStart: number, audioEnd: number, level: number }[]) => { const timelineContentWidth = this.props.PanelWidth() - AudioBox.playheadWidth; - const audioEnd = m.audioEnd === undefined ? m.audioStart + 10 / timelineContentWidth * this.audioDuration : m.audioEnd; - for (let i = 0; i < AudioBox.NUMBER_OF_BUCKETS; i++) { - if (this._count[i][0] >= m.audioStart && this._count[i][0] <= audioEnd) { - this._count[i][1]++; - - if (this._count[i][1] > max) { - max = this._count[i][1]; - } - } - } - - for (let i = 0; i < AudioBox.NUMBER_OF_BUCKETS; i++) { - if (this._count[i][0] >= m.audioStart && this._count[i][0] <= audioEnd) { - this._count[i][1] = max; + const x1 = m.audioStart; + const x2 = m.audioEnd === undefined ? m.audioStart + 10 / timelineContentWidth * this.audioDuration : m.audioEnd; + let max = 0; + const overlappedLevels = new Set(placed.map(p => { + const y1 = p.audioStart; + const y2 = p.audioEnd; + if ((x1 >= y1 && x1 <= y2) || (x2 >= y1 && x2 <= y2) || + (y1 >= x1 && y1 <= x2) || (y2 >= x1 && y2 <= x2)) { + max = Math.max(max, p.level); + return p.level; } - } + })); + let level = max + 1; + for (let j = max; j >= 0; j--) !overlappedLevels.has(j) && (level = j); - if (this.dataDoc.markerAmount < max) { - this.dataDoc.markerAmount = max; - } - return max - 1; + placed.push({ audioStart: x1, audioEnd: x2, level }); + return level; } @computed get selectionContainer() { - return !this._selectRegionVisible ? (null) :
; } - @computed get markerDocs() { return DocListCast(this.dataDoc[this.annotationKey]); } - @computed get links() { return DocListCast(this.dataDoc.links); } - // returns the audio waveform @computed get waveform() { const audioBuckets = Cast(this.dataDoc.audioBuckets, listSpec("number"), []); @@ -544,7 +507,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent this.props.ScreenToLocalTransform().translate(-x - 4, -y - 3)} - parentActive={returnTrue} + parentActive={(out) => this.props.isSelected(out) || this._isChildActive} + whenActiveChanged={action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive))} onClick={script} onDoubleClick={this.layoutDoc.playOnClick ? undefined : doublescript} ignoreAutoHeight={false} @@ -563,12 +527,14 @@ export class AudioBox extends ViewBoxAnnotatableComponent} ; }); + render() { const interactive = SnappingManager.GetIsDragging() || this.active() ? "-interactive" : ""; - this._first = true; // for indicating the first marker that is rendered - const timelineContentWidth = this.props.PanelWidth() - AudioBox.playheadWidth; const timelineContentHeight = (this.props.PanelHeight() * AudioBox.heightPercent / 100) * AudioBox.heightPercent / 100; // panelHeight * heightPercent is player height. * heightPercent is timeline height (as per css inline) + const overlaps: { audioStart: number, audioEnd: number, level: number }[] = []; + const drawMarkers = this.markerDocs.map((m, i) => ({ level: this.getLevel(m, overlaps), marker: m })); + const maxLevel = overlaps.reduce((m, o) => Math.max(m, o.level), 0) + 1; return
}
: -
+
@@ -603,20 +569,20 @@ export class AudioBox extends ViewBoxAnnotatableComponent {this.waveform}
- {this.markerDocs.map((m, i) => { - const isOverlap = this.isOverlap(m); + {drawMarkers.map((d, i) => { + const m = d.marker; const left = NumCast(m.audioStart) / this.audioDuration * timelineContentWidth; - const top = isOverlap / (this.dataDoc.markerAmount + 1) * timelineContentHeight; + const top = d.level / maxLevel * timelineContentHeight; const timespan = m.audioEnd === undefined ? 10 / timelineContentWidth * this.audioDuration : NumCast(m.audioEnd) - NumCast(m.audioStart); return this.layoutDoc.hideMarkers ? (null) :
{ this.playFrom(NumCast(m.audioStart), Cast(m.audioEnd, "number", null)); e.stopPropagation(); }} > {this.renderMarker(m, this.rangeClickScript, this.rangePlayScript, left + AudioBox.playheadWidth, (1 - AudioBox.heightPercent / 100) / 2 * this.props.PanelHeight() + top, timelineContentWidth * timespan / this.audioDuration, - timelineContentHeight / (this.dataDoc.markerAmount + 1))} + timelineContentHeight / maxLevel)}
; })} {this.selectionContainer} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 131e33e2a..6371ae5fb 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -416,7 +416,7 @@ export class DocumentViewInternal extends DocComponent { this._timeout = undefined; clickFunc(); }, 500); + this._timeout = setTimeout(() => { this._timeout = undefined; clickFunc(); }, 350); } else clickFunc(); } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself this.props.addDocTab(DocUtils.makeCustomViewClicked(Doc.MakeAlias(this.props.Document), undefined, "onClick"), "add:right"); -- cgit v1.2.3-70-g09d2