aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts36
-rw-r--r--src/client/views/Main.tsx11
-rw-r--r--src/client/views/collections/CollectionView.tsx2
-rw-r--r--src/client/views/nodes/AudioBox.scss4
-rw-r--r--src/client/views/nodes/AudioBox.tsx44
-rw-r--r--src/client/views/nodes/DocumentView.tsx4
-rw-r--r--src/client/views/nodes/FieldView.tsx11
-rw-r--r--src/client/views/nodes/VideoBox.scss4
-rw-r--r--src/client/views/nodes/VideoBox.tsx43
-rw-r--r--src/fields/AudioField.ts31
-rw-r--r--src/fields/VideoField.ts30
-rw-r--r--src/server/Message.ts2
-rw-r--r--src/server/ServerUtil.ts35
13 files changed, 241 insertions, 16 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index fc210e9a2..a91834cca 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -14,6 +14,11 @@ import { HtmlField } from "../../fields/HtmlField";
import { Key } from "../../fields/Key"
import { Field } from "../../fields/Field";
import { KeyValueBox } from "../views/nodes/KeyValueBox"
+import { KVPField } from "../../fields/KVPField";
+import { VideoField } from "../../fields/VideoField"
+import { VideoBox } from "../views/nodes/VideoBox";
+import { AudioField } from "../../fields/AudioField";
+import { AudioBox } from "../views/nodes/AudioBox";
import { PDFField } from "../../fields/PDFField";
import { PDFBox } from "../views/nodes/PDFBox";
import { CollectionPDFView } from "../views/collections/CollectionPDFView";
@@ -40,6 +45,8 @@ export namespace Documents {
let webProto: Document;
let collProto: Document;
let kvpProto: Document;
+ let videoProto: Document;
+ let audioProto: Document;
let pdfProto: Document;
const textProtoId = "textProto";
const pdfProtoId = "pdfProto";
@@ -47,6 +54,8 @@ export namespace Documents {
const webProtoId = "webProto";
const collProtoId = "collectionProto";
const kvpProtoId = "kvpProto";
+ const videoProtoId = "videoProto"
+ const audioProtoId = "audioProto";
export function initProtos(mainDocId: string, callback: (mainDoc?: Document) => void) {
Server.GetFields([collProtoId, textProtoId, imageProtoId, mainDocId], (fields) => {
@@ -121,6 +130,17 @@ export namespace Documents {
kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValueBox.LayoutString(),
{ x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
}
+ function GetVideoPrototype(): Document {
+ return videoProto ? videoProto :
+ videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", VideoBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
+ }
+ function GetAudioPrototype(): Document {
+ return audioProto ? audioProto :
+ audioProto = setupPrototypeOptions(audioProtoId, "AUDIO_PROTO", AudioBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
+ }
+
export function ImageDocument(url: string, options: DocumentOptions = {}) {
let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
@@ -130,6 +150,22 @@ export namespace Documents {
doc.SetText(KeyStore.OverlayLayout, FixedCaption());
return doc;
}
+ export function VideoDocument(url: string, options: DocumentOptions = {}){
+ let doc = SetInstanceOptions(GetVideoPrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
+ new URL(url), VideoField);
+ doc.SetText(KeyStore.Caption, "my caption...");
+ doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption());
+ doc.SetText(KeyStore.OverlayLayout, FixedCaption());
+ return doc;
+ }
+ export function AudioDocument(url: string, options: DocumentOptions = {}){
+ let doc = SetInstanceOptions(GetAudioPrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
+ new URL(url), AudioField);
+ doc.SetText(KeyStore.Caption, "my caption...");
+ doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption());
+ doc.SetText(KeyStore.OverlayLayout, FixedCaption());
+ return doc;
+ }
export function TextDocument(options: DocumentOptions = {}) {
return SetInstanceOptions(GetTextPrototype(), options, "", TextField);
}
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index c9bdc24c2..6f08566bc 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -54,14 +54,17 @@ Documents.initProtos(mainDocId, (res?: Document) => {
let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf"
let weburl = "https://cs.brown.edu/courses/cs166/";
+ let audiourl = "http://techslides.com/demos/samples/sample.mp3";
+ let videourl = "http://techslides.com/demos/sample-videos/small.mp4";
let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}))
let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" }))
let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 200, height: 200, title: "a schema collection" }));
+ let addVideoNode = action(() => Documents.VideoDocument(videourl, {width: 200, height:200, title: "video node"}));
let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" }));
let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" }));
let addWebNode = action(() => Documents.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" }));
-
+ let addAudioNode = action(() => Documents.AudioDocument(audiourl,{ width: 200, height: 200, title: "audio node" } ))
let addClick = (creator: () => Document) => action(() =>
mainfreeform.GetList<Document>(KeyStore.Data, []).push(creator())
);
@@ -71,6 +74,8 @@ Documents.initProtos(mainDocId, (res?: Document) => {
let webRef = React.createRef<HTMLDivElement>();
let textRef = React.createRef<HTMLDivElement>();
let schemaRef = React.createRef<HTMLDivElement>();
+ let videoRef = React.createRef<HTMLDivElement>();
+ let audioRef = React.createRef<HTMLDivElement>();
let colRef = React.createRef<HTMLDivElement>();
ReactDOM.render((
@@ -98,6 +103,10 @@ Documents.initProtos(mainDocId, (res?: Document) => {
<button onPointerDown={setupDrag(schemaRef, addSchemaNode)} onClick={addClick(addSchemaNode)}>Add Schema</button></div>
<div className="main-buttonDiv" style={{ bottom: '125px' }} >
<button onClick={clearDatabase}>Clear Database</button></div>
+ <div className="main-buttonDiv" style={{ bottom: '175px' }} ref={videoRef}>
+ <button onPointerDown={setupDrag(videoRef, addVideoNode)} onClick={addClick(addVideoNode)}>Add Video</button></div>
+ <div className="main-buttonDiv" style={{ bottom: '200px' }} ref={audioRef}>
+ <button onPointerDown={setupDrag(audioRef, addAudioNode)} onClick={addClick(addAudioNode)}>Add Audio</button></div>
<div className="main-buttonDiv" style={{ bottom: '150px' }} ref={pdfRef}>
<button onPointerDown={setupDrag(pdfRef, addPDFNode)} onClick={addClick(addPDFNode)}>Add PDF</button></div>
<button className="main-undoButtons" style={{ bottom: '25px' }} onClick={() => UndoManager.Undo()}>Undo</button>
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 49df04163..f154909bb 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -116,4 +116,4 @@ export class CollectionView extends React.Component<CollectionViewProps> {
{this.subView}
</div>)
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss
new file mode 100644
index 000000000..704cdc31c
--- /dev/null
+++ b/src/client/views/nodes/AudioBox.scss
@@ -0,0 +1,4 @@
+.audiobox-cont{
+ height: 100%;
+ width: 100%;
+} \ No newline at end of file
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
new file mode 100644
index 000000000..f7d89843d
--- /dev/null
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -0,0 +1,44 @@
+import React = require("react")
+import { FieldViewProps, FieldView } from './FieldView';
+import { FieldWaiting } from '../../../fields/Field';
+import { observer } from "mobx-react"
+import { ContextMenu } from "../../views/ContextMenu";
+import { observable, action } from 'mobx';
+import { KeyStore } from '../../../fields/KeyStore';
+import { AudioField } from "../../../fields/AudioField";
+import "./AudioBox.scss"
+import { NumberField } from "../../../fields/NumberField";
+
+@observer
+export class AudioBox extends React.Component<FieldViewProps> {
+
+ public static LayoutString() { return FieldView.LayoutString(AudioBox) }
+
+ constructor(props: FieldViewProps) {
+ super(props);
+ }
+
+
+
+ componentDidMount() {
+ }
+
+ componentWillUnmount() {
+ }
+
+
+ render() {
+ let field = this.props.doc.Get(this.props.fieldKey)
+ let path = field == FieldWaiting ? "http://techslides.com/demos/samples/sample.mp3":
+ field instanceof AudioField ? field.Data.href : "http://techslides.com/demos/samples/sample.mp3";
+
+ return (
+ <div>
+ <audio controls className = "audiobox-cont">
+ <source src = {path} type="audio/mpeg"/>
+ Not supported.
+ </audio>
+ </div>
+ )
+ }
+} \ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 41e93df35..263bb31d7 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -16,6 +16,8 @@ import { CollectionPDFView } from "../collections/CollectionPDFView";
import { ContextMenu } from "../ContextMenu";
import { FormattedTextBox } from "../nodes/FormattedTextBox";
import { ImageBox } from "../nodes/ImageBox";
+import { VideoBox } from "../nodes/VideoBox";
+import { AudioBox } from "../nodes/AudioBox";
import { Documents } from "../../documents/Documents"
import { KeyValueBox } from "./KeyValueBox"
import { WebBox } from "../nodes/WebBox";
@@ -196,7 +198,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
@computed get mainContent() {
return <JsxParser
- components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, PDFBox }}
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, VideoBox, AudioBox, PDFBox }}
bindings={this._documentBindings}
jsx={this.layout}
showWarnings={true}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 9e63006d1..49f4cefce 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -8,10 +8,15 @@ import { NumberField } from "../../../fields/NumberField";
import { RichTextField } from "../../../fields/RichTextField";
import { ImageField } from "../../../fields/ImageField";
import { WebField } from "../../../fields/WebField";
+import { VideoField } from "../../../fields/VideoField"
import { Key } from "../../../fields/Key";
import { FormattedTextBox } from "./FormattedTextBox";
import { ImageBox } from "./ImageBox";
import { WebBox } from "./WebBox";
+import { VideoBox } from "./VideoBox";
+import { AudioBox } from "./AudioBox";
+import { AudioField } from "../../../fields/AudioField";
+
//
// these properties get assigned through the render() method of the DocumentView when it creates this node.
@@ -55,6 +60,12 @@ export class FieldView extends React.Component<FieldViewProps> {
}
else if (field instanceof WebField) {
return <WebBox {...this.props} />
+ }
+ else if (field instanceof VideoField){
+ return <VideoBox {...this.props}/>
+ }
+ else if (field instanceof AudioField){
+ return <AudioBox {...this.props}/>
}
// bcz: this belongs here, but it doesn't render well so taking it out for now
// else if (field instanceof HtmlField) {
diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss
new file mode 100644
index 000000000..7306450d9
--- /dev/null
+++ b/src/client/views/nodes/VideoBox.scss
@@ -0,0 +1,4 @@
+.videobox-cont{
+ width: 100%;
+ height: 100%;
+} \ No newline at end of file
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
new file mode 100644
index 000000000..22ff5c5ad
--- /dev/null
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -0,0 +1,43 @@
+import React = require("react")
+import { FieldViewProps, FieldView } from './FieldView';
+import { FieldWaiting } from '../../../fields/Field';
+import { observer } from "mobx-react"
+import { VideoField } from '../../../fields/VideoField';
+import "./VideoBox.scss"
+import { ContextMenu } from "../../views/ContextMenu";
+import { observable, action } from 'mobx';
+import { KeyStore } from '../../../fields/KeyStore';
+
+@observer
+export class VideoBox extends React.Component<FieldViewProps> {
+
+ public static LayoutString() { return FieldView.LayoutString(VideoBox) }
+
+ constructor(props: FieldViewProps) {
+ super(props);
+ }
+
+
+
+ componentDidMount() {
+ }
+
+ componentWillUnmount() {
+ }
+
+
+ render() {
+ let field = this.props.doc.Get(this.props.fieldKey)
+ let path = field == FieldWaiting ? "http://techslides.com/demos/sample-videos/small.mp4":
+ field instanceof VideoField ? field.Data.href : "http://techslides.com/demos/sample-videos/small.mp4";
+
+ return (
+ <div>
+ <video width = {200} height = {200} controls className = "videobox-cont">
+ <source src = {path} type = "video/mp4"/>
+ Not supported.
+ </video>
+ </div>
+ )
+ }
+} \ No newline at end of file
diff --git a/src/fields/AudioField.ts b/src/fields/AudioField.ts
new file mode 100644
index 000000000..aefcc15c1
--- /dev/null
+++ b/src/fields/AudioField.ts
@@ -0,0 +1,31 @@
+import { BasicField } from "./BasicField";
+import { Field, FieldId } from "./Field";
+import { Types } from "../server/Message";
+
+export class AudioField extends BasicField<URL> {
+ constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
+ super(data == undefined ? new URL("http://techslides.com/demos/samples/sample.mp3") : data, save, id);
+ }
+
+ toString(): string {
+ return this.Data.href;
+ }
+
+
+ ToScriptString(): string {
+ return `new AudioField("${this.Data}")`;
+ }
+
+ Copy(): Field {
+ return new AudioField(this.Data);
+ }
+
+ ToJson(): { type: Types, data: URL, _id: string } {
+ return {
+ type: Types.Audio,
+ data: this.Data,
+ _id: this.Id
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/fields/VideoField.ts b/src/fields/VideoField.ts
new file mode 100644
index 000000000..5f4ae19bf
--- /dev/null
+++ b/src/fields/VideoField.ts
@@ -0,0 +1,30 @@
+import { BasicField } from "./BasicField";
+import { Field, FieldId } from "./Field";
+import { Types } from "../server/Message";
+
+export class VideoField extends BasicField<URL> {
+ constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
+ super(data == undefined ? new URL("http://techslides.com/demos/sample-videos/small.mp4") : data, save, id);
+ }
+
+ toString(): string {
+ return this.Data.href;
+ }
+
+ ToScriptString(): string {
+ return `new VideoField("${this.Data}")`;
+ }
+
+ Copy(): Field {
+ return new VideoField(this.Data);
+ }
+
+ ToJson(): { type: Types, data: URL, _id: string } {
+ return {
+ type: Types.Video,
+ data: this.Data,
+ _id: this.Id
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/server/Message.ts b/src/server/Message.ts
index 5e97a5edf..8a00f6b59 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -45,7 +45,7 @@ export class GetFieldArgs {
}
export enum Types {
- Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html, Ink, PDF
+ Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html, Video, Audio, Ink, PDF
}
export class DocumentTransfer implements Transferable {
diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts
index 3b9d14891..5331c9e30 100644
--- a/src/server/ServerUtil.ts
+++ b/src/server/ServerUtil.ts
@@ -1,17 +1,24 @@
-import {HtmlField} from '../fields/HtmlField';
+
+import { Field } from './../fields/Field';
+import { TextField } from './../fields/TextField';
+import { NumberField } from './../fields/NumberField';
+import { RichTextField } from './../fields/RichTextField';
+import { Key } from './../fields/Key';
+import { ImageField } from './../fields/ImageField';
+import { ListField } from './../fields/ListField';
+import { Document } from './../fields/Document';
+import { Server } from './../client/Server';
+import { Types } from './Message';
+import { Utils } from '../Utils';
+import { HtmlField } from '../fields/HtmlField';
+import { WebField } from '../fields/WebField';
+import { AudioField } from '../fields/AudioField';
+import { VideoField } from '../fields/VideoField';
import {InkField} from '../fields/InkField';
import {PDFField} from '../fields/PDFField';
-import {WebField} from '../fields/WebField';
-import {Utils} from '../Utils';
-import {Document} from './../fields/Document';
-import {Field} from './../fields/Field';
-import {ImageField} from './../fields/ImageField';
-import {Key} from './../fields/Key';
-import {ListField} from './../fields/ListField';
-import {NumberField} from './../fields/NumberField';
-import {RichTextField} from './../fields/RichTextField';
-import {TextField} from './../fields/TextField';
-import {Types} from './Message';
+
+
+
export class ServerUtils {
public static FromJson(json: any): Field {
@@ -44,6 +51,10 @@ export class ServerUtils {
return new PDFField(new URL(data), id, false)
case Types.List:
return ListField.FromJson(id, data)
+ case Types.Audio:
+ return new AudioField(new URL(data), id, false)
+ case Types.Video:
+ return new VideoField(new URL(data), id, false)
case Types.Ink:
return InkField.FromJson(id, data);
case Types.Document: