From a5da5e6246a6fd7500fed8b206fc3540be509eab Mon Sep 17 00:00:00 2001 From: Jenny Yu Date: Fri, 22 Apr 2022 19:53:44 -0400 Subject: uploading not working (cannot find ffmpeg) --- src/server/ApiManagers/UploadManager.ts | 534 ++++++++++++++++---------------- 1 file changed, 267 insertions(+), 267 deletions(-) (limited to 'src/server') diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index bfa07d47a..5a19477dd 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -19,288 +19,288 @@ import { SolrManager } from "./SearchManager"; import { StringDecoder } from "string_decoder"; export enum Directory { - parsed_files = "parsed_files", - images = "images", - videos = "videos", - pdfs = "pdfs", - text = "text", - pdf_thumbnails = "pdf_thumbnails", - audio = "audio", + parsed_files = "parsed_files", + images = "images", + videos = "videos", + pdfs = "pdfs", + text = "text", + pdf_thumbnails = "pdf_thumbnails", + audio = "audio", } export function serverPathToFile(directory: Directory, filename: string) { - return normalize(`${filesDirectory}/${directory}/${filename}`); + return normalize(`${filesDirectory}/${directory}/${filename}`); } export function pathToDirectory(directory: Directory) { - return normalize(`${filesDirectory}/${directory}`); + return normalize(`${filesDirectory}/${directory}`); } export function clientPathToFile(directory: Directory, filename: string) { - return `/files/${directory}/${filename}`; + return `/files/${directory}/${filename}`; } export default class UploadManager extends ApiManager { - protected initialize(register: Registration): void { + protected initialize(register: Registration): void { - register({ - method: Method.POST, - subscription: "/uploadFormData", - secureHandler: async ({ req, res }) => { - const form = new formidable.IncomingForm(); - form.keepExtensions = true; - form.uploadDir = pathToDirectory(Directory.parsed_files); - return new Promise(resolve => { - form.parse(req, async (_err, _fields, files) => { - const results: Upload.FileResponse[] = []; - for (const key in files) { - const f = files[key]; - if (!Array.isArray(f)) { - const result = await DashUploadUtils.upload(f); - result && !(result.result instanceof Error) && results.push(result); - } - } - _success(res, results); - resolve(); - }); - }); - } - }); + register({ + method: Method.POST, + subscription: "/uploadFormData", + secureHandler: async ({ req, res }) => { + const form = new formidable.IncomingForm(); + form.keepExtensions = true; + form.uploadDir = pathToDirectory(Directory.parsed_files); + return new Promise(resolve => { + form.parse(req, async (_err, _fields, files) => { + const results: Upload.FileResponse[] = []; + for (const key in files) { + const f = files[key]; + if (!Array.isArray(f)) { + const result = await DashUploadUtils.upload(f); + result && !(result.result instanceof Error) && results.push(result); + } + } + _success(res, results); + resolve(); + }); + }); + } + }); - register({ - method: Method.POST, - subscription: "/uploadYoutubeVideo", - secureHandler: async ({ req, res }) => { - //req.readableBuffer.head.data - return new Promise(async resolve => { - req.addListener("data", async (args) => { - console.log(args); - const payload = String.fromCharCode.apply(String, args); - const videoId = JSON.parse(payload).videoId; - const results: Upload.FileResponse[] = []; - const result = await DashUploadUtils.uploadYoutube(videoId); - result && !(result.result instanceof Error) && results.push(result); - _success(res, results); - resolve(); - }); - }); - } - }); + register({ + method: Method.POST, + subscription: "/uploadYoutubeVideo", + secureHandler: async ({ req, res }) => { + //req.readableBuffer.head.data + return new Promise(async resolve => { + req.addListener("data", async (args) => { + console.log(args); + const payload = String.fromCharCode.apply(String, args); + const videoId = JSON.parse(payload).videoId; + const results: Upload.FileResponse[] = []; + const result = await DashUploadUtils.uploadYoutube(videoId); + result && !(result.result instanceof Error) && results.push(result); + _success(res, results); + resolve(); + }); + }); + } + }); - register({ - method: Method.POST, - subscription: new RouteSubscriber("youtubeScreenshot"), - secureHandler: async ({ req, res }) => { - const { id, timecode } = req.body; - const convert = (raw: string) => { - const number = Math.floor(Number(raw)); - const seconds = number % 60; - const minutes = (number - seconds) / 60; - return `${minutes}m${seconds}s`; - }; - const suffix = timecode ? `&t=${convert(timecode)}` : ``; - const targetUrl = `https://www.youtube.com/watch?v=${id}${suffix}`; - const buffer = await captureYoutubeScreenshot(targetUrl); - if (!buffer) { - return res.send(); - } - const resolvedName = `youtube_capture_${id}_${suffix}.png`; - const resolvedPath = serverPathToFile(Directory.images, resolvedName); - return new Promise(resolve => { - writeFile(resolvedPath, buffer, async error => { - if (error) { - return res.send(); + register({ + method: Method.POST, + subscription: new RouteSubscriber("youtubeScreenshot"), + secureHandler: async ({ req, res }) => { + const { id, timecode } = req.body; + const convert = (raw: string) => { + const number = Math.floor(Number(raw)); + const seconds = number % 60; + const minutes = (number - seconds) / 60; + return `${minutes}m${seconds}s`; + }; + const suffix = timecode ? `&t=${convert(timecode)}` : ``; + const targetUrl = `https://www.youtube.com/watch?v=${id}${suffix}`; + const buffer = await captureYoutubeScreenshot(targetUrl); + if (!buffer) { + return res.send(); } - await DashUploadUtils.outputResizedImages(() => createReadStream(resolvedPath), resolvedName, pathToDirectory(Directory.images)); - res.send({ - accessPaths: { - agnostic: DashUploadUtils.getAccessPaths(Directory.images, resolvedName) - } - } as Upload.FileInformation); - resolve(); - }); - }); - } - }); + const resolvedName = `youtube_capture_${id}_${suffix}.png`; + const resolvedPath = serverPathToFile(Directory.images, resolvedName); + return new Promise(resolve => { + 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); + resolve(); + }); + }); + } + }); - register({ - method: Method.POST, - subscription: "/uploadRemoteImage", - secureHandler: async ({ req, res }) => { + register({ + method: Method.POST, + subscription: "/uploadRemoteImage", + secureHandler: async ({ req, res }) => { - const { sources } = req.body; - if (Array.isArray(sources)) { - const results = await Promise.all(sources.map(source => DashUploadUtils.UploadImage(source))); - return res.send(results); - } - res.send(); - } - }); + const { sources } = req.body; + if (Array.isArray(sources)) { + const results = await Promise.all(sources.map(source => DashUploadUtils.UploadImage(source))); + return res.send(results); + } + res.send(); + } + }); - register({ - method: Method.POST, - subscription: "/uploadDoc", - secureHandler: ({ req, res }) => { + register({ + method: Method.POST, + subscription: "/uploadDoc", + secureHandler: ({ req, res }) => { - const form = new formidable.IncomingForm(); - form.keepExtensions = true; - // let path = req.body.path; - const ids: { [id: string]: string } = {}; - let remap = true; - const getId = (id: string): string => { - if (!remap) return id; - if (id.endsWith("Proto")) return id; - if (id in ids) { - return ids[id]; - } else { - return ids[id] = v4(); - } - }; - const mapFn = (doc: any) => { - if (doc.id) { - doc.id = getId(doc.id); - } - for (const key in doc.fields) { - if (!doc.fields.hasOwnProperty(key)) { continue; } - const field = doc.fields[key]; - if (field === undefined || field === null) { continue; } + const form = new formidable.IncomingForm(); + form.keepExtensions = true; + // let path = req.body.path; + const ids: { [id: string]: string } = {}; + let remap = true; + const getId = (id: string): string => { + if (!remap) return id; + if (id.endsWith("Proto")) return id; + if (id in ids) { + return ids[id]; + } else { + return ids[id] = v4(); + } + }; + const mapFn = (doc: any) => { + if (doc.id) { + doc.id = getId(doc.id); + } + for (const key in doc.fields) { + if (!doc.fields.hasOwnProperty(key)) { continue; } + const field = doc.fields[key]; + if (field === undefined || field === null) { continue; } - if (field.__type === "Doc") { - mapFn(field); - } else if (field.__type === "proxy" || field.__type === "prefetch_proxy") { - field.fieldId = getId(field.fieldId); - } else if (field.__type === "script" || field.__type === "computed") { - if (field.captures) { - field.captures.fieldId = getId(field.captures.fieldId); - } - } else if (field.__type === "list") { - mapFn(field); - } else if (typeof field === "string") { - const re = /("(?:dataD|d)ocumentId"\s*:\s*")([\w\-]*)"/g; - doc.fields[key] = (field as any).replace(re, (match: any, p1: string, p2: string) => { - return `${p1}${getId(p2)}"`; - }); - } else if (field.__type === "RichTextField") { - const re = /("href"\s*:\s*")(.*?)"/g; - field.Data = field.Data.replace(re, (match: any, p1: string, p2: string) => { - return `${p1}${getId(p2)}"`; - }); - } - } - }; - return new Promise(resolve => { - form.parse(req, async (_err, fields, files) => { - remap = fields.remap !== "false"; - let id: string = ""; - try { - for (const name in files) { - const f = files[name]; - const path_2 = Array.isArray(f) ? "" : f.path; - const zip = new AdmZip(path_2); - zip.getEntries().forEach((entry: any) => { - if (!entry.entryName.startsWith("files/")) return; - let directory = dirname(entry.entryName) + "/"; - const extension = extname(entry.entryName); - const base = basename(entry.entryName).split(".")[0]; + if (field.__type === "Doc") { + mapFn(field); + } else if (field.__type === "proxy" || field.__type === "prefetch_proxy") { + field.fieldId = getId(field.fieldId); + } else if (field.__type === "script" || field.__type === "computed") { + if (field.captures) { + field.captures.fieldId = getId(field.captures.fieldId); + } + } else if (field.__type === "list") { + mapFn(field); + } else if (typeof field === "string") { + const re = /("(?:dataD|d)ocumentId"\s*:\s*")([\w\-]*)"/g; + doc.fields[key] = (field as any).replace(re, (match: any, p1: string, p2: string) => { + return `${p1}${getId(p2)}"`; + }); + } else if (field.__type === "RichTextField") { + const re = /("href"\s*:\s*")(.*?)"/g; + field.Data = field.Data.replace(re, (match: any, p1: string, p2: string) => { + return `${p1}${getId(p2)}"`; + }); + } + } + }; + return new Promise(resolve => { + form.parse(req, async (_err, fields, files) => { + remap = fields.remap !== "false"; + let id: string = ""; try { - zip.extractEntryTo(entry.entryName, publicDirectory, true, false); - directory = "/" + directory; + for (const name in files) { + const f = files[name]; + const path_2 = Array.isArray(f) ? "" : f.path; + const zip = new AdmZip(path_2); + zip.getEntries().forEach((entry: any) => { + if (!entry.entryName.startsWith("files/")) return; + let directory = dirname(entry.entryName) + "/"; + const extension = extname(entry.entryName); + const base = basename(entry.entryName).split(".")[0]; + try { + zip.extractEntryTo(entry.entryName, publicDirectory, true, false); + directory = "/" + directory; - createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_o" + extension)); - createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_s" + extension)); - createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_m" + extension)); - createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_l" + extension)); - } catch (e) { - console.log(e); - } - }); - const json = zip.getEntry("doc.json"); - try { - const data = JSON.parse(json.getData().toString("utf8")); - const datadocs = data.docs; - id = getId(data.id); - const docs = Object.keys(datadocs).map(key => datadocs[key]); - docs.forEach(mapFn); - await Promise.all(docs.map((doc: any) => new Promise(res => { - Database.Instance.replace(doc.id, doc, (err, r) => { - err && console.log(err); - res(); - }, true); - }))); - } catch (e) { console.log(e); } - unlink(path_2, () => { }); - } - SolrManager.update(); - res.send(JSON.stringify(id || "error")); - } catch (e) { console.log(e); } - resolve(); - }); - }); - } - }); + createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_o" + extension)); + createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_s" + extension)); + createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_m" + extension)); + createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_l" + extension)); + } catch (e) { + console.log(e); + } + }); + const json = zip.getEntry("doc.json"); + try { + const data = JSON.parse(json.getData().toString("utf8")); + const datadocs = data.docs; + id = getId(data.id); + const docs = Object.keys(datadocs).map(key => datadocs[key]); + docs.forEach(mapFn); + await Promise.all(docs.map((doc: any) => new Promise(res => { + Database.Instance.replace(doc.id, doc, (err, r) => { + err && console.log(err); + res(); + }, true); + }))); + } catch (e) { console.log(e); } + unlink(path_2, () => { }); + } + SolrManager.update(); + res.send(JSON.stringify(id || "error")); + } catch (e) { console.log(e); } + resolve(); + }); + }); + } + }); - register({ - method: Method.POST, - subscription: "/inspectImage", - secureHandler: async ({ req, res }) => { + register({ + method: Method.POST, + subscription: "/inspectImage", + secureHandler: async ({ req, res }) => { - const { source } = req.body; - if (typeof source === "string") { - return res.send(await DashUploadUtils.InspectImage(source)); - } - res.send({}); - } - }); + const { source } = req.body; + if (typeof source === "string") { + return res.send(await DashUploadUtils.InspectImage(source)); + } + res.send({}); + } + }); - register({ - method: Method.POST, - subscription: "/uploadURI", - secureHandler: ({ req, res }) => { - const uri = req.body.uri; - const filename = req.body.name; - const origSuffix = req.body.nosuffix ? SizeSuffix.None : SizeSuffix.Original; - if (!uri || !filename) { - res.status(401).send("incorrect parameters specified"); - return; - } - return imageDataUri.outputFile(uri, serverPathToFile(Directory.images, InjectSize(filename, origSuffix))).then((savedName: string) => { - const ext = extname(savedName).toLowerCase(); - const { pngs, jpgs } = AcceptableMedia; - const resizers = !origSuffix ? [{ resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }] : [ - { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" }, - { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }, - { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" }, - ]; - let isImage = false; - if (pngs.includes(ext)) { - resizers.forEach(element => { - element.resizer = element.resizer.png(); - }); - isImage = true; - } else if (jpgs.includes(ext)) { - resizers.forEach(element => { - element.resizer = element.resizer.jpeg(); - }); - isImage = true; - } - if (isImage) { - resizers.forEach(resizer => { - const path = serverPathToFile(Directory.images, filename + resizer.suffix + ext); - createReadStream(savedName).pipe(resizer.resizer).pipe(createWriteStream(path)); - }); + register({ + method: Method.POST, + subscription: "/uploadURI", + secureHandler: ({ req, res }) => { + const uri = req.body.uri; + const filename = req.body.name; + const origSuffix = req.body.nosuffix ? SizeSuffix.None : SizeSuffix.Original; + if (!uri || !filename) { + res.status(401).send("incorrect parameters specified"); + return; + } + return imageDataUri.outputFile(uri, serverPathToFile(Directory.images, InjectSize(filename, origSuffix))).then((savedName: string) => { + const ext = extname(savedName).toLowerCase(); + const { pngs, jpgs } = AcceptableMedia; + const resizers = !origSuffix ? [{ resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }] : [ + { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" }, + { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }, + { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" }, + ]; + let isImage = false; + if (pngs.includes(ext)) { + resizers.forEach(element => { + element.resizer = element.resizer.png(); + }); + isImage = true; + } else if (jpgs.includes(ext)) { + resizers.forEach(element => { + element.resizer = element.resizer.jpeg(); + }); + isImage = true; + } + if (isImage) { + resizers.forEach(resizer => { + const path = serverPathToFile(Directory.images, filename + resizer.suffix + ext); + createReadStream(savedName).pipe(resizer.resizer).pipe(createWriteStream(path)); + }); - } - res.send(clientPathToFile(Directory.images, filename + ext)); - }); - } - }); + } + res.send(clientPathToFile(Directory.images, filename + ext)); + }); + } + }); - } + } } function delay(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise(resolve => setTimeout(resolve, ms)); } /** * On success, returns a buffer containing the bytes of a screenshot @@ -309,25 +309,25 @@ function delay(ms: number) { * On failure, returns undefined. */ async function captureYoutubeScreenshot(targetUrl: string) { - // const browser = await launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] }); - // const page = await browser.newPage(); - // // await page.setViewport({ width: 1920, height: 1080 }); + // 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, { waitUntil: 'domcontentloaded' as any }); + // // await page.goto(targetUrl, { waitUntil: 'domcontentloaded' as any }); - // const videoPlayer = await page.$('.html5-video-player'); - // videoPlayer && await page.focus("video"); - // await delay(7000); - // const ad = await page.$('.ytp-ad-skip-button-text'); - // await ad?.click(); - // await videoPlayer?.click(); - // await delay(1000); - // // hide youtube player controls. - // await page.evaluate(() => (document.querySelector('.ytp-chrome-bottom') as HTMLElement).style.display = 'none'); + // const videoPlayer = await page.$('.html5-video-player'); + // videoPlayer && await page.focus("video"); + // await delay(7000); + // const ad = await page.$('.ytp-ad-skip-button-text'); + // await ad?.click(); + // await videoPlayer?.click(); + // await delay(1000); + // // hide youtube player controls. + // await page.evaluate(() => (document.querySelector('.ytp-chrome-bottom') as HTMLElement).style.display = 'none'); - // const buffer = await videoPlayer?.screenshot({ encoding: "binary" }); - // await browser.close(); + // const buffer = await videoPlayer?.screenshot({ encoding: "binary" }); + // await browser.close(); - // return buffer; - return null; + // return buffer; + return null; } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From f4b6942fc1cad1f7e7ec7552e22f6c56bc158a77 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 26 Apr 2022 14:35:49 -0400 Subject: made creating a new thumbnail icon delete previous ones. fixed bug where documents would re-render if an earlier docuent in the collection list was added/removed. --- .../collectionFreeForm/CollectionFreeFormView.tsx | 7 +++---- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 3 +-- src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 5 +++-- src/client/views/nodes/WebBox.tsx | 2 +- src/server/ApiManagers/UploadManager.ts | 12 ++++++++---- 6 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src/server') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a14405a0b..bdae5a4f8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1147,7 +1147,7 @@ export class CollectionFreeFormView extends CollectionSubView this.props.isSelected() || this.props.isContentActive(); - getChildDocView(entry: PoolData, renderIndex: number) { + getChildDocView(entry: PoolData) { const childLayout = entry.pair.layout; const childData = entry.pair.data; const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine); @@ -1156,7 +1156,6 @@ export class CollectionFreeFormView extends CollectionSubView this.isCurrent(entry[1].pair.layout)).forEach((entry, i) => elements.push({ - ele: this.getChildDocView(entry[1], i), + ele: this.getChildDocView(entry[1]), bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica) })); @@ -1436,7 +1435,7 @@ export class CollectionFreeFormView extends CollectionSubView { - VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), true).then( + VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), true, this.layoutDoc[Id] + "-icon").then( returnedfilename => setTimeout(action(() => { this.dataDoc.icon = new ImageField(returnedfilename); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 6097425e1..3f16d3c49 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,4 +1,4 @@ -import { action, computed, observable } from "mobx"; +import { action, computed, observable, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, Opt } from "../../../fields/Doc"; import { List } from "../../../fields/List"; @@ -28,7 +28,6 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { jitterRotation: number; dataTransition?: string; replica: string; - renderIndex: number; CollectionFreeFormView: CollectionFreeFormView; } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 54c4be24d..23749d479 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -93,7 +93,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { - VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), true).then( + VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), true, this.layoutDoc[Id] + "-icon").then( returnedfilename => setTimeout(action(() => { this.dataDoc.icon = new ImageField(returnedfilename); this.dataDoc["icon-nativeWidth"] = nativeWidth; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index c31d38b0d..e57cb1abe 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -53,14 +53,15 @@ export class VideoBox extends ViewBoxAnnotatableComponent { - VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-thumb" + (new Date()).getTime(), true).then( + VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), true, this.layoutDoc[Id] + "-icon").then( returnedfilename => setTimeout(action(() => this.layoutDoc.thumb = new ImageField(returnedfilename)), 500)); }) .catch(function (error: any) { diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index bfa07d47a..5e0cd67cc 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -3,7 +3,7 @@ import { Method, _success } from "../RouteManager"; import * as formidable from 'formidable'; import v4 = require('uuid/v4'); const AdmZip = require('adm-zip'); -import { extname, basename, dirname } from 'path'; +import { extname, basename, dirname, } from 'path'; import { createReadStream, createWriteStream, unlink, writeFile } from "fs"; import { publicDirectory, filesDirectory } from ".."; import { Database } from "../database"; @@ -13,10 +13,8 @@ import { AcceptableMedia, Upload } from "../SharedMediaTypes"; import { normalize } from "path"; import RouteSubscriber from "../RouteSubscriber"; const imageDataUri = require('image-data-uri'); -import { isWebUri } from "valid-url"; -import { Opt } from "../../fields/Doc"; import { SolrManager } from "./SearchManager"; -import { StringDecoder } from "string_decoder"; +let fs = require('fs'); export enum Directory { parsed_files = "parsed_files", @@ -260,10 +258,16 @@ export default class UploadManager extends ApiManager { const uri = req.body.uri; const filename = req.body.name; const origSuffix = req.body.nosuffix ? SizeSuffix.None : SizeSuffix.Original; + const deleteFiles = req.body.replaceRootFilename; if (!uri || !filename) { res.status(401).send("incorrect parameters specified"); return; } + if (deleteFiles) { + const path = serverPathToFile(Directory.images, ""); + let regex = new RegExp(`${deleteFiles}.*`); + fs.readdirSync(path).filter((f: any) => regex.test(f)).map((f: any) => fs.unlinkSync(path + f)); + } return imageDataUri.outputFile(uri, serverPathToFile(Directory.images, InjectSize(filename, origSuffix))).then((savedName: string) => { const ext = extname(savedName).toLowerCase(); const { pngs, jpgs } = AcceptableMedia; -- cgit v1.2.3-70-g09d2 From 8c14a52dbbd57db316d1f807a49cf5752c574e06 Mon Sep 17 00:00:00 2001 From: geireann Date: Tue, 26 Apr 2022 16:49:48 -0400 Subject: Update applied_session_agent.ts --- src/server/DashSession/Session/agents/applied_session_agent.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/server/DashSession/Session/agents/applied_session_agent.ts b/src/server/DashSession/Session/agents/applied_session_agent.ts index 12064668b..8339a06dc 100644 --- a/src/server/DashSession/Session/agents/applied_session_agent.ts +++ b/src/server/DashSession/Session/agents/applied_session_agent.ts @@ -9,8 +9,8 @@ export abstract class AppliedSessionAgent { // the following two methods allow the developer to create a custom // session and use the built in customization options for each thread - protected abstract async initializeMonitor(monitor: Monitor): Promise; - protected abstract async initializeServerWorker(): Promise; + protected abstract initializeMonitor(monitor: Monitor): Promise; + protected abstract initializeServerWorker(): Promise; private launched = false; -- cgit v1.2.3-70-g09d2 From 91c6f0a2ec6b0e55d9d07009eecc8c2b8856af6a Mon Sep 17 00:00:00 2001 From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com> Date: Wed, 27 Apr 2022 12:03:51 -0400 Subject: attempting to fix server topology issues --- src/server/database.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/server') diff --git a/src/server/database.ts b/src/server/database.ts index 2a55c14de..4d77c7a0d 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -34,7 +34,13 @@ export namespace Database { console.log(`mongoose established default connection at ${url}`); resolve(); }); - mongoose.connect(url, { useNewUrlParser: true, useUnifiedTopology: true, dbName: schema }); + mongoose.connect(url, { + useNewUrlParser: true, + useUnifiedTopology: true, + dbName: schema, + reconnectTries: Number.MAX_VALUE, + reconnectInterval: 1000, + }); }); } } catch (e) { -- cgit v1.2.3-70-g09d2 From 59a22f3a007b201e68ac2f3e1d62e0ca5e66488a Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 28 Apr 2022 12:13:44 -0400 Subject: fixed feedback dragging link button. fixed warnings. added some assymetric linkRelationships. --- src/client/documents/Documents.ts | 3 ++- src/client/util/DocumentManager.ts | 2 +- src/client/util/LinkManager.ts | 2 +- src/client/views/SidebarAnnos.tsx | 2 +- .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../views/collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/linking/LinkMenu.tsx | 4 +--- src/client/views/nodes/DocumentLinksButton.scss | 2 ++ src/client/views/nodes/DocumentLinksButton.tsx | 10 +++++----- src/client/views/nodes/DocumentView.tsx | 4 ++-- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 4 ++-- src/client/views/nodes/formattedText/RichTextRules.ts | 2 +- src/client/views/search/SearchBox.tsx | 2 +- src/server/ApiManagers/UploadManager.ts | 4 ++-- 15 files changed, 24 insertions(+), 23 deletions(-) (limited to 'src/server') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0bb873667..087d32a60 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1094,10 +1094,11 @@ export namespace DocUtils { export function MakeLinkToActiveAudio(getSourceDoc: () => Doc, broadcastEvent = true) { broadcastEvent && runInAction(() => DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1); return DocUtils.ActiveRecordings.map(audio => - DocUtils.MakeLink({ doc: getSourceDoc() }, { doc: audio.getAnchor() || audio.props.Document }, "recording link", "recording timeline")); + DocUtils.MakeLink({ doc: getSourceDoc() }, { doc: audio.getAnchor() || audio.props.Document }, "recording annotation:linked recording", "recording timeline")); } export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = "", description: string = "", id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) { + if (!linkRelationship) linkRelationship = target.doc.type === DocumentType.RTF ? "Commentary:Comments On" : "link"; const sv = DocumentManager.Instance.getDocumentView(source.doc); if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target.doc) return; if (target.doc === Doc.UserDoc()) return undefined; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 412d5a169..b6c28d2fe 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -167,7 +167,7 @@ export class DocumentManager { ): Promise => { originalTarget = originalTarget ?? targetDoc; const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView; - var docView = getFirstDocView(targetDoc, originatingDoc); + const docView = getFirstDocView(targetDoc, originatingDoc); const annotatedDoc = Cast(targetDoc.annotationOn, Doc, null); const resolvedTarget = targetDoc.type === DocumentType.MARKER ? annotatedDoc ?? targetDoc : targetDoc; // if target is a marker, then focus toggling should apply to the document it's on since the marker itself doesn't have a hidden field var wasHidden = resolvedTarget.hidden; diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 7ba7a1d4c..9445533dc 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -152,7 +152,7 @@ export class LinkManager { this.relatedLinker(anchor).forEach(link => { if (link.linkRelationship && link.linkRelationship !== "-ungrouped-") { const relation = StrCast(link.linkRelationship); - const anchorRelation = relation.indexOf(":") ? relation.split(":")[Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), anchor) ? 0 : 1] : relation; + const anchorRelation = relation.indexOf(":") !== -1 ? relation.split(":")[Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), anchor) ? 0 : 1] : relation; const group = anchorGroups.get(anchorRelation); anchorGroups.set(anchorRelation, group ? [...group, link] : [link]); } else { diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 43a02d029..04c0565ea 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -61,7 +61,7 @@ export class SidebarAnnos extends React.Component { FormattedTextBox.SelectOnLoad = target[Id]; FormattedTextBox.DontSelectInitialText = true; this.allMetadata.map(tag => target[tag] = tag); - DocUtils.MakeLink({ doc: anchor }, { doc: target }, "inline markup"); + DocUtils.MakeLink({ doc: anchor }, { doc: target }, "inline comment:comment on"); this.addDocument(target); this._stackRef.current?.focusDocument(target); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index f0b3d70a0..3f72052ae 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -278,7 +278,7 @@ export class CollectionFreeFormView extends CollectionSubView : -
+
{this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? //if the origin node is not this node -
DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)}> @@ -256,7 +255,8 @@ export class DocumentLinksButton extends React.Component +
: diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9d738180b..8570f6fff 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -663,7 +663,7 @@ export class DocumentViewInternal extends DocComponent d.anchor1 === this.props.Document); if (!portalLink) { const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _fitWidth: true, title: StrCast(this.props.Document.title) + " [Portal]" }); - DocUtils.MakeLink({ doc: this.props.Document }, { doc: portal }, "portal to"); + DocUtils.MakeLink({ doc: this.props.Document }, { doc: portal }, "portal to:portal from"); } this.Document.followLinkLocation = "inPlace"; this.Document.followLinkZoom = true; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index aadad5ffa..5982d4d66 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -152,7 +152,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { this.Document._curPage = Math.max(1, (NumCast(this.Document._curPage) || 1) - 1); return true; - }; + } public forwardPage = () => { this.Document._curPage = Math.min(NumCast(this.dataDoc[this.props.fieldKey + "-numPages"]), (NumCast(this.Document._curPage) || 1) + 1); return true; - }; + } public gotoPage = (p: number) => this.Document._curPage = p; @undoBatch diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index 00c03875b..427e05edb 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -275,7 +275,7 @@ export class RichTextRules { this.TextBox.EditorView?.dispatch(rstate.tr.setSelection(new TextSelection(rstate.doc.resolve(start), rstate.doc.resolve(end - 3)))); } const target = ((docx instanceof Doc) && docx) || Docs.Create.FreeformDocument([], { title: rawdocid.replace(/^:/, ""), _width: 500, _height: 500, }, docid); - DocUtils.MakeLink({ doc: this.TextBox.getAnchor() }, { doc: target }, "portal to", undefined); + DocUtils.MakeLink({ doc: this.TextBox.getAnchor() }, { doc: target }, "portal to:portal from", undefined); const fstate = this.TextBox.EditorView?.state; if (fstate && selection) { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 5fe2a5ab1..9257cb75e 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -112,7 +112,7 @@ export class SearchBox extends ViewBoxBaseComponent() { if (this.props.linkFrom) { const linkFrom = this.props.linkFrom(); if (linkFrom) { - DocUtils.MakeLink({ doc: linkFrom }, { doc: linkTo }, "Link"); + DocUtils.MakeLink({ doc: linkFrom }, { doc: linkTo }); } } }); diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 5e0cd67cc..83a2bc79b 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -14,7 +14,7 @@ import { normalize } from "path"; import RouteSubscriber from "../RouteSubscriber"; const imageDataUri = require('image-data-uri'); import { SolrManager } from "./SearchManager"; -let fs = require('fs'); +const fs = require('fs'); export enum Directory { parsed_files = "parsed_files", @@ -265,7 +265,7 @@ export default class UploadManager extends ApiManager { } if (deleteFiles) { const path = serverPathToFile(Directory.images, ""); - let regex = new RegExp(`${deleteFiles}.*`); + const regex = new RegExp(`${deleteFiles}.*`); fs.readdirSync(path).filter((f: any) => regex.test(f)).map((f: any) => fs.unlinkSync(path + f)); } return imageDataUri.outputFile(uri, serverPathToFile(Directory.images, InjectSize(filename, origSuffix))).then((savedName: string) => { -- cgit v1.2.3-70-g09d2 From 0b1c54427cef9a50793ab157bcaa0e6bd8b182a6 Mon Sep 17 00:00:00 2001 From: Geireann <60007097+geireann@users.noreply.github.com> Date: Thu, 28 Apr 2022 13:52:14 -0400 Subject: Update database.ts --- src/server/database.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/server/database.ts b/src/server/database.ts index 4d77c7a0d..725b66836 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -38,8 +38,8 @@ export namespace Database { useNewUrlParser: true, useUnifiedTopology: true, dbName: schema, - reconnectTries: Number.MAX_VALUE, - reconnectInterval: 1000, + // reconnectTries: Number.MAX_VALUE, + // reconnectInterval: 1000, }); }); } -- cgit v1.2.3-70-g09d2 From 10dda7683987a7d0735478374af1a256bca8e7f1 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 29 Apr 2022 20:37:22 -0400 Subject: another fix for Label's BigText to make multiline work better. fixed server bug for 'write after end' when servering web pages. --- src/client/views/nodes/LabelBigText.js | 46 +++++++++++++++++++++------------- src/client/views/nodes/LabelBox.tsx | 15 +++++------ src/server/server_Initialization.ts | 25 ++++++++++++------ 3 files changed, 55 insertions(+), 31 deletions(-) (limited to 'src/server') diff --git a/src/client/views/nodes/LabelBigText.js b/src/client/views/nodes/LabelBigText.js index 6a212d9ea..290152cd0 100644 --- a/src/client/views/nodes/LabelBigText.js +++ b/src/client/views/nodes/LabelBigText.js @@ -100,7 +100,8 @@ export default function BigText(element, options) { horizontalAlign: "center", verticalAlign: "center", textAlign: "center", - whiteSpace: "nowrap" + whiteSpace: "nowrap", + singleLine: true }; //Merge provided options and default options @@ -111,20 +112,29 @@ export default function BigText(element, options) { //Get variables which we will reference frequently var style = element.style; - var computedStyle = document.defaultView.getComputedStyle(element); var parent = element.parentNode; var parentStyle = parent.style; var parentComputedStyle = document.defaultView.getComputedStyle(parent); //hides the element to prevent "flashing" style.visibility = "hidden"; - //Set some properties style.display = "inline-block"; style.clear = "both"; style.float = "left"; - style.fontSize = (1000 * options.fontSizeFactor) + "px"; - style.lineHeight = "1000px"; + var fontSize = options.maximumFontSize; + if (options.singleLine) { + style.fontSize = (fontSize * options.fontSizeFactor) + "px"; + style.lineHeight = fontSize + "px"; + } else { + for (; fontSize > options.minimumFontSize; fontSize = fontSize - Math.min(fontSize / 2, Math.max(0, fontSize - 48) + 2)) { + style.fontSize = (fontSize * options.fontSizeFactor) + "px"; + style.lineHeight = "1"; + if (element.offsetHeight <= +parentComputedStyle.height.replace("px", "")) { + break; + } + } + } style.whiteSpace = options.whiteSpace; style.textAlign = options.textAlign; style.position = "relative"; @@ -132,6 +142,7 @@ export default function BigText(element, options) { style.margin = 0; style.left = "50%"; style.top = "50%"; + var computedStyle = document.defaultView.getComputedStyle(element); //Get properties of parent to allow easier referencing later. var parentPadding = { @@ -175,19 +186,20 @@ export default function BigText(element, options) { box.height = element.offsetWidth * sine + element.offsetHeight * cosine; } - var widthFactor = (parentInnerWidth - parentPadding.left - parentPadding.right) / box.width; - var heightFactor = (parentInnerHeight - parentPadding.top - parentPadding.bottom) / box.height; + var parentWidth = (parentInnerWidth - parentPadding.left - parentPadding.right); + var parentHeight = (parentInnerHeight - parentPadding.top - parentPadding.bottom); + var widthFactor = parentWidth / box.width; + var heightFactor = parentHeight / box.height; var lineHeight; if (options.limitingDimension.toLowerCase() === "width") { - lineHeight = Math.floor(widthFactor * 1000); - parentStyle.height = lineHeight + "px"; + lineHeight = Math.floor(widthFactor * fontSize); } else if (options.limitingDimension.toLowerCase() === "height") { - lineHeight = Math.floor(heightFactor * 1000); + lineHeight = Math.floor(heightFactor * fontSize); } else if (widthFactor < heightFactor) - lineHeight = Math.floor(widthFactor * 1000); + lineHeight = Math.floor(widthFactor * fontSize); else if (widthFactor >= heightFactor) - lineHeight = Math.floor(heightFactor * 1000); + lineHeight = Math.floor(heightFactor * fontSize); var fontSize = lineHeight * options.fontSizeFactor; if (fontSize < options.minimumFontSize) { @@ -214,11 +226,11 @@ export default function BigText(element, options) { style.marginBottom = "0px"; style.marginRight = "0px"; - if (options.limitingDimension.toLowerCase() === "height") { - //this option needs the font-size to be set already so computedStyle.getPropertyValue("width") returns the right size - //this +4 is to compensate the rounding erros that can occur due to the calls to Math.floor in the centering code - parentStyle.width = (parseInt(computedStyle.getPropertyValue("width")) + 4) + "px"; - } + // if (options.limitingDimension.toLowerCase() === "height") { + // //this option needs the font-size to be set already so computedStyle.getPropertyValue("width") returns the right size + // //this +4 is to compensate the rounding erros that can occur due to the calls to Math.floor in the centering code + // parentStyle.width = (parseInt(computedStyle.getPropertyValue("width")) + 4) + "px"; + // } //Calculate the inner width and height var innerDimensions = _calculateInnerDimensions(computedStyle); diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 1a28fc318..2ff2adafa 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { Doc, DocListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; -import { Cast, StrCast, NumCast } from '../../../fields/Types'; +import { Cast, StrCast, NumCast, BoolCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; @@ -82,13 +82,14 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro const params = { rotateText: null, fontSizeFactor: 1, - minimumFontSize: NumCast(this.layoutDoc._minFontSize), - maximumFontSize: NumCast(this.layoutDoc._maxFontSize), + minimumFontSize: NumCast(this.rootDoc._minFontSize, 2), + maximumFontSize: NumCast(this.rootDoc._maxFontSize, 1000), limitingDimension: "both", horizontalAlign: "center", verticalAlign: "center", textAlign: "center", - whiteSpace: this.layoutDoc._singleLine ? "nowrap" : "pre-wrap" + singleLine: BoolCast(this.rootDoc._singleLine), + whiteSpace: this.rootDoc._singleLine ? "nowrap" : "pre-wrap" }; this._timeout = undefined; if (!r) return params; @@ -98,7 +99,7 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro parentStyle.display = ""; parentStyle.alignItems = ""; r.setAttribute("style", ""); - r.style.width = this.layoutDoc._singleLine ? "" : "100%"; + r.style.width = this.rootDoc._singleLine ? "" : "100%"; r.style.textOverflow = "ellipsis"; r.style.overflow = "hidden"; @@ -129,9 +130,9 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro paddingBottom: NumCast(this.rootDoc._yPadding), width: this.props.PanelWidth(), height: this.props.PanelHeight(), - whiteSpace: this.layoutDoc._singleLine ? "pre" : "pre-wrap" + whiteSpace: this.rootDoc._singleLine ? "pre" : "pre-wrap" }} > - this.fitTextToBox(r))}> + this.fitTextToBox(r))}> {label.startsWith("#") ? (null) : label.replace(/([\.\-&])/g, "$1 ")}
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 24cc3b796..81ed0d2a1 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -193,11 +193,11 @@ function proxyServe(req: any, requrl: string, response: any) { return `href="${resolvedServerUrl + "/corsProxy/http" + href}"`; }; const zipToStringDecoder = new (require('string_decoder').StringDecoder)('utf8'); - // const htmlText = zipToStringDecoder.write(zlib.gunzipSync(htmlBodyMemoryStream.read()).toString('utf8') - // .replace('', ' ') - // .replace(/href="http([^"]*)"/g, replacer) - // .replace(/target="_blank"/g, "")); - // rewrittenHtmlBody = zlib.gzipSync(htmlText); + const htmlText = zipToStringDecoder.write(zlib.gunzipSync(htmlBodyMemoryStream.read()).toString('utf8') + .replace('', ' ') + .replace(/href="http([^"]*)"/g, replacer) + .replace(/target="_blank"/g, "")); + rewrittenHtmlBody = zlib.gzipSync(htmlText); const bodyStream = htmlBodyMemoryStream.read(); if (bodyStream) { const htmlText = zipToStringDecoder.write(zlib.gunzipSync(bodyStream).toString('utf8') @@ -208,14 +208,25 @@ function proxyServe(req: any, requrl: string, response: any) { } else { console.log("EMPTY body: href"); } - } catch (e) { console.log(e); } + } catch (e) { + console.log("EROR?: ", e); + } } }); }) .on('data', (e: any) => { - rewrittenHtmlBody && response.send(rewrittenHtmlBody); + try { + if (!response.connection.writable) { + rewrittenHtmlBody && response.send(rewrittenHtmlBody); + } + } catch (e) { + console.log("ERROR data : ", e); + } rewrittenHtmlBody = undefined; }) + .on('error', (e: any) => { + console.log("ERROR ON SERVER: ", e); + }) .pipe(response); }) .pipe(htmlBodyMemoryStream); -- cgit v1.2.3-70-g09d2 From 38e14d3eec79e40317bfd64388dd9bad97a24aff Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 29 Apr 2022 23:40:38 -0400 Subject: fixes to webpage proxying. fixes for images (and clippings) to use appropriate sampled image. --- src/client/views/nodes/ImageBox.tsx | 4 ++-- src/server/server_Initialization.ts | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/server') diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 5982d4d66..d061cdd0b 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -72,10 +72,10 @@ export class ImageBox extends ViewBoxAnnotatableComponent ( { forceFull: this.props.renderDepth < 1 || this.layoutDoc._showFullRes, - scrSize: this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0], + scrSize: this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0] / this.nativeSize.nativeWidth, selected: this.props.isSelected() }), - ({ forceFull, scrSize, selected }) => this._curSuffix = this.fieldKey === "icon" ? "_m" : forceFull ? "_o" : scrSize < 100 ? "_s" : scrSize < 400 ? "_m" : scrSize < 800 || !selected ? "_l" : "_o", + ({ forceFull, scrSize, selected }) => this._curSuffix = this.fieldKey === "icon" ? "_m" : forceFull ? "_o" : scrSize < 0.25 ? "_s" : scrSize < 0.5 ? "_m" : scrSize < 0.8 || !selected ? "_l" : "_o", { fireImmediately: true, delay: 1000 }); this._disposers.path = reaction(() => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }), ({ nativeSize, width }) => { diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 81ed0d2a1..5bfd0213c 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -193,16 +193,11 @@ function proxyServe(req: any, requrl: string, response: any) { return `href="${resolvedServerUrl + "/corsProxy/http" + href}"`; }; const zipToStringDecoder = new (require('string_decoder').StringDecoder)('utf8'); - const htmlText = zipToStringDecoder.write(zlib.gunzipSync(htmlBodyMemoryStream.read()).toString('utf8') - .replace('', ' ') - .replace(/href="http([^"]*)"/g, replacer) - .replace(/target="_blank"/g, "")); - rewrittenHtmlBody = zlib.gzipSync(htmlText); const bodyStream = htmlBodyMemoryStream.read(); if (bodyStream) { const htmlText = zipToStringDecoder.write(zlib.gunzipSync(bodyStream).toString('utf8') .replace('', ' ') - // .replace(/href="http([^"]*)"/g, replacer) + .replace(/href="https?([^"]*)"/g, replacer) .replace(/target="_blank"/g, "")); rewrittenHtmlBody = zlib.gzipSync(htmlText); } else { @@ -216,7 +211,7 @@ function proxyServe(req: any, requrl: string, response: any) { }) .on('data', (e: any) => { try { - if (!response.connection.writable) { + if (response.connection?.writable) { rewrittenHtmlBody && response.send(rewrittenHtmlBody); } } catch (e) { @@ -237,12 +232,17 @@ function registerEmbeddedBrowseRelativePathHandler(server: express.Express) { const relativeUrl = req.originalUrl; if (!req.user) res.redirect("/home"); // When no user is logged in, we interpret a relative URL as being a reference to something they don't have access to and redirect to /home else if (!res.headersSent && req.headers.referer?.includes("corsProxy")) { // a request for something by a proxied referrer means it must be a relative reference. So construct a proxied absolute reference here. - const proxiedRefererUrl = decodeURIComponent(req.headers.referer); // (e.g., http://localhost:/corsProxy/https://en.wikipedia.org/wiki/Engelbart) - const dashServerUrl = proxiedRefererUrl.match(/.*corsProxy\//)![0]; // the dash server url (e.g.: http://localhost:/corsProxy/ ) - const actualReferUrl = proxiedRefererUrl.replace(dashServerUrl, ""); // the url of the referer without the proxy (e.g., : http:s//en.wikipedia.org/wiki/Engelbart) - const absoluteTargetBaseUrl = actualReferUrl.match(/http[s]?:\/\/[^\/]*/)![0]; // the base of the original url (e.g., https://en.wikipedia.org) - const redirectedProxiedUrl = dashServerUrl + encodeURIComponent(absoluteTargetBaseUrl + relativeUrl); // the new proxied full url (e..g, http://localhost:/corsProxy/https://en.wikipedia.org/) - res.redirect(redirectedProxiedUrl); + try { + const proxiedRefererUrl = decodeURIComponent(req.headers.referer); // (e.g., http://localhost:/corsProxy/https://en.wikipedia.org/wiki/Engelbart) + const dashServerUrl = proxiedRefererUrl.match(/.*corsProxy\//)![0]; // the dash server url (e.g.: http://localhost:/corsProxy/ ) + const actualReferUrl = proxiedRefererUrl.replace(dashServerUrl, ""); // the url of the referer without the proxy (e.g., : http:s//en.wikipedia.org/wiki/Engelbart) + const absoluteTargetBaseUrl = actualReferUrl.match(/https?:\/\/[^\/]*/)![0]; // the base of the original url (e.g., https://en.wikipedia.org) + const redirectedProxiedUrl = dashServerUrl + encodeURIComponent(absoluteTargetBaseUrl + relativeUrl); // the new proxied full url (e..g, http://localhost:/corsProxy/https://en.wikipedia.org/) + if (relativeUrl.startsWith("//")) res.redirect("http:" + relativeUrl); + else res.redirect(redirectedProxiedUrl); + } catch (e) { + console.log("Error embed: ", e); + } } else if (relativeUrl.startsWith("/search") && !req.headers.referer?.includes("corsProxy")) { // detect search query and use default search engine res.redirect(req.headers.referer + "corsProxy/" + encodeURIComponent("http://www.google.com" + relativeUrl)); } else { -- cgit v1.2.3-70-g09d2 From e40a1e248da90af698d5ff64bd5d63d11211e6dc Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 13 May 2022 11:58:10 -0400 Subject: fixed crashing bug when quickly re-updating webbox (or other) icon. fixed infinite loop in FilterBox. changed TimeView to scale WebBox's. fixed issues with timeView filters. fixed bugs with webBox scrolling on startup, following links, etc. --- .../views/collections/CollectionTimeView.tsx | 18 +-- .../CollectionFreeFormLayoutEngines.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- src/client/views/nodes/ComparisonBox.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 23 ++-- src/client/views/nodes/FilterBox.tsx | 10 +- src/client/views/nodes/WebBox.tsx | 136 +++++++++++---------- src/client/views/pdf/Annotation.tsx | 37 +++--- src/client/views/pdf/PDFViewer.tsx | 2 +- src/client/views/search/SearchBox.tsx | 4 +- src/fields/Doc.ts | 32 ++++- src/server/ApiManagers/UploadManager.ts | 14 ++- 12 files changed, 166 insertions(+), 118 deletions(-) (limited to 'src/server') diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index e63ea7151..4f6f45d2f 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -10,6 +10,7 @@ import { ComputedField, ScriptField } from "../../../fields/ScriptField"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { emptyFunction, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents } from "../../../Utils"; import { Docs } from "../../documents/Documents"; +import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from "../../util/DocumentManager"; import { ScriptingGlobals } from "../../util/ScriptingGlobals"; import { ContextMenu } from "../ContextMenu"; @@ -128,6 +129,7 @@ export class CollectionTimeView extends CollectionSubView() { } } + dontScaleFilter = (doc: Doc) => doc.type === DocumentType.RTF; @computed get contents() { return
@@ -137,6 +139,7 @@ export class CollectionTimeView extends CollectionSubView() { childClickScript={this._childClickedScript} viewDefDivClick={this._viewDefDivClick} childFreezeDimensions={true} + dontScaleFilter={this.dontScaleFilter} layoutEngine={this.layoutEngine} />
; } @@ -174,7 +177,7 @@ export class CollectionTimeView extends CollectionSubView() { typeof (pair.layout[fieldKey]) === "string").filter(fieldKey => fieldKey[0] !== "_" && (fieldKey[0] !== "#" || fieldKey === "#") && (fieldKey === "tags" || fieldKey[0] === toUpper(fieldKey)[0])).map(fieldKey => keySet.add(fieldKey))); Array.from(keySet).map(fieldKey => docItems.push({ description: ":" + fieldKey, event: () => this.layoutDoc._pivotField = fieldKey, icon: "compress-arrows-alt" })); - docItems.push({ description: ":(null)", event: () => this.layoutDoc._pivotField = undefined, icon: "compress-arrows-alt" }); + docItems.push({ description: ":default", event: () => this.layoutDoc._pivotField = undefined, icon: "compress-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Pivot Fields ...", subitems: docItems, icon: "eye" }); const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(x, y); ContextMenu.Instance.displayMenu(x, y, ":"); @@ -234,16 +237,17 @@ export class CollectionTimeView extends CollectionSubView() { } ScriptingGlobals.add(function pivotColumnClick(pivotDoc: Doc, bounds: ViewDefBounds) { + const pivotField = StrCast(pivotDoc._pivotField) || "author"; let prevFilterIndex = NumCast(pivotDoc._prevFilterIndex); const originalFilter = StrListCast(ObjectField.MakeCopy(pivotDoc._docFilters as ObjectField)); pivotDoc["_prevDocFilter" + prevFilterIndex] = ObjectField.MakeCopy(pivotDoc._docFilters as ObjectField); pivotDoc["_prevDocRangeFilters" + prevFilterIndex] = ObjectField.MakeCopy(pivotDoc._docRangeFilters as ObjectField); - pivotDoc["_prevPivotFields" + prevFilterIndex] = pivotDoc._pivotField; + pivotDoc["_prevPivotFields" + prevFilterIndex] = pivotField; pivotDoc._prevFilterIndex = ++prevFilterIndex; - runInAction(() => { - pivotDoc._docFilters = new List(); + pivotDoc._docFilters = new List(); + setTimeout(action(() => { const filterVals = (bounds.payload as string[]); - filterVals.map(filterVal => Doc.setDocFilter(pivotDoc, StrCast(pivotDoc._pivotField), filterVal, "check")); + filterVals.map(filterVal => Doc.setDocFilter(pivotDoc, pivotField, filterVal, "check")); const pivotView = DocumentManager.Instance.getDocumentView(pivotDoc); if (pivotDoc && pivotView?.ComponentView instanceof CollectionTimeView && filterVals.length === 1) { if (pivotView?.ComponentView.childDocs.length && pivotView.ComponentView.childDocs[0][filterVals[0]]) { @@ -252,11 +256,11 @@ ScriptingGlobals.add(function pivotColumnClick(pivotDoc: Doc, bounds: ViewDefBou } const newFilters = StrListCast(pivotDoc._docFilters); if (newFilters.length && originalFilter.length && - newFilters[newFilters.length - 1] === originalFilter[originalFilter.length - 1]) { + newFilters.lastElement() === originalFilter.lastElement()) { pivotDoc._prevFilterIndex = --prevFilterIndex; pivotDoc["_prevDocFilter" + prevFilterIndex] = undefined; pivotDoc["_prevDocRangeFilters" + prevFilterIndex] = undefined; pivotDoc["_prevPivotFields" + prevFilterIndex] = undefined; } - }); + })); }); \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 16c7df311..9de2cfcf9 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -147,7 +147,7 @@ export function computePivotLayout( const pivotColumnGroups = new Map, PivotColumn>(); let nonNumbers = 0; - const pivotFieldKey = toLabel(engineProps?.pivotField ?? pivotDoc._pivotField); + const pivotFieldKey = toLabel(engineProps?.pivotField ?? pivotDoc._pivotField) || "author"; childPairs.map(pair => { const lval = pivotFieldKey === "#" || pivotFieldKey === "tags" ? Array.from(Object.keys(Doc.GetProto(pair.layout))).filter(k => k.startsWith("#")).map(k => k.substring(1)) : Cast(pair.layout[pivotFieldKey], listSpec("string"), null); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 19b6612b0..4f79d19ad 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -75,6 +75,7 @@ export type collectionFreeformViewProps = { scaleField?: string; noOverlay?: boolean; // used to suppress docs in the overlay (z) layer (ie, for minimap since overlay doesn't scale) engineProps?: any; + dontScaleFilter?: (doc: Doc) => boolean; // whether this collection should scale documents to fit their panel vs just scrolling them dontRenderDocuments?: boolean; // used for annotation overlays which need to distribute documents into different freeformviews with different mixBlendModes depending on whether they are transparent or not. // However, this screws up interactions since only the top layer gets events. so we render the freeformview a 3rd time with all documents in order to get interaction events (eg., marquee) but we don't actually want to display the documents. }; @@ -1197,10 +1198,11 @@ export class CollectionFreeFormView extends CollectionSubView { - whichDoc !== targetDoc && r?.focus(targetDoc); + whichDoc !== targetDoc && r?.focus(whichDoc); }} {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} isContentActive={returnFalse} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e117be0c2..f30d093a1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -168,6 +168,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps { radialMenu?: String[]; LayoutTemplateString?: string; dontCenter?: "x" | "y" | "xy"; + dontScaleFilter?: (doc: Doc) => boolean; // decides whether a document can be scaled to fit its container vs native size with scrolling ContentScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NativeWidth?: () => number; NativeHeight?: () => number; @@ -249,6 +250,7 @@ export class DocumentViewInternal extends DocComponent !this.props.isSelected() && LightboxView.LightboxDoc !== this.rootDoc && this.thumb && - !Doc.AreProtosEqual(DocumentLinksButton.StartLink, this.rootDoc) && - !this._componentView?.isAnyChildContentActive?.() ? true : false + thumbShown = () => { + return !this.props.isSelected() && LightboxView.LightboxDoc !== this.rootDoc && this.thumb && + !Doc.AreProtosEqual(DocumentLinksButton.StartLink, this.rootDoc) && + !Doc.isBrushedHighlightedDegree(this.props.Document) && + !this._componentView?.isAnyChildContentActive?.() ? true : false; + } @computed get contents() { TraceMobx(); const audioView = !this.layoutDoc._showAudio ? (null) : @@ -874,7 +879,7 @@ export class DocumentViewInternal extends DocComponent {!this._retryThumb || !this.thumbShown() ? (null) : - this.props.isSelected(), + reaction(() => this.props.isSelected() || this.isAnyChildContentActive() || Doc.isBrushedHighlightedDegree(this.props.Document), async (selected) => { if (selected) { this._webPageHasBeenRendered = true; - setTimeout(action(() => { - this._scrollHeight = Math.max(this.scrollHeight, this._iframe?.contentDocument?.body.scrollHeight || 0); - if (this._initialScroll !== undefined) { - this.setScrollPos(this._initialScroll); - } - })); } else if ((!this.props.isContentActive() || SnappingManager.GetIsDragging()) && // update thumnail when unselected AND (no child annotation is active OR we've started dragging the document in which case no additional deselect will occur so this is the only chance to update the thumbnail) !this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && // don't create a thumbnail when double-clicking to enter lightbox because thumbnail will be empty LightboxView.LightboxDoc !== this.rootDoc) { // don't create a thumbnail if entering Lightbox from maximize either, since thumb will be empty. - const imageBitmap = ImageCast(this.layoutDoc["thumb-frozen"])?.url.href; - if (this._iframe && !imageBitmap) { - var htmlString = this._iframe.contentDocument && new XMLSerializer().serializeToString(this._iframe.contentDocument); - if (!htmlString) { - htmlString = await (await fetch(Utils.CorsProxy(this.webField!.href))).text(); - } - this.layoutDoc.thumb = undefined; - const nativeWidth = NumCast(this.layoutDoc.nativeWidth); - CreateImage( - this._webUrl.endsWith("/") ? this._webUrl.substring(0, this._webUrl.length - 1) : this._webUrl, - this._iframe.contentDocument?.styleSheets ?? [], - htmlString, - nativeWidth, - nativeWidth * this.props.PanelHeight() / this.props.PanelWidth(), - NumCast(this.layoutDoc._scrollTop) - ).then - ((data_url: any) => { - VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), true, this.layoutDoc[Id] + "-icon").then( - returnedfilename => setTimeout(action(() => this.layoutDoc.thumb = new ImageField(returnedfilename)), 500)); - }) - .catch(function (error: any) { - console.error('oops, something went wrong!', error); - }); - } + this.updateThumb(); } - }, { fireImmediately: this.props.isSelected() }); + }, { fireImmediately: this.props.isSelected() || this.isAnyChildContentActive() || (Doc.isBrushedHighlightedDegree(this.props.Document) ? true : false) }); this._disposers.autoHeight = reaction(() => this.layoutDoc._autoHeight, autoHeight => { @@ -183,21 +188,16 @@ export class WebBox extends ViewBoxAnnotatableComponent NumCast(this.layoutDoc._scrollTop), (scrollTop) => { - if (quickScroll) this._initialScroll = scrollTop; - else { - const viewTrans = StrCast(this.Document._viewTransition); - const durationMiliStr = viewTrans.match(/([0-9]*)ms/); - const durationSecStr = viewTrans.match(/([0-9.]*)s/); - const duration = durationMiliStr ? Number(durationMiliStr[1]) : durationSecStr ? Number(durationSecStr[1]) * 1000 : 0; - this.goTo(scrollTop, duration); - } + const viewTrans = StrCast(this.Document._viewTransition); + const durationMiliStr = viewTrans.match(/([0-9]*)ms/); + const durationSecStr = viewTrans.match(/([0-9.]*)s/); + const duration = durationMiliStr ? Number(durationMiliStr[1]) : durationSecStr ? Number(durationSecStr[1]) * 1000 : 0; + this.goTo(scrollTop, duration); }, { fireImmediately: true } ); - quickScroll = false; } @action componentWillUnmount() { Object.values(this._disposers).forEach(disposer => disposer?.()); @@ -234,7 +234,6 @@ export class WebBox extends ViewBoxAnnotatableComponent this.urlEditor; // controls to be added to the top bar when a document of this type is selected scrollFocus = (doc: Doc, smooth: boolean) => { - this.props.select(false); // hack to preven the webBox from being replaced with a thumbnail that currently doesn't show the the anchors if (StrCast(doc.webUrl) !== this._url) this.submitURL(StrCast(doc.webUrl), !smooth); if (DocListCast(this.props.Document[this.fieldKey + "-sidebar"]).includes(doc) && !this.SidebarShown) { this.toggleSidebar(!smooth); @@ -242,15 +241,16 @@ export class WebBox extends ViewBoxAnnotatableComponent { const iframe = this._iframe; + if (this._initialScroll !== undefined) { + this.setScrollPos(this._initialScroll); + } let requrlraw = decodeURIComponent(iframe?.contentWindow?.location.href.replace(Utils.prepend("") + "/corsProxy/", "") ?? this._url.toString()); if (requrlraw !== this._url.toString()) { if (requrlraw.match(/q=.*&/)?.length && this._url.toString().match(/q=.*&/)?.length) { @@ -342,8 +345,8 @@ export class WebBox extends ViewBoxAnnotatableComponent this._scrollHeight = Math.max(this.scrollHeight, iframe?.contentDocument?.body.scrollHeight || 0)), 5000); + this._scrollHeight = Math.max(this._scrollHeight, iframe?.contentDocument.body.scrollHeight); + setTimeout(action(() => this._scrollHeight = Math.max(this._scrollHeight, iframe?.contentDocument?.body.scrollHeight || 0)), 5000); iframe.setAttribute("enable-annotation", "true"); iframe.contentDocument.addEventListener("click", undoBatch(action((e: MouseEvent) => { let href = ""; @@ -374,29 +377,29 @@ export class WebBox extends ViewBoxAnnotatableComponent { - const iframeHeight = Math.max(1000, this._scrollHeight - this.panelHeight()); - timeout = scrollTop > iframeHeight ? 0 : timeout; + const iframeHeight = Math.max(scrollTop, this._scrollHeight - this.panelHeight()); this._scrollTimer && clearTimeout(this._scrollTimer); this._scrollTimer = setTimeout(action(() => { this._scrollTimer = undefined; if (!LinkDocPreview.LinkInfo && this._outerRef.current && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath()))) { - this.layoutDoc._scrollTop = this._outerRef.current.scrollTop = scrollTop > iframeHeight ? iframeHeight : scrollTop; + this.layoutDoc.thumb = undefined; + this.layoutDoc.thumbScrollTop = undefined; + this.layoutDoc.scrollTop = this._outerRef.current.scrollTop = scrollTop > iframeHeight ? iframeHeight : scrollTop; } }), timeout); } goTo = (scrollTop: number, duration: number) => { if (this._outerRef.current) { - const iframeHeight = Math.max(1000, this._scrollHeight - this.panelHeight()); - scrollTop = scrollTop > iframeHeight + 50 ? iframeHeight : scrollTop; + const iframeHeight = Math.max(scrollTop, this._scrollHeight - this.panelHeight()); if (duration) { smoothScroll(duration, [this._outerRef.current], scrollTop); this.setDashScrollTop(scrollTop, duration); } else { this.setDashScrollTop(scrollTop); } - } + } else this._initialScroll = scrollTop; } forward = (checkAvailable?: boolean) => { @@ -456,6 +459,10 @@ export class WebBox extends ViewBoxAnnotatableComponent([...(history || []), url]); this.layoutDoc._scrollTop = 0; + if (this._webPageHasBeenRendered) { + this.layoutDoc.thumb = undefined; + this.layoutDoc.thumbScrollTop = undefined; + } future && (future.length = 0); } if (!preview) { @@ -566,6 +573,7 @@ export class WebBox extends ViewBoxAnnotatableComponent this._iframe = r)} src={"https://crossorigin.me/https://cs.brown.edu"} />; } - setTimeout(action(() => this._webPageHasBeenRendered = true)); + setTimeout(action(() => { + this._scrollHeight = Math.max(this._scrollHeight, this._iframe && this._iframe.contentDocument && this._iframe.contentDocument.body ? this._iframe.contentDocument.body.scrollHeight : 0); + if (this._initialScroll === undefined && !this._webPageHasBeenRendered) this.setScrollPos(NumCast(this.layoutDoc.thumbScrollTop, NumCast(this.layoutDoc.scrollTop))); + this._webPageHasBeenRendered = true; + })); return view; } diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 218f37f3d..fb2e33e2a 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -22,7 +22,11 @@ interface IAnnotationProps extends FieldViewProps { export class Annotation extends React.Component { render() { - return DocListCast(this.props.anno.textInlineAnnotations).map(a => ); + return
+ {DocListCast(this.props.anno.textInlineAnnotations).map(a => + + )} +
} } @@ -32,23 +36,10 @@ interface IRegionAnnotationProps extends IAnnotationProps { } @observer class RegionAnnotation extends React.Component { - private _disposers: { [name: string]: IReactionDisposer } = {}; private _mainCont: React.RefObject = React.createRef(); - @observable _brushed: boolean = false; @computed get annoTextRegion() { return Cast(this.props.document.annoTextRegion, Doc, null) || this.props.document; } - componentDidMount() { - this._disposers.brush = reaction( - () => this.annoTextRegion && Doc.isBrushedHighlightedDegree(this.annoTextRegion), - brushed => brushed !== undefined && runInAction(() => this._brushed = brushed !== 0) - ); - } - - componentWillUnmount() { - Object.values(this._disposers).forEach(disposer => disposer?.()); - } - @undoBatch deleteAnnotation = () => { const docAnnotations = DocListCast(this.props.dataDoc[this.props.fieldKey]); @@ -91,15 +82,27 @@ class RegionAnnotation extends React.Component { } render() { - return (
this.props.showInfo(this.props.anno)} onPointerLeave={() => this.props.showInfo(undefined)} onPointerDown={this.onPointerDown} ref={this._mainCont} + const brushed = this.annoTextRegion && Doc.isBrushedHighlightedDegree(this.annoTextRegion); + return (
{ + Doc.BrushDoc(this.props.anno); + this.props.showInfo(this.props.anno); + })} + onPointerLeave={action(() => { + Doc.UnBrushDoc(this.props.anno); + this.props.showInfo(undefined); + })} + onPointerDown={this.onPointerDown} style={{ left: NumCast(this.props.document.x), top: NumCast(this.props.document.y), width: NumCast(this.props.document._width), height: NumCast(this.props.document._height), - opacity: this._brushed ? 0.5 : undefined, + opacity: brushed === Doc.DocBrushStatus.highlighted ? 0.5 : undefined, pointerEvents: this.props.pointerEvents?.() as any, - backgroundColor: this._brushed ? "orange" : StrCast(this.props.document.backgroundColor), + outline: brushed === Doc.DocBrushStatus.linkHighlighted ? "solid 1px lightBlue" : undefined, + backgroundColor: brushed === Doc.DocBrushStatus.highlighted ? "orange" : + StrCast(this.props.document.backgroundColor), }} >
); } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 608ba07ff..b0a5fc93b 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -484,7 +484,7 @@ export class PDFViewer extends React.Component { CollectionView={undefined} ScreenToLocalTransform={this.overlayTransform} renderDepth={this.props.renderDepth + 1} - />; + /> @computed get overlayTransparentAnnotations() { return this.renderAnnotations(this.transparentFilter, false); } @computed get overlayOpaqueAnnotations() { return this.renderAnnotations(this.opaqueFilter, false); } @computed get overlayClickableAnnotations() { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 3d36efbc4..2905e96d9 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -127,9 +127,11 @@ export class SearchBox extends ViewBoxBaseComponent() { static foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) { let newarray: Doc[] = []; var depth = 0; + let visited: Doc[] = []; while (docs.length > 0) { newarray = []; - docs.filter(d => d).forEach(d => { + docs.filter(d => d && !visited.includes(d)).forEach(d => { + visited.push(d); const fieldKey = Doc.LayoutFieldKey(d); const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); const data = d[annos ? fieldKey + "-annotations" : fieldKey]; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 50e5fcbc4..9de8d0831 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1016,12 +1016,28 @@ export namespace Doc { unbrushed = 0, protoBrushed = 1, selfBrushed = 2, - highlighted = 3 + highlighted = 3, + linkHighlighted = 4, } // don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message) export function IsBrushedDegreeUnmemoized(doc: Doc) { if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return DocBrushStatus.unbrushed; - return brushManager.BrushedDoc.has(doc) ? DocBrushStatus.selfBrushed : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? DocBrushStatus.protoBrushed : DocBrushStatus.unbrushed; + const status = brushManager.BrushedDoc.has(doc) ? DocBrushStatus.selfBrushed : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? DocBrushStatus.protoBrushed : DocBrushStatus.unbrushed; + if (status === DocBrushStatus.unbrushed) { + const lastBrushed = Array.from(brushManager.BrushedDoc.keys()).lastElement(); + if (lastBrushed) { + for (var link of LinkManager.Instance.getAllDirectLinks(lastBrushed)) { + const a1 = Cast(link.anchor1, Doc, null); + const a2 = Cast(link.anchor2, Doc, null); + if (Doc.AreProtosEqual(a1, doc) || Doc.AreProtosEqual(a2, doc) || + (Doc.AreProtosEqual(Cast(a1.annotationOn, Doc, null), doc)) || + (Doc.AreProtosEqual(Cast(a2.annotationOn, Doc, null), doc))) { + return DocBrushStatus.linkHighlighted; + } + } + } + } + return status; } export function IsBrushedDegree(doc: Doc) { return computedFn(function IsBrushDegree(doc: Doc) { @@ -1030,14 +1046,18 @@ export namespace Doc { } export function BrushDoc(doc: Doc) { if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc; - brushManager.BrushedDoc.set(doc, true); - brushManager.BrushedDoc.set(Doc.GetProto(doc), true); + runInAction(() => { + brushManager.BrushedDoc.set(doc, true); + brushManager.BrushedDoc.set(Doc.GetProto(doc), true); + }); return doc; } export function UnBrushDoc(doc: Doc) { if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc; - brushManager.BrushedDoc.delete(doc); - brushManager.BrushedDoc.delete(Doc.GetProto(doc)); + runInAction(() => { + brushManager.BrushedDoc.delete(doc); + brushManager.BrushedDoc.delete(Doc.GetProto(doc)); + }); return doc; } diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 83a2bc79b..cd85a7a65 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -271,10 +271,10 @@ export default class UploadManager extends ApiManager { return imageDataUri.outputFile(uri, serverPathToFile(Directory.images, InjectSize(filename, origSuffix))).then((savedName: string) => { const ext = extname(savedName).toLowerCase(); const { pngs, jpgs } = AcceptableMedia; - const resizers = !origSuffix ? [{ resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }] : [ - { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" }, - { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }, - { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" }, + const resizers = !origSuffix ? [{ resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: SizeSuffix.Medium }] : [ + { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: SizeSuffix.Small }, + { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: SizeSuffix.Medium }, + { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: SizeSuffix.Large }, ]; let isImage = false; if (pngs.includes(ext)) { @@ -290,8 +290,10 @@ export default class UploadManager extends ApiManager { } if (isImage) { resizers.forEach(resizer => { - const path = serverPathToFile(Directory.images, filename + resizer.suffix + ext); - createReadStream(savedName).pipe(resizer.resizer).pipe(createWriteStream(path)); + const path = serverPathToFile(Directory.images, InjectSize(filename, resizer.suffix) + ext); + createReadStream(savedName).on("error", e => console.log("Resizing Read error:" + e)) + .pipe(resizer.resizer) + .pipe(createWriteStream(path).on("error", e => console.log("Resizing write error: " + e))); }); } -- cgit v1.2.3-70-g09d2 From 5b419a93e8d4a4c3eb3a6b354026e8e67a2753b7 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 13 May 2022 15:48:54 -0400 Subject: simplified how web pages are served and I think fixed some bugs with pages that didn't always render --- src/client/views/nodes/WebBox.tsx | 9 +-- src/server/ApiManagers/UploadManager.ts | 4 +- src/server/server_Initialization.ts | 101 +++++++++++++++----------------- 3 files changed, 54 insertions(+), 60 deletions(-) (limited to 'src/server') diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index af7a2b941..20e01be05 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -381,12 +381,13 @@ export class WebBox extends ViewBoxAnnotatableComponent { this._scrollTimer = undefined; - if (!LinkDocPreview.LinkInfo && this._outerRef.current && + const newScrollTop = scrollTop > iframeHeight ? iframeHeight : scrollTop; + if (!LinkDocPreview.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath()))) { this.layoutDoc.thumb = undefined; this.layoutDoc.thumbScrollTop = undefined; - this.layoutDoc.scrollTop = this._outerRef.current.scrollTop = scrollTop > iframeHeight ? iframeHeight : scrollTop; - } + this.layoutDoc.scrollTop = this._outerRef.current.scrollTop = newScrollTop; + } else if (this._outerRef.current) this._outerRef.current.scrollTop = newScrollTop; }), timeout); } @@ -761,7 +762,7 @@ export class WebBox extends ViewBoxAnnotatableComponent this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)} onPointerDown={this.onMarqueeDown} > -
+
{this.content}
{renderAnnotations(this.transparentFilter)} diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index cd85a7a65..2c667ba3e 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -291,9 +291,9 @@ export default class UploadManager extends ApiManager { if (isImage) { resizers.forEach(resizer => { const path = serverPathToFile(Directory.images, InjectSize(filename, resizer.suffix) + ext); - createReadStream(savedName).on("error", e => console.log("Resizing Read error:" + e)) + createReadStream(savedName).on("error", e => console.log("Resizing read:" + e)) .pipe(resizer.resizer) - .pipe(createWriteStream(path).on("error", e => console.log("Resizing write error: " + e))); + .pipe(createWriteStream(path).on("error", e => console.log("Resizing write: " + e))); }); } diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 5bfd0213c..8bf84622d 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -171,60 +171,53 @@ function registerCorsProxy(server: express.Express) { function proxyServe(req: any, requrl: string, response: any) { const htmlBodyMemoryStream = new (require('memorystream'))(); - req.headers.cookie = ""; - req.pipe(request(requrl)) - .on("error", (e: any) => console.log(`Malformed CORS url: ${requrl}`, e)) - .on("end", () => { - var rewrittenHtmlBody: any = undefined; - req.pipe(request(requrl)) - .on("response", (res: any) => { - const headers = Object.keys(res.headers); - const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; - headers.forEach(headerName => { - const header = res.headers[headerName]; - if (Array.isArray(header)) { - res.headers[headerName] = header.filter(h => !headerCharRegex.test(h)); - } else if (headerCharRegex.test(header || "")) { - delete res.headers[headerName]; - } - if (headerName === "content-encoding" && header.includes("gzip")) { - try { - const replacer = (match: any, href: string, offset: any, string: any) => { - return `href="${resolvedServerUrl + "/corsProxy/http" + href}"`; - }; - const zipToStringDecoder = new (require('string_decoder').StringDecoder)('utf8'); - const bodyStream = htmlBodyMemoryStream.read(); - if (bodyStream) { - const htmlText = zipToStringDecoder.write(zlib.gunzipSync(bodyStream).toString('utf8') - .replace('', ' ') - .replace(/href="https?([^"]*)"/g, replacer) - .replace(/target="_blank"/g, "")); - rewrittenHtmlBody = zlib.gzipSync(htmlText); - } else { - console.log("EMPTY body: href"); - } - } catch (e) { - console.log("EROR?: ", e); - } - } - }); - }) - .on('data', (e: any) => { - try { - if (response.connection?.writable) { - rewrittenHtmlBody && response.send(rewrittenHtmlBody); - } - } catch (e) { - console.log("ERROR data : ", e); - } - rewrittenHtmlBody = undefined; - }) - .on('error', (e: any) => { - console.log("ERROR ON SERVER: ", e); - }) - .pipe(response); - }) - .pipe(htmlBodyMemoryStream); + var retrieveHTTPBody: any; + const sendModifiedBody = () => { + const header = response.headers["content-encoding"]; + if (header && header.includes("gzip")) { + try { + const replacer = (match: any, href: string, offset: any, string: any) => { + return `href="${resolvedServerUrl + "/corsProxy/http" + href}"`; + }; + const zipToStringDecoder = new (require('string_decoder').StringDecoder)('utf8'); + const bodyStream = htmlBodyMemoryStream.read(); + if (bodyStream) { + const htmlText = zipToStringDecoder.write(zlib.gunzipSync(bodyStream).toString('utf8') + .replace('', ' ') + .replace(/href="https?([^"]*)"/g, replacer) + .replace(/target="_blank"/g, "")); + response.send(zlib.gzipSync(htmlText)); + } else { + req.pipe(request(requrl)).pipe(response); + console.log("EMPTY body:" + req.url); + } + } catch (e) { + console.log("EROR?: ", e); + } + } else req.pipe(request(requrl)).pipe(response); + } + retrieveHTTPBody = () => { + req.headers.cookie = ""; + req.pipe(request(requrl)) + .on("error", (e: any) => console.log(`Malformed CORS url: ${requrl}`, e)) + .on("response", (res: any) => { + res.headers; + const headers = Object.keys(res.headers); + const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; + headers.forEach(headerName => { + const header = res.headers[headerName]; + if (Array.isArray(header)) { + res.headers[headerName] = header.filter(h => !headerCharRegex.test(h)); + } else if (headerCharRegex.test(header || "")) { + delete res.headers[headerName]; + } else res.headers[headerName] = header; + }); + response.headers = response._headers = res.headers; + }) + .on("end", sendModifiedBody) + .pipe(htmlBodyMemoryStream); + }; + retrieveHTTPBody(); } function registerEmbeddedBrowseRelativePathHandler(server: express.Express) { -- cgit v1.2.3-70-g09d2 From 3847b2bbba9a64b846ecd6af481fd04df55bd798 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 13 May 2022 16:26:33 -0400 Subject: fixed bug with following links in lightbox. --- src/client/util/LinkManager.ts | 2 +- src/server/server_Initialization.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/server') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index b28662a57..2100b1195 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -246,7 +246,7 @@ export class LinkManager { while (containerDocContext.length && !DocumentManager.Instance.getDocumentView(containerDocContext[0]) && containerDocContext[0].context) { containerDocContext = [Cast(containerDocContext[0].context, Doc, null), ...containerDocContext]; } - const targetContexts = LightboxView.LightboxDoc ? [containerAnnoDoc || containerDocContext[0]] : containerDocContext; + const targetContexts = LightboxView.LightboxDoc ? [containerAnnoDoc || containerDocContext[0]].filter(a => a) : containerDocContext; DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "lightbox"), finished), targetContexts, linkDoc, undefined, sourceDoc, allFinished); } } else { diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 8bf84622d..bdea57cb2 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -228,9 +228,9 @@ function registerEmbeddedBrowseRelativePathHandler(server: express.Express) { try { const proxiedRefererUrl = decodeURIComponent(req.headers.referer); // (e.g., http://localhost:/corsProxy/https://en.wikipedia.org/wiki/Engelbart) const dashServerUrl = proxiedRefererUrl.match(/.*corsProxy\//)![0]; // the dash server url (e.g.: http://localhost:/corsProxy/ ) - const actualReferUrl = proxiedRefererUrl.replace(dashServerUrl, ""); // the url of the referer without the proxy (e.g., : http:s//en.wikipedia.org/wiki/Engelbart) + const actualReferUrl = proxiedRefererUrl.replace(dashServerUrl, ""); // the url of the referer without the proxy (e.g., : https://en.wikipedia.org/wiki/Engelbart) const absoluteTargetBaseUrl = actualReferUrl.match(/https?:\/\/[^\/]*/)![0]; // the base of the original url (e.g., https://en.wikipedia.org) - const redirectedProxiedUrl = dashServerUrl + encodeURIComponent(absoluteTargetBaseUrl + relativeUrl); // the new proxied full url (e..g, http://localhost:/corsProxy/https://en.wikipedia.org/) + const redirectedProxiedUrl = dashServerUrl + encodeURIComponent(absoluteTargetBaseUrl + relativeUrl); // the new proxied full url (e.g., http://localhost:/corsProxy/https://en.wikipedia.org/) if (relativeUrl.startsWith("//")) res.redirect("http:" + relativeUrl); else res.redirect(redirectedProxiedUrl); } catch (e) { -- cgit v1.2.3-70-g09d2 From 57c1b8235b26a1b6a315922b4dc2926e1e597674 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 13 May 2022 18:17:10 -0400 Subject: removed layerProvider functionality. --- src/client/documents/Documents.ts | 3 +- src/client/views/DocComponent.tsx | 4 -- src/client/views/GestureOverlay.tsx | 1 - src/client/views/InkingStroke.tsx | 2 +- src/client/views/LightboxView.tsx | 1 - src/client/views/MainView.tsx | 6 --- src/client/views/OverlayView.tsx | 1 - src/client/views/Palette.tsx | 1 - src/client/views/PropertiesView.tsx | 2 - src/client/views/StyleProvider.tsx | 52 +++------------------- src/client/views/TemplateMenu.tsx | 1 - src/client/views/collections/CollectionMenu.tsx | 1 - .../collections/CollectionStackedTimeline.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 2 - .../views/collections/CollectionTreeView.tsx | 1 - src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/collections/TabDocView.tsx | 19 +------- src/client/views/collections/TreeView.tsx | 2 - .../collectionFreeForm/CollectionFreeFormView.tsx | 24 +++++----- .../collections/collectionFreeForm/MarqueeView.tsx | 10 ++--- .../collectionLinear/CollectionLinearView.tsx | 1 - .../CollectionMulticolumnView.tsx | 1 - .../CollectionMultirowView.tsx | 1 - .../collectionSchema/CollectionSchemaView.tsx | 1 - .../collections/collectionSchema/SchemaTable.tsx | 1 - src/client/views/linking/LinkPopup.tsx | 3 +- src/client/views/nodes/AudioBox.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 - src/client/views/nodes/DocumentView.tsx | 5 +-- src/client/views/nodes/FilterBox.tsx | 1 - src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 1 - src/client/views/nodes/LinkAnchorBox.tsx | 1 - src/client/views/nodes/LinkDocPreview.tsx | 1 - src/client/views/nodes/VideoBox.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 6 +-- .../views/nodes/formattedText/DashDocView.tsx | 1 - .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/client/views/nodes/trails/PresBox.tsx | 2 +- src/client/views/nodes/trails/PresElementBox.tsx | 1 - src/client/views/pdf/Annotation.tsx | 2 +- src/client/views/search/SearchBox.tsx | 2 +- src/fields/Doc.ts | 2 +- src/mobile/AudioUpload.tsx | 1 - src/mobile/MobileInterface.tsx | 1 - src/server/server_Initialization.ts | 2 +- 46 files changed, 41 insertions(+), 143 deletions(-) (limited to 'src/server') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d9c2e0d8b..797a129c4 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -122,7 +122,6 @@ export class DocumentOptions { _scrollTop?: number; // scroll location for pdfs _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged _chromeHidden?: boolean; // whether the editing chrome for a document is hidden - _layerTags?: List; // layer tags a document has (used for tab filtering "layers" in document tab) _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view) _forceActive?: boolean; // flag to handle pointer events when not selected (or otherwise active) _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere @@ -426,7 +425,7 @@ export namespace Docs { childDontRegisterViews: true, _isLinkButton: true, _height: 150, description: "", showCaption: "description", backgroundColor: "lightblue", // lightblue is default color for linking dot and link documents text comment area links: "@links(self)", - _removeDropProperties: new List(["_layerTags", "isLinkButton"]), + _removeDropProperties: new List(["isLinkButton"]), } }], [DocumentType.LINKDB, { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 79aaf2158..9c176a4fd 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -44,7 +44,6 @@ interface ViewBoxBaseProps { ContainingCollectionDoc: Opt; DocumentView?: () => DocumentView; fieldKey: string; - layerProvider?: (doc: Doc, assign?: boolean) => boolean; isSelected: (outsideReaction?: boolean) => boolean; isContentActive: () => boolean | undefined; renderDepth: number; @@ -85,7 +84,6 @@ export interface ViewBoxAnnotatableProps { DataDoc?: Doc; fieldKey: string; filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) - layerProvider?: (doc: Doc, assign?: boolean) => boolean; isContentActive: () => boolean | undefined; select: (isCtrlPressed: boolean) => void; whenChildContentsActiveChanged: (isActive: boolean) => void; @@ -209,13 +207,11 @@ export function ViewBoxAnnotatableComponent

() if ([AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))) inheritParentAcls(CurrentUserUtils.ActiveDashboard, doc); doc.context = this.props.Document; if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document; - this.props.layerProvider?.(doc, true); Doc.AddDocToList(targetDataDoc, annotationKey ?? this.annotationKey, doc); }); } else { added.filter(doc => [AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))).map(doc => { // only make a pushpin if we have acl's to edit the document - this.props.layerProvider?.(doc, true); //DocUtils.LeavePushpin(doc); doc._stayInCollection = undefined; doc.context = this.props.Document; diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 50dca0a99..482b62479 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -881,7 +881,6 @@ export class GestureOverlay extends Touchable { isContentActive={returnFalse} renderDepth={0} styleProvider={returnEmptyString} - layerProvider={undefined} docViewPath={returnEmptyDoclist} focus={DocUtils.DefaultFocus} whenChildContentsActiveChanged={emptyFunction} diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 3d9c048e5..d0f01c363 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -332,7 +332,7 @@ export class InkingStroke extends ViewBoxBaseComponent() { inkStrokeWidth, inkStrokeWidth + (highlightIndex && closed && fillColor && (new Color(fillColor)).alpha() < 1 ? 6 : 15), StrCast(this.layoutDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap), StrCast(this.layoutDoc.strokeBezier), !closed ? "none" : fillColor === "transparent" || suppressFill ? "none" : fillColor, startMarker, endMarker, - markerScale, undefined, inkScaleX, inkScaleY, "", this.props.pointerEvents?.() ?? (this.props.layerProvider?.(this.props.Document) === false ? "none" : "visiblepainted"), 0.0, + markerScale, undefined, inkScaleX, inkScaleY, "", this.props.pointerEvents?.() ?? (this.rootDoc._lockedPosition ? "none" : "visiblepainted"), 0.0, false, downHdlr); const fsize = +(StrCast(this.props.Document.fontSize, "12px").replace("px", "")); // bootsrap 3 style sheet sets line height to be 20px for default 14 point font size. diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 59ed0dc92..9882693ee 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -246,7 +246,6 @@ export class LightboxView extends React.Component { docFilters={this.docFilters} removeDocument={undefined} styleProvider={DefaultStyleProvider} - layerProvider={returnTrue} ScreenToLocalTransform={this.lightboxScreenToLocal} PanelWidth={this.lightboxWidth} PanelHeight={this.lightboxHeight} diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index db51c54f8..2e1d10955 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -281,7 +281,6 @@ export class MainView extends React.Component { addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} - layerProvider={undefined} styleProvider={undefined} rootSelected={returnTrue} isContentActive={returnTrue} @@ -361,7 +360,6 @@ export class MainView extends React.Component { addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} - layerProvider={undefined} styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards || this._sidebarContent.proto === Doc.UserDoc().myFilesystem ? DashboardStyleProvider : DefaultStyleProvider} rootSelected={returnTrue} removeDocument={returnFalse} @@ -402,7 +400,6 @@ export class MainView extends React.Component { docViewPath={returnEmptyDoclist} focus={DocUtils.DefaultFocus} styleProvider={DefaultStyleProvider} - layerProvider={undefined} isContentActive={returnTrue} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -516,7 +513,6 @@ export class MainView extends React.Component { dropAction={"alias"} setHeight={returnFalse} styleProvider={DefaultStyleProvider} - layerProvider={undefined} rootSelected={returnTrue} bringToFront={emptyFunction} select={emptyFunction} @@ -591,7 +587,6 @@ export class MainView extends React.Component { ContainingCollectionDoc={undefined} Document={DocumentLinksButton.invisibleWebDoc} dropAction={"move"} - layerProvider={undefined} styleProvider={undefined} isSelected={returnFalse} select={returnFalse} @@ -673,7 +668,6 @@ export class MainView extends React.Component { rootSelected={returnFalse} renderDepth={0} setHeight={returnFalse} - layerProvider={undefined} styleProvider={undefined} addDocTab={returnFalse} pinToPres={returnFalse} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 0f51cf9b2..ebad2981d 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -195,7 +195,6 @@ export class OverlayView extends React.Component { whenChildContentsActiveChanged={emptyFunction} focus={DocUtils.DefaultFocus} styleProvider={DefaultStyleProvider} - layerProvider={undefined} docViewPath={returnEmptyDoclist} addDocTab={returnFalse} pinToPres={emptyFunction} diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx index 529697f71..954529bc9 100644 --- a/src/client/views/Palette.tsx +++ b/src/client/views/Palette.tsx @@ -54,7 +54,6 @@ export default class Palette extends React.Component { focus={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={returnEmptyString} - layerProvider={undefined} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 21c688421..bba2ac211 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -303,7 +303,6 @@ export class PropertiesView extends React.Component { fitContentsToDoc={returnTrue} rootSelected={returnFalse} styleProvider={DefaultStyleProvider} - layerProvider={undefined} docViewPath={returnEmptyDoclist} freezeDimensions={true} dontCenter={"y"} @@ -1010,7 +1009,6 @@ export class PropertiesView extends React.Component { createNewFilterDoc={this.createNewFilterDoc} updateFilterDoc={this.updateFilterDoc} docViewPath={returnEmptyDoclist} - layerProvider={undefined} dontCenter="y" />

diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 5056dedaf..334415b38 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -26,10 +26,6 @@ import React = require("react"); import { InkingStroke } from './InkingStroke'; import { TreeSort } from './collections/TreeView'; -export enum StyleLayers { - Background = "background" -} - export enum StyleProp { TreeViewIcon = "treeViewIcon", TreeViewSortings = "treeViewSortings",// options for how to sort tree view items @@ -56,14 +52,9 @@ export enum StyleProp { function darkScheme() { return CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark; } -function toggleBackground(doc: Doc) { +function toggleLockedPosition(doc: Doc) { UndoManager.RunInBatch(() => runInAction(() => { - const layers = StrListCast(doc._layerTags); - if (!layers.includes(StyleLayers.Background)) { - if (!layers.length) doc._layerTags = new List([StyleLayers.Background]); - else layers.push(StyleLayers.Background); - } - else layers.splice(layers.indexOf(StyleLayers.Background), 1); + doc._lockedPosition = !doc._lockedPosition; }), "toggleBackground"); } @@ -86,7 +77,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === "comic"; - const isBackground = () => StrListCast(doc?._layerTags).includes(StyleLayers.Background); + const isBackground = () => doc && BoolCast(doc._lockedPosition); const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor); const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity); const showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle); @@ -177,7 +168,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt 0 && ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ? -
toggleBackground(doc)}> +
toggleLockedPosition(doc)}>
: (null); @@ -251,30 +240,3 @@ export function DashboardStyleProvider(doc: Opt, props: Opt { - if (doc.z) return true; - if (assign) { - const activeLayer = StrCast(thisDoc?.activeLayer); - if (activeLayer) { - const layers = Cast(doc._layerTags, listSpec("string"), []); - if (layers.length && !layers.includes(activeLayer)) layers.push(activeLayer); - else if (!layers.length) doc._layerTags = new List([activeLayer]); - if (activeLayer === "red" || activeLayer === "green" || activeLayer === "blue") doc._backgroundColor = activeLayer; - } - return true; - } else { - if (Doc.AreProtosEqual(doc, thisDoc)) return true; - const layers = StrListCast(doc._layerTags); - if (!layers.length && !thisDoc?.activeLayer) return true; - if (layers.includes(StrCast(thisDoc?.activeLayer))) return true; - return false; - } - }; -} \ No newline at end of file diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index b3a24e031..636f7042f 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -131,7 +131,6 @@ export class TemplateMenu extends React.Component { ContainingCollectionDoc={undefined} ContainingCollectionView={undefined} styleProvider={DefaultStyleProvider} - layerProvider={undefined} setHeight={returnFalse} docViewPath={returnEmptyDoclist} docFilters={returnEmptyFilter} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 364a2440e..b3fbd4ca4 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -108,7 +108,6 @@ export class CollectionMenu extends AntimodeMenu{ dropAction={"alias"} setHeight={returnFalse} styleProvider={DefaultStyleProvider} - layerProvider={undefined} rootSelected={returnTrue} bringToFront={emptyFunction} select={emptyFunction} diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index de307416f..683b6d51d 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -392,7 +392,7 @@ export class CollectionStackedTimeline extends CollectionSubView + style={{ pointerEvents: this.rootDoc._lockedPosition ? "none" : undefined }}> {this.showIsTagged()} {this.renderSubView(this.collectionViewType, props)}
); diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 8dfc7edc7..73e5a9178 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -26,7 +26,7 @@ import { Colors, Shadows } from '../global/globalEnums'; import { LightboxView } from '../LightboxView'; import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView"; import { PinProps, PresBox, PresMovement } from '../nodes/trails'; -import { DefaultLayerProvider, DefaultStyleProvider, StyleLayers, StyleProp } from '../StyleProvider'; +import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; import { CollectionDockingView } from './CollectionDockingView'; import { CollectionDockingViewMenu } from './CollectionDockingViewMenu'; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; @@ -94,20 +94,6 @@ export class TabDocView extends React.Component { if (tab.element[0].children[1].children.length === 1) { - const toggle = document.createElement("div"); - toggle.style.width = "10px"; - toggle.style.height = "calc(100% - 2px)"; - toggle.style.left = "-2px"; - toggle.style.bottom = "1px"; - toggle.style.borderTopRightRadius = "7px"; - toggle.style.position = "relative"; - toggle.style.display = "inline-block"; - toggle.style.background = "transparent"; - toggle.onclick = (e: MouseEvent) => { - if (tab.contentItem === tab.header.parent.getActiveContentItem()) { - tab.DashDoc.activeLayer = tab.DashDoc.activeLayer ? undefined : StyleLayers.Background; - } - }; iconWrap.className = "lm_iconWrap"; iconWrap.id = "lm_iconWrap"; closeWrap.className = "lm_iconWrap"; @@ -357,7 +343,6 @@ export class TabDocView extends React.Component { disableMinimap = () => !this._document || (this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform); hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap); - @computed get layerProvider() { return this._document && DefaultLayerProvider(this._document); } @computed get docView() { return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? (null) : <> this._view = r)} @@ -369,7 +354,6 @@ export class TabDocView extends React.Component { isContentActive={returnTrue} PanelWidth={this.PanelWidth} PanelHeight={this.PanelHeight} - layerProvider={this.layerProvider} styleProvider={DefaultStyleProvider} docFilters={CollectionDockingView.Instance.childDocFilters} docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters} @@ -520,7 +504,6 @@ export class TabMinimapView extends React.Component { whenChildContentsActiveChanged={emptyFunction} focus={DocUtils.DefaultFocus} styleProvider={TabMinimapView.miniStyleProvider} - layerProvider={undefined} addDocTab={this.props.addDocTab} pinToPres={TabDocView.PinDoc} docFilters={CollectionDockingView.Instance.childDocFilters} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 164021358..d608f800c 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -663,7 +663,6 @@ export class TreeView extends React.Component { hideDecorationTitle={this.props.treeView.outlineMode} hideResizeHandles={this.props.treeView.outlineMode} styleProvider={this.titleStyleProvider} - layerProvider={returnTrue} docViewPath={returnEmptyDoclist} treeViewDoc={this.props.treeView.props.Document} addDocument={undefined} @@ -760,7 +759,6 @@ export class TreeView extends React.Component { renderDepth={this.props.renderDepth + 1} treeViewDoc={this.props.treeView?.props.Document} rootSelected={returnTrue} - layerProvider={returnTrue} docViewPath={this.props.treeView.props.docViewPath} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 4f79d19ad..322944d92 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -44,7 +44,7 @@ import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; import { PresBox } from "../../nodes/trails/PresBox"; import { VideoBox } from "../../nodes/VideoBox"; import { CreateImage } from "../../nodes/WebBoxRenderer"; -import { StyleLayers, StyleProp } from "../../StyleProvider"; +import { StyleProp } from "../../StyleProvider"; import { CollectionDockingView } from "../CollectionDockingView"; import { CollectionSubView } from "../CollectionSubView"; import { CollectionViewType } from "../CollectionView"; @@ -122,8 +122,6 @@ export class CollectionFreeFormView extends CollectionSubView ele.bounds && !ele.bounds.z).map(ele => ele.ele); } - @computed get backgroundEvents() { return this.props.layerProvider?.(this.layoutDoc) === false && SnappingManager.GetIsDragging(); } - @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && this.props.isContentActive(); } @computed get fitToContentVals() { return { bounds: { ...this.contentBounds, cx: (this.contentBounds.x + this.contentBounds.r) / 2, cy: (this.contentBounds.y + this.contentBounds.b) / 2 }, @@ -222,8 +220,8 @@ export class CollectionFreeFormView extends CollectionSubView s.backgroundColor); // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document - set?.filter(s => !StrListCast(s._layerTags).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); - set?.filter(s => StrListCast(s._layerTags).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); + set?.map(s => styleProp = StrCast(s.backgroundColor)); } } //else if (doc && NumCast(doc.group, -1) !== -1) styleProp = "gray"; return styleProp; @@ -1017,7 +1014,7 @@ export class CollectionFreeFormView extends CollectionSubView { - if (sendToBack || StrListCast(doc._layerTags).includes(StyleLayers.Background)) { + if (sendToBack) { doc.zIndex = 0; } else if (doc.isInkMask) { doc.zIndex = 5000; @@ -1155,7 +1152,7 @@ export class CollectionFreeFormView extends CollectionSubView { const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine); - const pointerEvents = this.props.isContentActive() === false ? "none" : this.backgroundActive || this.props.childPointerEvents ? "all" : + const pointerEvents = this.props.isContentActive() === false ? "none" : this.props.childPointerEvents ? "all" : (this.props.viewDefDivClick || (engine === "pass" && !this.props.isSelected(true))) ? "none" : this.props.pointerEvents?.(); return pointerEvents; } @@ -1195,7 +1192,6 @@ export class CollectionFreeFormView extends CollectionSubView intersectRect(docDims(doc), rect); const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) }; - let snappableDocs = activeDocs.filter(doc => !StrListCast(doc._layerTags).includes(StyleLayers.Background) && doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to + let snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect))); // if not, see if there are background docs to snap to !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z !== undefined && isDocInView(doc, otherBounds))); // if not, then why not snap to floating docs @@ -1739,7 +1735,7 @@ export class CollectionFreeFormView extends CollectionSubView
} - {this.props.Document._isGroup && SnappingManager.GetIsDragging() && (this.ChildDrag || this.props.layerProvider?.(this.props.Document) === false) ? + {this.props.Document._isGroup && SnappingManager.GetIsDragging() && this.ChildDrag ?
, options: DocumentOptions, id?: string) => Doc>, layers: string[], makeGroup: Opt) => { + getCollection = action((selected: Doc[], creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, makeGroup: Opt) => { const newCollection = creator ? creator(selected, { title: "nested stack", }) : ((doc: Doc) => { Doc.GetProto(doc).data = new List(selected); Doc.GetProto(doc).title = makeGroup ? "grouping" : "nested freeform"; @@ -357,7 +356,6 @@ export class MarqueeView extends React.Component(layers); newCollection._width = this.Bounds.width; newCollection._height = this.Bounds.height; newCollection._isGroup = makeGroup; @@ -437,7 +435,7 @@ export class MarqueeView extends React.Component { - const newCollection = this.getCollection([], undefined, [StyleLayers.Background], undefined); + const newCollection = this.getCollection([], undefined, undefined); this.props.addDocument?.(newCollection); MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); @@ -617,7 +615,7 @@ export class MarqueeView extends React.Component this.props.layerProvider?.(doc) !== false && !doc.z).map(selectFunc); + this.props.activeDocuments().filter(doc => !doc.z && !doc._lockedPosition).map(selectFunc); if (!selection.length && selectBackgrounds) this.props.activeDocuments().filter(doc => doc.z === undefined).map(selectFunc); if (!selection.length) this.props.activeDocuments().filter(doc => doc.z !== undefined).map(selectFunc); return selection; diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index c615bfb8e..bec582dcd 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -155,7 +155,6 @@ export class CollectionLinearView extends CollectionSubView() { renderDepth={this.props.renderDepth + 1} focus={emptyFunction} styleProvider={this.props.styleProvider} - layerProvider={this.props.layerProvider} docViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 6929a1cd8..92f9b2f49 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -219,7 +219,6 @@ export class CollectionMulticolumnView extends CollectionSubView() { Document={layout} DataDoc={layout.resolvedDataDoc as Doc} styleProvider={this.props.styleProvider} - layerProvider={this.props.layerProvider} docViewPath={this.props.docViewPath} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 7e2b83230..4c4054b09 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -218,7 +218,6 @@ export class CollectionMultirowView extends CollectionSubView() { Document={layout} DataDoc={layout.resolvedDataDoc as Doc} styleProvider={this.props.styleProvider} - layerProvider={this.props.layerProvider} docViewPath={this.props.docViewPath} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index a93762ea4..b731479a5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -417,7 +417,6 @@ export class CollectionSchemaView extends CollectionSubView() { docRangeFilters={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} styleProvider={DefaultStyleProvider} - layerProvider={undefined} docViewPath={returnEmptyDoclist} ContainingCollectionDoc={this.props.CollectionView?.props.Document} ContainingCollectionView={this.props.CollectionView} diff --git a/src/client/views/collections/collectionSchema/SchemaTable.tsx b/src/client/views/collections/collectionSchema/SchemaTable.tsx index 605481ddf..bea5b3be6 100644 --- a/src/client/views/collections/collectionSchema/SchemaTable.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTable.tsx @@ -573,7 +573,6 @@ export class SchemaTable extends React.Component { Document={this._showDoc} DataDoc={this._showDataDoc} styleProvider={DefaultStyleProvider} - layerProvider={undefined} docViewPath={returnEmptyDoclist} freezeDimensions={true} focus={DocUtils.DefaultFocus} diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx index c8be9069c..4b33ef8ae 100644 --- a/src/client/views/linking/LinkPopup.tsx +++ b/src/client/views/linking/LinkPopup.tsx @@ -67,7 +67,7 @@ export class LinkPopup extends React.Component { */} - { pinToPres={emptyFunction} rootSelected={returnTrue} styleProvider={DefaultStyleProvider} - layerProvider={undefined} removeDocument={undefined} ScreenToLocalTransform={Transform.Identity} PanelWidth={this.getPWidth} diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index e28e5b453..d97cb6f84 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -654,7 +654,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent {!this.path ? this.recordingControls : this.playbackControls}
; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index edadd59c0..5a0ab9110 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -21,7 +21,6 @@ import React = require("react"); export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined; sizeProvider?: (doc: Doc, replica: string) => { width: number, height: number } | undefined; - layerProvider: ((doc: Doc, assign?: boolean) => boolean) | undefined; renderCutoffProvider: (doc: Doc) => boolean; zIndex?: number; highlight?: boolean; @@ -159,7 +158,6 @@ export class CollectionFreeFormDocumentView extends DocComponent number; docViewPath: () => DocumentView[]; dataTransition?: string; // specifies animation transition - used by collectionPile and potentially other layout engines when changing the size of documents so that the change won't be abrupt - layerProvider: undefined | ((doc: Doc, assign?: boolean) => boolean); styleProvider: Opt; focus: DocFocusFunc; fitWidth?: (doc: Doc) => boolean; @@ -474,7 +473,7 @@ export class DocumentViewInternal extends DocComponent() { treeViewHideHeaderFields={false} dontRegisterView={true} styleProvider={this.FilterStyleProvider} - layerProvider={this.props.layerProvider} docViewPath={this.props.docViewPath} scriptContext={this.props.scriptContext} moveDocument={returnFalse} diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index e7c43e5cd..3b04aa807 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -379,7 +379,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { docRangeFilters: returnEmptyFilter, searchFilterDocs: returnEmptyDoclist, styleProvider: DefaultStyleProvider, - layerProvider: undefined, docViewPath: returnEmptyDoclist, ContainingCollectionView: undefined, ContainingCollectionDoc: undefined, diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 437d29f39..7fd289a97 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -89,7 +89,6 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { openLinkTargetOnRight = (e: React.MouseEvent) => { const alias = Doc.MakeAlias(Cast(this.layoutDoc[this.fieldKey], Doc, null)); alias._isLinkButton = undefined; - alias._layerTags = undefined; alias.layoutKey = "layout"; this.props.addDocTab(alias, "add:right"); } diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 375434933..ba515fb89 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -179,7 +179,6 @@ export class LinkDocPreview extends React.Component { moveDocument={returnFalse} rootSelected={returnFalse} styleProvider={this.props.docProps?.styleProvider} - layerProvider={this.props.docProps?.layerProvider} docViewPath={returnEmptyDoclist} ScreenToLocalTransform={Transform.Identity} isDocumentActive={returnFalse} diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 3b4c94562..c350e3139 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -809,7 +809,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { e.stopPropagation(); e.preventDefault(); }}> diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 20e01be05..445df8ddd 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -74,7 +74,7 @@ export class WebBox extends ViewBoxAnnotatableComponent a.textInlineAnnotations); } @computed get webField() { return Cast(this.dataDoc[this.props.fieldKey], WebField)?.url; } - @computed get webThumb() { return this.props.thumbShown?.() && ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumbScrollTop === this.layoutDoc._scrollTop ? this.layoutDoc.thumb : undefined))?.url } + @computed get webThumb() { return this.props.thumbShown?.() && ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumbScrollTop === this.layoutDoc._scrollTop ? this.layoutDoc.thumb : undefined))?.url; } constructor(props: any) { super(props); @@ -134,7 +134,7 @@ export class WebBox extends ViewBoxAnnotatableComponent setTimeout(action(() => { this.lockout = false; this.layoutDoc.thumb = new ImageField(returnedfilename); - this.layoutDoc.thumbScrollTop = scrollTop + this.layoutDoc.thumbScrollTop = scrollTop; }), 500)); }) .catch(function (error: any) { @@ -717,7 +717,7 @@ export class WebBox extends ViewBoxAnnotatableComponent !this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== "none" && !MarqueeOptionsMenu.Instance.isShown() ? "all" : SnappingManager.GetIsDragging() ? undefined : "none"; annotationPointerEvents = () => this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"; render() { - const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : this.props.pointerEvents?.() as any; + const pointerEvents = this.layoutDoc._lockedPosition ? "none" : this.props.pointerEvents?.() as any; const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; const scale = previewScale * (this.props.scaling?.() || 1); const renderAnnotations = (docFilters?: () => string[]) => diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index 364be461f..1d8e3a2cf 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -182,7 +182,6 @@ export class DashDocViewInternal extends React.Component { removeDocument={this.removeDoc} isDocumentActive={returnFalse} isContentActive={this._textBox.props.isContentActive} - layerProvider={this._textBox.props.layerProvider} styleProvider={this._textBox.props.styleProvider} docViewPath={this._textBox.props.docViewPath} ScreenToLocalTransform={this.getDocTransform} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 29117794e..f2a222cee 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1630,7 +1630,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const active = this.props.isContentActive(); const scale = (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1); const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; - const interactive = (CurrentUserUtils.SelectedTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false); + const interactive = (CurrentUserUtils.SelectedTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || !this.layoutDoc._lockedPosition); if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(FormattedTextBoxComment.Hide); const minimal = this.props.ignoreAutoHeight; const paddingX = NumCast(this.layoutDoc._xMargin, this.props.xPadding || 0); diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 820d7ef96..64f5a296f 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -700,7 +700,7 @@ export class PresBox extends ViewBoxBaseComponent() { removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.rootDoc, this.fieldKey, doc); getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight panelHeight = () => this.props.PanelHeight() - 40; - isContentActive = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) && + isContentActive = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && !this.layoutDoc._lockedPosition) && (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) /** diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index f4dc9b615..ef918d991 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -80,7 +80,6 @@ export class PresElementBox extends ViewBoxBaseComponent() { Document={this.targetDoc} DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]} styleProvider={this.styleProvider} - layerProvider={this.props.layerProvider} docViewPath={returnEmptyDoclist} rootSelected={returnTrue} addDocument={returnFalse} diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index fb2e33e2a..5bdce273d 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -26,7 +26,7 @@ export {DocListCast(this.props.anno.textInlineAnnotations).map(a => )} -
+
; } } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 2905e96d9..152b7bbcb 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -127,7 +127,7 @@ export class SearchBox extends ViewBoxBaseComponent() { static foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) { let newarray: Doc[] = []; var depth = 0; - let visited: Doc[] = []; + const visited: Doc[] = []; while (docs.length > 0) { newarray = []; docs.filter(d => d && !visited.includes(d)).forEach(d => { diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 9de8d0831..194b3ba27 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1026,7 +1026,7 @@ export namespace Doc { if (status === DocBrushStatus.unbrushed) { const lastBrushed = Array.from(brushManager.BrushedDoc.keys()).lastElement(); if (lastBrushed) { - for (var link of LinkManager.Instance.getAllDirectLinks(lastBrushed)) { + for (const link of LinkManager.Instance.getAllDirectLinks(lastBrushed)) { const a1 = Cast(link.anchor1, Doc, null); const a2 = Cast(link.anchor2, Doc, null); if (Doc.AreProtosEqual(a1, doc) || Doc.AreProtosEqual(a2, doc) || diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx index 88221732e..418464f0e 100644 --- a/src/mobile/AudioUpload.tsx +++ b/src/mobile/AudioUpload.tsx @@ -96,7 +96,6 @@ export class AudioUpload extends React.Component { isDocumentActive={returnTrue} isContentActive={emptyFunction} focus={emptyFunction} - layerProvider={undefined} styleProvider={() => "rgba(0,0,0,0)"} docViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index cfcc48608..78ec706d7 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -214,7 +214,6 @@ export class MobileInterface extends React.Component { isContentActive={emptyFunction} focus={DocUtils.DefaultFocus} styleProvider={this.whitebackground} - layerProvider={undefined} docViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index bdea57cb2..fd000a83c 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -195,7 +195,7 @@ function proxyServe(req: any, requrl: string, response: any) { console.log("EROR?: ", e); } } else req.pipe(request(requrl)).pipe(response); - } + }; retrieveHTTPBody = () => { req.headers.cookie = ""; req.pipe(request(requrl)) -- cgit v1.2.3-70-g09d2