aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/util/ProsemirrorExampleTransfer.ts17
-rw-r--r--src/client/views/DocumentDecorations.tsx26
-rw-r--r--src/client/views/collections/CollectionSubView.tsx5
-rw-r--r--src/client/views/collections/CollectionView.tsx9
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx13
-rw-r--r--src/client/views/webcam/DashWebRTCVideo.tsx2
-rw-r--r--src/client/views/webcam/WebCamLogic.js61
7 files changed, 68 insertions, 65 deletions
diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index da3815181..81cf54d4c 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -175,13 +175,16 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
});
const path = (state.doc.resolve(state.selection.from - 1) as any).path;
const spaceSeparator = path[path.length - 3].childCount > 1 ? 0 : -1;
- const textsel = TextSelection.create(state.doc, range!.end - path[path.length - 3].lastChild.nodeSize + spaceSeparator, range!.end);
- const text = range ? state.doc.textBetween(textsel.from, textsel.to) : "";
- let whitespace = text.length - 1;
- for (; whitespace >= 0 && text[whitespace] !== " "; whitespace--) { }
- if (text.endsWith(":")) {
- dispatch(state.tr.addMark(textsel.from + whitespace + 1, textsel.to, schema.marks.metadata.create() as any).
- addMark(textsel.from + whitespace + 1, textsel.to - 2, schema.marks.metadataKey.create() as any));
+ const anchor = range!.end - path[path.length - 3].lastChild.nodeSize + spaceSeparator;
+ if (anchor >= 0) {
+ const textsel = TextSelection.create(state.doc, anchor, range!.end);
+ const text = range ? state.doc.textBetween(textsel.from, textsel.to) : "";
+ let whitespace = text.length - 1;
+ for (; whitespace >= 0 && text[whitespace] !== " "; whitespace--) { }
+ if (text.endsWith(":")) {
+ dispatch(state.tr.addMark(textsel.from + whitespace + 1, textsel.to, schema.marks.metadata.create() as any).
+ addMark(textsel.from + whitespace + 1, textsel.to - 2, schema.marks.metadataKey.create() as any));
+ }
}
return false;
});
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7359835c5..3dfe34234 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -5,7 +5,6 @@ import { action, computed, observable, reaction } from "mobx";
import { observer } from "mobx-react";
import { Doc } from "../../new_fields/Doc";
import { PositionDocument } from '../../new_fields/documentSchemas';
-import { ObjectField } from '../../new_fields/ObjectField';
import { ScriptField } from '../../new_fields/ScriptField';
import { Cast, StrCast } from "../../new_fields/Types";
import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
@@ -107,27 +106,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
if (key === 13) {
const text = e.target.value;
if (text.startsWith("::")) {
- const targetID = text.slice(2, text.length);
+ this._accumulatedTitle = text.slice(2, text.length);
const promoteDoc = SelectionManager.SelectedDocuments()[0];
- DocUtils.Publish(promoteDoc.props.Document, targetID, promoteDoc.props.addDocument, promoteDoc.props.removeDocument);
- } else if (text.startsWith(">")) {
- const fieldTemplateView = SelectionManager.SelectedDocuments()[0];
- SelectionManager.DeselectAll();
- const fieldTemplate = fieldTemplateView.props.Document;
- const containerView = fieldTemplateView.props.ContainingCollectionView;
- const docTemplate = fieldTemplateView.props.ContainingCollectionDoc;
- if (containerView && docTemplate) {
- const metaKey = text.startsWith(">>") ? text.slice(2, text.length) : text.slice(1, text.length);
- if (metaKey !== containerView.props.fieldKey && containerView.props.DataDoc) {
- const fd = fieldTemplate.data;
- fd instanceof ObjectField && (Doc.GetProto(containerView.props.DataDoc)[metaKey] = ObjectField.MakeCopy(fd));
- }
- fieldTemplate.title = metaKey;
- Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate));
- if (text.startsWith(">>")) {
- Doc.GetProto(docTemplate).layout = StrCast(fieldTemplateView.props.Document.layout).replace(/fieldKey={'[^']*'}/, `fieldKey={"${metaKey}"}`);
- }
- }
+ Doc.SetInPlace(promoteDoc.props.Document, "title", this._accumulatedTitle, true);
+ DocUtils.Publish(promoteDoc.props.Document, this._accumulatedTitle, promoteDoc.props.addDocument, promoteDoc.props.removeDocument);
}
e.target.blur();
}
@@ -539,7 +521,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
{minimizeIcon}
{this._edtingTitle ? <>
- <input ref={this._keyinput} className="title" type="text" name="dynbox" value={this._accumulatedTitle} style={{ width: "calc(100% - 20px)" }}
+ <input ref={this._keyinput} className="title" type="text" name="dynbox" autoComplete="on" value={this._accumulatedTitle} style={{ width: "calc(100% - 20px)" }}
onBlur={e => this.titleBlur(true)} onChange={this.titleChanged} onKeyPress={this.titleEntered} />
<div className="publishBox" title="make document referenceable by its title"
onPointerDown={e => {
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 20941493f..32480ad4e 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -85,7 +85,10 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
this._childLayoutDisposer && this._childLayoutDisposer();
}
- @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) : Doc.GetProto(this.props.Document); }
+ @computed get dataDoc() {
+ return (this.props.DataDoc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) :
+ this.props.Document.resolvedDataDoc ? this.props.Document : Doc.GetProto(this.props.Document)); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template
+ }
// The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc.
// When a document has a DataDoc but it's not a template, then it contains its own rendering data, but needs to pass the DataDoc through
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 8dd844711..de3e9737f 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -37,6 +37,7 @@ import './CollectionView.scss';
import { CollectionViewBaseChrome } from './CollectionViewChromes';
import { CollectionTimeView } from './CollectionTimeView';
import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView';
+import { List } from '../../../new_fields/List';
export const COLLECTION_BORDER_WIDTH = 2;
const path = require('path');
library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy);
@@ -132,8 +133,9 @@ export class CollectionView extends Touchable<FieldViewProps> {
@action.bound
addDocument(doc: Doc): boolean {
- const targetDataDoc = this.props.Document[DataSym];
- Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc);
+ const targetDataDoc = this.props.Document.resolvedDataDoc && !this.props.Document.isTemplateForField ? this.props.Document : Doc.GetProto(this.props.Document[DataSym]);
+ targetDataDoc[this.props.fieldKey] = new List<Doc>([...DocListCast(targetDataDoc[this.props.fieldKey]), doc]); // DocAddToList may write to targetdataDoc's parent ... we don't want this. should really change GetProto to GetDataDoc and test for resolvedDataDoc there
+ // Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc);
targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
Doc.GetProto(doc).lastOpened = new DateField;
return true;
@@ -143,7 +145,8 @@ export class CollectionView extends Touchable<FieldViewProps> {
removeDocument(doc: Doc): boolean {
const docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView);
docView && SelectionManager.DeselectDoc(docView);
- const value = Cast(this.props.Document[DataSym][this.props.fieldKey], listSpec(Doc), []);
+ const targetDataDoc = this.props.Document.resolvedDataDoc ? this.props.Document : this.props.Document[DataSym];
+ const value = Cast(targetDataDoc[this.props.fieldKey], listSpec(Doc), []);
let index = value.reduce((p, v, i) => (v instanceof Doc && v === doc) ? i : p, -1);
index = index !== -1 ? index : value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1);
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 0cc276458..7fbee8881 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -812,7 +812,11 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
}
static _downEvent: any;
+ _downX = 0;
+ _downY = 0;
onPointerDown = (e: React.PointerEvent): void => {
+ this._downX = e.clientX;
+ this._downY = e.clientY;
this.doLinkOnDeselect();
FormattedTextBox._downEvent = true;
FormattedTextBoxComment.textBox = this;
@@ -923,7 +927,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
// }
// }
- this.hitBulletTargets(e.clientX, e.clientY, e.shiftKey, false);
+ if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientX - this._downX) < 4) {
+ this.hitBulletTargets(e.clientX, e.clientY, e.shiftKey, false);
+ }
if (this._recording) setTimeout(() => { this.stopDictation(true); setTimeout(() => this.recordDictation(), 500); }, 500);
}
@@ -955,8 +961,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
addStyleSheetRule(FormattedTextBox._bulletStyleSheet, list_node.attrs.mapStyle + list_node.attrs.bulletStyle + ":hover:before", { background: "lightgray" });
} else if (Math.abs(pos.pos - pos.inside) < 2) {
if (!highlightOnly) {
- this._editorView!.dispatch(this._editorView!.state.tr.setNodeMarkup(pos.inside, list_node.type, { ...list_node.attrs, visibility: !list_node.attrs.visibility }));
- this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, pos.inside)));
+ const offset = this._editorView!.state.doc.nodeAt(pos.inside)?.type === schema.nodes.ordered_list ? 1 : 0;
+ this._editorView!.dispatch(this._editorView!.state.tr.setNodeMarkup(pos.inside + offset, list_node.type, { ...list_node.attrs, visibility: !list_node.attrs.visibility }));
+ this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, pos.inside + offset)));
}
addStyleSheetRule(FormattedTextBox._bulletStyleSheet, list_node.attrs.mapStyle + list_node.attrs.bulletStyle + ":hover:before", { background: "lightgray" });
}
diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx
index 0eefbbc91..cbf75f708 100644
--- a/src/client/views/webcam/DashWebRTCVideo.tsx
+++ b/src/client/views/webcam/DashWebRTCVideo.tsx
@@ -70,7 +70,7 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV
<div className="webcam-cont" style={{ width: "100%", height: "100%" }} onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}>
<div className="webcam-header">DashWebRTC</div>
<input id="roomName" type="text" placeholder="Enter room name" ref={(e) => this.roomText = e!} onKeyDown={this.onEnterKeyDown} />
- <video id="localVideo" className={"RTCVideo" + (this.remoteVideoAdded ? " side" : " main")} autoPlay playsInline ref={(e) => {
+ <video id="localVideo" className={"RTCVideo" + (this.remoteVideoAdded ? " side" : " main")} autoPlay playsInline muted ref={(e) => {
}}></video>
<video id="remoteVideo" className="RTCVideo main" autoPlay playsInline ref={(e) => {
}}></video>
diff --git a/src/client/views/webcam/WebCamLogic.js b/src/client/views/webcam/WebCamLogic.js
index 1e0a749ea..3dfb82465 100644
--- a/src/client/views/webcam/WebCamLogic.js
+++ b/src/client/views/webcam/WebCamLogic.js
@@ -120,6 +120,38 @@ export function initialize(roomName, handlerUI) {
console.log('Getting user media with constraints', constraints);
+ const requestTurn = (turnURL) => {
+ var turnExists = false;
+ for (var i in pcConfig.iceServers) {
+ if (pcConfig.iceServers[i].urls.substr(0, 5) === 'turn:') {
+ turnExists = true;
+ turnReady = true;
+ break;
+ }
+ }
+ if (!turnExists) {
+ console.log('Getting TURN server from ', turnURL);
+ // No TURN server. Get one from computeengineondemand.appspot.com:
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ var turnServer = JSON.parse(xhr.responseText);
+ console.log('Got TURN server: ', turnServer);
+ pcConfig.iceServers.push({
+ 'urls': 'turn:' + turnServer.username + '@' + turnServer.turn,
+ 'credential': turnServer.password
+ });
+ turnReady = true;
+ }
+ };
+ xhr.open('GET', turnURL, true);
+ xhr.send();
+ }
+ }
+
+
+
+
if (location.hostname !== 'localhost') {
requestTurn(
`${window.location.origin}/corsProxy/${encodeURIComponent("https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913")}`
@@ -201,34 +233,7 @@ export function initialize(roomName, handlerUI) {
trace('Failed to create session description: ' + error.toString());
}
- const requestTurn = (turnURL) => {
- var turnExists = false;
- for (var i in pcConfig.iceServers) {
- if (pcConfig.iceServers[i].urls.substr(0, 5) === 'turn:') {
- turnExists = true;
- turnReady = true;
- break;
- }
- }
- if (!turnExists) {
- console.log('Getting TURN server from ', turnURL);
- // No TURN server. Get one from computeengineondemand.appspot.com:
- var xhr = new XMLHttpRequest();
- xhr.onreadystatechange = function () {
- if (xhr.readyState === 4 && xhr.status === 200) {
- var turnServer = JSON.parse(xhr.responseText);
- console.log('Got TURN server: ', turnServer);
- pcConfig.iceServers.push({
- 'urls': 'turn:' + turnServer.username + '@' + turnServer.turn,
- 'credential': turnServer.password
- });
- turnReady = true;
- }
- };
- xhr.open('GET', turnURL, true);
- xhr.send();
- }
- }
+
const handleRemoteStreamAdded = (event) => {
console.log('Remote stream added.');