aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoranika-ahluwalia <anika.ahluwalia@gmail.com>2020-05-18 17:21:35 -0500
committeranika-ahluwalia <anika.ahluwalia@gmail.com>2020-05-18 17:21:35 -0500
commit43a6a2296810b6ebafb849abc1d96a4d2fef0888 (patch)
tree57f4bf109a2f8b4b6c60c213f982d512fdd50f40 /src
parente3a3dfde10610eab18563c06717b3828bd849512 (diff)
parentda7ba72e8c75dfaa9920920b8234d99f699578a8 (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into script_documents
Diffstat (limited to 'src')
-rw-r--r--src/client/views/MainView.tsx18
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/server/ApiManagers/UploadManager.ts64
-rw-r--r--src/server/DashUploadUtils.ts2
5 files changed, 74 insertions, 14 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 4a20c39d4..1d6421656 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -186,16 +186,17 @@ export class MainView extends React.Component {
_LODdisable: true
};
const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
- const mainDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row");
+ const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row");
const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
- mainDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!]);
- mainDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode"]);
+ const cloneWorkspace = ScriptField.MakeScript(`cloneWorkspace()`);
+ workspaceDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, cloneWorkspace!]);
+ workspaceDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "New Workspace Layout"]);
- Doc.AddDocToList(workspaces, "data", mainDoc);
+ Doc.AddDocToList(workspaces, "data", workspaceDoc);
// bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
- setTimeout(() => this.openWorkspace(mainDoc), 0);
+ setTimeout(() => this.openWorkspace(workspaceDoc), 0);
}
@action
@@ -564,3 +565,10 @@ export class MainView extends React.Component {
}
Scripting.addGlobal(function freezeSidebar() { MainView.expandFlyout(); });
Scripting.addGlobal(function toggleComicMode() { Doc.UserDoc().fontFamily = "Comic Sans MS"; Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic" });
+Scripting.addGlobal(function cloneWorkspace() {
+ const copiedWorkspace = Doc.MakeCopy(Cast(Doc.UserDoc().activeWorkspace, Doc, null), true);
+ const workspaces = Cast(Doc.UserDoc().myWorkspaces, Doc, null);
+ Doc.AddDocToList(workspaces, "data", copiedWorkspace);
+ // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
+ setTimeout(() => MainView.Instance.openWorkspace(copiedWorkspace), 0);
+});
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d8fe662ae..aeb0a5813 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1179,8 +1179,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this._timelineVisible = !this._timelineVisible;
}), icon: this._timelineVisible ? faEyeSlash : faEye
});
- ContextMenu.Instance.addItem({ description: "Advance", event: this.nextKeyframe, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" });
- ContextMenu.Instance.addItem({ description: "Backup ", event: this.prevKeyframe, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" });
const options = ContextMenu.Instance.findByDescription("Options...");
const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7bb945264..b9d33da90 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1167,7 +1167,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
<div className="documentView-contentBlocker" />
</> :
this.innards}
- {(this.Document.isBackground !== undefined || this.isSelected(false)) && this.props.renderDepth > 0 && this.props.PanelWidth() > 0 ?
+ {(this.Document.isBackground !== undefined || this.isSelected(false)) && (this.Document.type === DocumentType.COL || this.Document.type === DocumentType.IMG) && this.props.renderDepth > 0 && this.props.PanelWidth() > 0 ?
<div className="documentView-lock" onClick={() => this.toggleBackground(true)}>
<FontAwesomeIcon icon={this.Document.isBackground ? "unlock" : "lock"} style={{ color: this.Document.isBackground ? "red" : undefined }} size="lg" />
</div>
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index b185d3b55..06c2e516d 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -4,14 +4,18 @@ import * as formidable from 'formidable';
import v4 = require('uuid/v4');
const AdmZip = require('adm-zip');
import { extname, basename, dirname } from 'path';
-import { createReadStream, createWriteStream, unlink } from "fs";
+import { createReadStream, createWriteStream, unlink, writeFile } from "fs";
import { publicDirectory, filesDirectory } from "..";
import { Database } from "../database";
import { DashUploadUtils, InjectSize, SizeSuffix } from "../DashUploadUtils";
import * as sharp from 'sharp';
import { AcceptibleMedia, Upload } from "../SharedMediaTypes";
import { normalize } from "path";
+import RouteSubscriber from "../RouteSubscriber";
const imageDataUri = require('image-data-uri');
+import { isWebUri } from "valid-url";
+import { launch } from "puppeteer";
+import { Opt } from "../../fields/Doc";
export enum Directory {
parsed_files = "parsed_files",
@@ -61,10 +65,38 @@ export default class UploadManager extends ApiManager {
});
register({
- method: Method.GET,
- subscription: "/hello",
- secureHandler: ({ req, res }) => {
- res.send("<h1>world!</h1>");
+ method: Method.POST,
+ subscription: new RouteSubscriber("youtubeScreenshot"),
+ secureHandler: async ({ req, res }) => {
+ const { url, t } = req.query;
+ const parseUrl = (url: string) => {
+ url = decodeURIComponent(url)
+ if (!/^(?:f|ht)tps?\:\/\//.test(url)) {
+ url = 'http://' + url
+ }
+ return url;
+ }
+ let targetUrl: string;
+ if (!url || !t || !isWebUri(targetUrl = parseUrl(url as string))) {
+ return res.send();
+ }
+ const buffer = await captureYoutubeScreenshot(targetUrl, t as string);
+ if (!buffer) {
+ return res.send();
+ }
+ const resolvedName = `${targetUrl}@${t}.png`;
+ const resolvedPath = serverPathToFile(Directory.images, resolvedName);
+ writeFile(resolvedPath, buffer, async error => {
+ if (error) {
+ return res.send();
+ }
+ await DashUploadUtils.outputResizedImages(() => createReadStream(resolvedPath), resolvedName, pathToDirectory(Directory.images));
+ res.send({
+ accessPaths: {
+ agnostic: DashUploadUtils.getAccessPaths(Directory.images, resolvedName)
+ }
+ } as Upload.FileInformation);
+ });
}
});
@@ -244,4 +276,26 @@ export default class UploadManager extends ApiManager {
}
+}
+
+/**
+ * On success, returns a buffer containing the bytes of a screenshot
+ * of the video specified by @param url at timecode @param t.
+ *
+ * On failure, returns undefined.
+ */
+async function captureYoutubeScreenshot(targetUrl: string, t: string): Promise<Opt<Buffer>> {
+ const browser = await launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
+ const page = await browser.newPage();
+ await page.setViewport({ width: 1920, height: 1080 });
+
+ await page.goto(targetUrl + '&t=' + t, { waitUntil: 'networkidle0' });
+
+ // hide youtube player controls.
+ await page.evaluate(() => (document.querySelector('.ytp-chrome-bottom') as any).style.display = 'none');
+
+ const buffer = await (await page.$('.html5-video-player'))?.screenshot({ encoding: "binary" });
+ await browser.close();
+
+ return buffer;
} \ No newline at end of file
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index b74904ada..c887aa4e6 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -257,7 +257,7 @@ export namespace DashUploadUtils {
});
}
- function getAccessPaths(directory: Directory, fileName: string) {
+ export function getAccessPaths(directory: Directory, fileName: string) {
return {
client: clientPathToFile(directory, fileName),
server: serverPathToFile(directory, fileName)