aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts2
-rw-r--r--src/client/views/nodes/AudioBox.scss1
-rw-r--r--src/client/views/nodes/AudioBox.tsx113
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx124
4 files changed, 172 insertions, 68 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 88f470576..402f3e82c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -628,7 +628,7 @@ export namespace Docs {
}
export function AudioDocument(url: string, options: DocumentOptions = {}) {
- const instance = InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(new URL(url)), { ...options }); // hideLinkButton: false, useLinkSmallAnchor: false,
+ const instance = InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(new URL(url)), { useLinkSmallAnchor: true, ...options }); // hideLinkButton: false, useLinkSmallAnchor: false,
Doc.GetProto(instance).backgroundColor = ComputedField.MakeFunction("this._audioState === 'playing' ? 'green':'gray'");
return instance;
}
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss
index 35ab5da8b..0ea4b37cb 100644
--- a/src/client/views/nodes/AudioBox.scss
+++ b/src/client/views/nodes/AudioBox.scss
@@ -148,6 +148,7 @@
width: 100%;
height: 100%;
overflow: hidden;
+ z-index: 0;
}
.audiobox-linker,
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 3d1932883..7c90547ef 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -75,6 +75,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
_markers: Array<any> = [];
_first: boolean = false;
_buckets: Array<number> = new Array();
+ _count: Array<any> = [];
private _isPointerDown = false;
private _currMarker: any;
@@ -516,53 +517,74 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
return false;
}
+ markers = () => {
+ const increment = NumCast(this.layoutDoc.duration) / 500;
+ this._count = [];
+ for (let i = 0; i < 500; i++) {
+ this._count.push([increment * i, 0])
+ }
+
+ }
+
// Probably need a better way to format
- isOverlap = (m: any, i: number) => {
- console.log("called");
- let counter = 0;
+ // isOverlap = (m: any, i: number) => {
+ // console.log("called");
+ // let counter = 0;
+ // if (this._first) {
+ // this._markers = [];
+ // this._first = false;
+ // }
+ // for (let i = 0; i < this._markers.length; i++) {
+ // if ((m.audioEnd > this._markers[i].audioStart && m.audioStart < this._markers[i].audioEnd)) {
+ // counter++;
+ // console.log(counter);
+ // }
+ // }
+
+ // if (this.dataDoc.markerAmount < counter) {
+ // this.dataDoc.markerAmount = counter;
+ // }
+
+ // this._markers.push(m);
+
+ // return counter;
+ // }
+
+ isOverlap = (m: any) => {
if (this._first) {
- this._markers = [];
this._first = false;
- }
- for (let i = 0; i < this._markers.length; i++) {
- if ((m.audioEnd > this._markers[i].audioStart && m.audioStart < this._markers[i].audioEnd)) {
- counter++;
- console.log(counter);
- }
+ this.markers();
+ console.log(this._count);
}
- if (this.dataDoc.markerAmount < counter) {
- this.dataDoc.markerAmount = counter;
- }
- this._markers.push(m);
+ let max = 0
- return counter;
- }
+ for (let i = 0; i < 500; i++) {
+ if (this._count[i][0] >= m.audioStart && this._count[i][0] <= m.audioEnd) {
+ this._count[i][1]++;
- // isOverlap = (m: any) => {
- // if (this._markers.length < 1) {
- // this._markers = new Array(Math.round(this.dataDoc.duration)).fill(0);
- // }
- // console.log(this._markers);
- // let max = 0
+ if (this._count[i][1] > max) {
+ max = this._count[i][1];
+ }
+ }
- // for (let i = Math.round(m.audioStart); i <= Math.round(m.audioEnd); i++) {
- // this._markers[i] = this._markers[i] + 1;
- // console.log(this._markers[i]);
- // if (this._markers[i] > max) {
- // max = this._markers[i];
- // }
- // }
+ }
- // console.log(max);
- // if (this.dataDoc.markerAmount < max) {
- // this.dataDoc.markerAmount = max;
- // }
- // return max
- // }
+ for (let i = 0; i < 500; i++) {
+ if (this._count[i][0] >= m.audioStart && this._count[i][0] <= m.audioEnd) {
+ this._count[i][1] = max;
+ }
+
+ }
+
+ if (this.dataDoc.markerAmount < max) {
+ this.dataDoc.markerAmount = max;
+ }
+ return max - 1
+ }
formatTime = (time: number) => {
const hours = Math.floor(time / 60 / 60);
@@ -609,6 +631,13 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
this._first = true;
}
+ @computed get height() {
+ console.log(this.layoutDoc._height);
+ if (this.layoutDoc._height) {
+ return 0.8 * this.layoutDoc._height
+ }
+ }
+
render() {
//trace();
const interactive = this.active() ? "-interactive" : "";
@@ -673,14 +702,14 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
this._hold ? this.end(this._ele!.currentTime) : this.start(this._ele!.currentTime);
}
}}>
- <div className="waveform" style={{ height: `${100}%`, width: "100%", bottom: "0px" }}>
+ <div className="waveform" id="waveform" style={{ height: `${100}%`, width: "100%", bottom: "0px" }}>
{console.log(this.peaks)}
<Waveform
color={"#000000"}
- height={20}
+ height={this.height}
barWidth={0.1}
pos={this.layoutDoc.currentTimecode}
- duration={this.layoutDoc.duration}
+ duration={this.dataDoc.duration}
peaks={this._buckets.length === 100 ? this._buckets : undefined}
progressColor={"#0000ff"} />
</div>
@@ -690,7 +719,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
(!m.isLabel) ?
(this.layoutDoc.hideMarkers) ? (null) :
rect =
- <div className={this.props.PanelHeight() < 32 ? "audiobox-marker-minicontainer" : "audiobox-marker-container1"} title={`${this.formatTime(Math.round(NumCast(m.audioStart)))}` + " - " + `${this.formatTime(Math.round(NumCast(m.audioEnd)))}`} key={i} id={"audiobox-marker-container1"} style={{ left: `${NumCast(m.audioStart) / NumCast(this.dataDoc.duration, 1) * 100}%`, width: `${(NumCast(m.audioEnd) - NumCast(m.audioStart)) / NumCast(this.dataDoc.duration, 1) * 100}%`, height: `${1 / (this.dataDoc.markerAmount + 2) * 100}%`, top: `${this.isOverlap(m, i) * 1 / (this.dataDoc.markerAmount + 2) * 100}%` }} onClick={e => { this.playFrom(NumCast(m.audioStart), NumCast(m.audioEnd)); e.stopPropagation() }} >
+ <div className={this.props.PanelHeight() < 32 ? "audiobox-marker-minicontainer" : "audiobox-marker-container1"} title={`${this.formatTime(Math.round(NumCast(m.audioStart)))}` + " - " + `${this.formatTime(Math.round(NumCast(m.audioEnd)))}`} key={i} id={"audiobox-marker-container1"} style={{ left: `${NumCast(m.audioStart) / NumCast(this.dataDoc.duration, 1) * 100}%`, width: `${(NumCast(m.audioEnd) - NumCast(m.audioStart)) / NumCast(this.dataDoc.duration, 1) * 100}%`, height: `${1 / (this.dataDoc.markerAmount + 1) * 100}%`, top: `${this.isOverlap(m) * 1 / (this.dataDoc.markerAmount + 1) * 100}%` }} onClick={e => { this.playFrom(NumCast(m.audioStart), NumCast(m.audioEnd)); e.stopPropagation() }} >
<div className="left-resizer" onPointerDown={e => this.onPointerDown(e, m, true)}></div>
<DocumentView {...this.props}
Document={m}
@@ -700,7 +729,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
rootSelected={returnFalse}
LayoutTemplate={undefined}
ContainingCollectionDoc={this.props.Document}
- removeDocument={undefined}
+ removeDocument={this.removeDocument}
parentActive={returnTrue}
onClick={this.layoutDoc.playOnClick ? this.rangeScript : undefined}
ignoreAutoHeight={false}
@@ -722,7 +751,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
rootSelected={returnFalse}
LayoutTemplate={undefined}
ContainingCollectionDoc={this.props.Document}
- removeDocument={undefined}
+ removeDocument={this.removeDocument}
parentActive={returnTrue}
onClick={this.layoutDoc.playOnClick ? this.labelScript : undefined}
ignoreAutoHeight={false}
@@ -776,7 +805,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
{this.formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}
</div>
<div className="total-time">
- {this.formatTime(Math.round(NumCast(this.layoutDoc.duration)))}
+ {this.formatTime(Math.round(NumCast(this.dataDoc.duration)))}
</div>
</div>
</div>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index b1d9be73b..91940466f 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -2,7 +2,7 @@ import { library } from '@fortawesome/fontawesome-svg-core';
import { faEdit, faSmile, faTextHeight, faUpload } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { isEqual } from "lodash";
-import { action, computed, IReactionDisposer, Lambda, observable, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, Lambda, observable, reaction, runInAction, trace } from "mobx";
import { observer } from "mobx-react";
import { baseKeymap, selectAll } from "prosemirror-commands";
import { history } from "prosemirror-history";
@@ -93,6 +93,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
private _undoTyping?: UndoManager.Batch;
private _disposers: { [name: string]: IReactionDisposer } = {};
private _dropDisposer?: DragManager.DragDropDisposer;
+ private _first: Boolean = true;
+ private _recordingStart: number = 0;
+ private _currentTime: number = 0;
+ private _linkTime: number | null = null;
+ private _pause: boolean = false;
@computed get _recording() { return this.dataDoc.audioState === "recording"; }
set _recording(value) { this.dataDoc.audioState = value ? "recording" : undefined; }
@@ -140,6 +145,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
super(props);
FormattedTextBox.Instance = this;
this.updateHighlights();
+ this._recordingStart = Date.now();
+ this.layoutDoc._timeStampOnEnter = true;
}
public get CurrentDiv(): HTMLDivElement { return this._ref.current!; }
@@ -197,9 +204,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
dispatchTransaction = (tx: Transaction) => {
+ let timeStamp;
+ clearTimeout(timeStamp);
+ console.log("hi");
if (this._editorView) {
+
const metadata = tx.selection.$from.marks().find((m: Mark) => m.type === schema.marks.metadata);
if (metadata) {
+
const range = tx.selection.$from.blockRange(tx.selection.$to);
let text = range ? tx.doc.textBetween(range.start, range.end) : "";
let textEndSelection = tx.selection.to;
@@ -221,6 +233,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
this.dataDoc[key] = value;
}
}
+
const state = this._editorView.state.apply(tx);
this._editorView.updateState(state);
(tx.storedMarks && !this._editorView.state.storedMarks) && (this._editorView.state.storedMarks = tx.storedMarks);
@@ -234,19 +247,33 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const json = JSON.stringify(state.toJSON());
let unchanged = true;
const effectiveAcl = GetEffectiveAcl(this.dataDoc);
+
+
if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) {
if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) {
this._applyingChange = true;
(curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text) && (this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())));
if ((!curTemp && !curProto) || curText || curLayout?.Data.includes("dash")) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended)
if (json.replace(/"selection":.*/, "") !== curLayout?.Data.replace(/"selection":.*/, "")) {
+ console.log("type");
+ if (!this._pause && !this.layoutDoc._timeStampOnEnter) {
+ console.log("started");
+ timeStamp = setTimeout(() => this.pause(), 10 * 1000);
+ }
+
+ if (this._pause) {
+ this._pause = false;
+ this.insertTime();
+ }
!curText && tx.storedMarks?.map(m => m.type.name === "pFontSize" && (Doc.UserDoc().fontSize = this.layoutDoc._fontSize = m.attrs.fontSize));
!curText && tx.storedMarks?.map(m => m.type.name === "pFontFamily" && (Doc.UserDoc().fontFamily = this.layoutDoc._fontFamily = m.attrs.fontFamily));
this.dataDoc[this.props.fieldKey] = new RichTextField(json, curText);
this.dataDoc[this.props.fieldKey + "-noTemplate"] = (curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited
ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText });
unchanged = false;
+
}
+
} else { // if we've deleted all the text in a note driven by a template, then restore the template data
this.dataDoc[this.props.fieldKey] = undefined;
this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse((curProto || curTemp).Data)));
@@ -260,6 +287,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
} else {
+
const json = JSON.parse(Cast(this.dataDoc[this.fieldKey], RichTextField)?.Data!);
json.selection = state.toJSON().selection;
this._editorView.updateState(EditorState.fromJSON(this.config, json));
@@ -267,6 +295,66 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
+ pause = () => this._pause = true;
+
+ formatTime = (time: number) => {
+ const hours = Math.floor(time / 60 / 60);
+ const minutes = Math.floor(time / 60) - (hours * 60);
+ const seconds = time % 60;
+
+ return hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0');
+ }
+
+ insertTime = () => {
+ let linkTime;
+ if (this._first) {
+ this._first = false;
+ DocListCast(this.dataDoc.links).map((l, i) => {
+ let la1 = l.anchor1 as Doc;
+ let la2 = l.anchor2 as Doc;
+ this._linkTime = NumCast(l.anchor2_timecode);
+ if (Doc.AreProtosEqual(la2, this.dataDoc)) {
+ la1 = l.anchor2 as Doc;
+ la2 = l.anchor1 as Doc;
+ this._linkTime = NumCast(l.anchor1_timecode);
+ }
+
+ })
+
+
+
+ }
+ this._currentTime = Date.now();
+ let time;
+ console.log(this._linkTime);
+ this._linkTime ? time = this.formatTime(Math.round(this._linkTime + this._currentTime / 1000 - this._recordingStart / 1000)) : time = null;
+
+ if (this._editorView) {
+ const state = this._editorView.state;
+ const now = Date.now();
+ let mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(now / 1000) });
+ if (!this._break && state.selection.to !== state.selection.from) {
+ for (let i = state.selection.from; i <= state.selection.to; i++) {
+ const pos = state.doc.resolve(i);
+ const um = Array.from(pos.marks()).find(m => m.type === schema.marks.user_mark);
+ if (um) {
+ mark = um;
+ break;
+ }
+ }
+ }
+ if (time) {
+ let value = "";
+ this._break = false;
+ value = this.layoutDoc._timeStampOnEnter ? "[" + time + "] " : "\n" + "[" + time + "] ";
+ console.log(value);
+ const from = state.selection.from;
+ const inserted = state.tr.insertText(value).addMark(from, from + value.length + 1, mark);
+ this._editorView.dispatch(this._editorView.state.tr.insertText(value));
+ }
+ }
+ }
+
updateTitle = () => {
if ((this.props.Document.isTemplateForField === "text" || !this.props.Document.isTemplateForField) && // only update the title if the data document's data field is changing
StrCast(this.dataDoc.title).startsWith("-") && this._editorView && !this.rootDoc.customTitle) {
@@ -501,6 +589,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
uicontrols.push({ description: `${this.layoutDoc._showSidebar ? "Hide" : "Show"} Sidebar`, event: () => this.layoutDoc._showSidebar = !this.layoutDoc._showSidebar, icon: "expand-arrows-alt" });
uicontrols.push({ description: `${this.layoutDoc._showAudio ? "Hide" : "Show"} Dictation Icon`, event: () => this.layoutDoc._showAudio = !this.layoutDoc._showAudio, icon: "expand-arrows-alt" });
uicontrols.push({ description: "Show Highlights...", noexpand: true, subitems: highlighting, icon: "hand-point-right" });
+ uicontrols.push({ description: `Create TimeStamp When ${this.layoutDoc._timeStampOnEnter ? "Pause" : "Enter"}`, event: () => this.layoutDoc._timeStampOnEnter = !this.layoutDoc._timeStampOnEnter, icon: "expand-arrows-alt" });
!Doc.UserDoc().noviceMode && uicontrols.push({
description: "Broadcast Message", event: () => DocServer.GetRefField("rtfProto").then(proto =>
proto instanceof Doc && (proto.BROADCAST_MESSAGE = Cast(this.rootDoc[this.fieldKey], RichTextField)?.Text)), icon: "expand-arrows-alt"
@@ -594,6 +683,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const recordingStart = DateCast(this.props.Document.recordingStart).date.getTime();
this._break = false;
value = "" + (mark.attrs.modified * 1000 - recordingStart) / 1000 + value;
+ console.log(value);
const from = state.selection.from;
const inserted = state.tr.insertText(value).addMark(from, from + value.length + 1, mark);
this._editorView.dispatch(inserted.setSelection(TextSelection.create(inserted.doc, from, from + value.length + 1)));
@@ -1295,30 +1385,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
e.stopPropagation();
if (e.key === "Tab" || e.key === "Enter") {
- // console.log(this._recording);
- // if (this._editorView) {
- // const state = this._editorView.state;
- // const now = Date.now();
- // let mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(now / 1000) });
- // if (!this._break && state.selection.to !== state.selection.from) {
- // for (let i = state.selection.from; i <= state.selection.to; i++) {
- // const pos = state.doc.resolve(i);
- // const um = Array.from(pos.marks()).find(m => m.type === schema.marks.user_mark);
- // if (um) {
- // mark = um;
- // break;
- // }
- // }
- // }
- // const recordingStart = DateCast(this.props.Document.recordingStart).date.getTime();
- // this._break = false;
- // let value = "" + (mark.attrs.modified * 1000 - recordingStart) / 1000;
- // //let value = "[0:02]";
- // const from = state.selection.from;
- // const inserted = state.tr.insertText(value).addMark(from, from + value.length + 1, mark);
-
- // this._editorView.dispatch(inserted.setSelection(TextSelection.create(inserted.doc, from, from + value.length + 1)));
- // }
+ if (e.key === "Enter" && this.layoutDoc._timeStampOnEnter) {
+ this.insertTime();
+ }
e.preventDefault();
}
if (e.key === " " || this._lastTimedMark?.attrs.userid !== Doc.CurrentUserEmail) {
@@ -1371,6 +1440,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
@computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); }
render() {
TraceMobx();
+ trace();
+ // if (this.props.Document.recordingStart) {
+ // console.log(DateCast(this.props.Document.recordingStart).date.getTime());
+ // }
+
const scale = this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground;