Add a notice about the "upload" dialog

Users keep getting confused about the webkit directory selection dialog that has unfortunate wording about "uploading" that I can't change. Hopefully this new dialog that displays before the dialog I can't control will help users understand that nothing is getting uploaded anywhere.

The message can be ignored in the future with a checkbox that sets a cookie.
This commit is contained in:
Tyler Hallada 2022-04-28 22:48:31 -04:00
parent c58a3a0316
commit 92ee93a3c9
4 changed files with 110 additions and 1 deletions

View File

@ -1,9 +1,11 @@
import React, { useContext, useRef, useState, useEffect } from "react"; import React, { useContext, useRef, useState, useEffect } from "react";
import Cookies from "js-cookie";
import { WorkerPoolContext } from "../lib/WorkerPool"; import { WorkerPoolContext } from "../lib/WorkerPool";
import { useAppSelector } from "../lib/hooks"; import { useAppSelector } from "../lib/hooks";
import { isPlugin, parsePluginFiles } from "../lib/plugins"; import { isPlugin, parsePluginFiles } from "../lib/plugins";
import styles from "../styles/DataDirPicker.module.css"; import styles from "../styles/DataDirPicker.module.css";
import { createPortal } from "react-dom";
type Props = {}; type Props = {};
@ -13,6 +15,9 @@ const DataDirPicker: React.FC<Props> = () => {
const plugins = useAppSelector((state) => state.plugins.plugins); const plugins = useAppSelector((state) => state.plugins.plugins);
const pluginsPending = useAppSelector((state) => state.plugins.pending); const pluginsPending = useAppSelector((state) => state.plugins.pending);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [uploadNoticeShown, setUploadNoticeShown] = useState(false);
const [ignoreUploadNoticeChecked, setIgnoreUploadNoticeChecked] =
useState(false);
useEffect(() => { useEffect(() => {
if (pluginsPending === 0 && loading) { if (pluginsPending === 0 && loading) {
@ -68,6 +73,53 @@ const DataDirPicker: React.FC<Props> = () => {
</strong> </strong>
. .
</p> </p>
{typeof window !== "undefined" &&
createPortal(
<dialog open={uploadNoticeShown} className={styles.dialog}>
<p>
<strong>NOTE:</strong> the following dialog will ask you to upload
all the files in your Data folder.&nbsp;
<strong>NOTHING WILL BE UPLOADED ANYWHERE</strong>. The plugin
files will only be transferred to your browser and processed on
your device.
</p>
<p>
Drag and drop the Data folder onto the web page to avoid the
upload dialog entirely.
</p>
<label>
<input
type="checkbox"
id="ignore-upload-notice"
checked={ignoreUploadNoticeChecked}
onChange={(event) => {
if (event.target.checked) {
setIgnoreUploadNoticeChecked(true);
} else {
setIgnoreUploadNoticeChecked(false);
}
}}
/>{" "}
Don&apos;t show this message again
</label>
<menu>
<button
onClick={() => {
setUploadNoticeShown(false);
if (ignoreUploadNoticeChecked) {
Cookies.set("ignoreDataDirPickerUploadNotice", "true");
}
if (inputRef.current) {
inputRef.current.click();
}
}}
>
Ok
</button>
</menu>
</dialog>,
document.body
)}
<input <input
type="file" type="file"
webkitdirectory="" webkitdirectory=""
@ -80,7 +132,11 @@ const DataDirPicker: React.FC<Props> = () => {
onClick={() => { onClick={() => {
if (inputRef.current) { if (inputRef.current) {
inputRef.current.value = ""; // clear the value so reloading same directory works inputRef.current.value = ""; // clear the value so reloading same directory works
inputRef.current.click(); if (Cookies.get("ignoreDataDirPickerUploadNotice") !== "true") {
setUploadNoticeShown(true);
} else {
inputRef.current.click();
}
} }
}} }}
disabled={!workerPool || loading} disabled={!workerPool || loading}

27
package-lock.json generated
View File

@ -12,6 +12,7 @@
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"downshift": "^6.1.7", "downshift": "^6.1.7",
"javascript-color-gradient": "^1.3.2", "javascript-color-gradient": "^1.3.2",
"js-cookie": "^3.0.1",
"mapbox-gl": "^2.6.1", "mapbox-gl": "^2.6.1",
"minisearch": "^3.2.0", "minisearch": "^3.2.0",
"next": "12.1.1-canary.15", "next": "12.1.1-canary.15",
@ -22,6 +23,7 @@
"swr": "^1.1.2" "swr": "^1.1.2"
}, },
"devDependencies": { "devDependencies": {
"@types/js-cookie": "^3.0.2",
"@types/node": "17.0.8", "@types/node": "17.0.8",
"@types/react": "17.0.38", "@types/react": "17.0.38",
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",
@ -467,6 +469,12 @@
"resolved": "https://registry.npmjs.org/@types/javascript-color-gradient/-/javascript-color-gradient-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@types/javascript-color-gradient/-/javascript-color-gradient-1.3.0.tgz",
"integrity": "sha512-wIzCbAXQPgWvAvwnJIRAy+RwMkAMp9Cv/BiQg4GQq7Vrnu9J9U3l7LbcP+UgwkkNOAXPq59jfQcPRGgPBgIAWA==" "integrity": "sha512-wIzCbAXQPgWvAvwnJIRAy+RwMkAMp9Cv/BiQg4GQq7Vrnu9J9U3l7LbcP+UgwkkNOAXPq59jfQcPRGgPBgIAWA=="
}, },
"node_modules/@types/js-cookie": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.2.tgz",
"integrity": "sha512-6+0ekgfusHftJNYpihfkMu8BWdeHs9EOJuGcSofErjstGPfPGEu9yTu4t460lTzzAMl2cM5zngQJqPMHbbnvYA==",
"dev": true
},
"node_modules/@types/json5": { "node_modules/@types/json5": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -2237,6 +2245,14 @@
"resolved": "https://registry.npmjs.org/javascript-color-gradient/-/javascript-color-gradient-1.3.2.tgz", "resolved": "https://registry.npmjs.org/javascript-color-gradient/-/javascript-color-gradient-1.3.2.tgz",
"integrity": "sha512-P/VjoTPdfRmMOkfR65m1BQTlX/hYphZIj5u1Ntvpxf+9011uXjazbEOQ63g3EhlgzHYa2uwVU3RVgy3gJuLdlQ==" "integrity": "sha512-P/VjoTPdfRmMOkfR65m1BQTlX/hYphZIj5u1Ntvpxf+9011uXjazbEOQ63g3EhlgzHYa2uwVU3RVgy3gJuLdlQ=="
}, },
"node_modules/js-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz",
"integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==",
"engines": {
"node": ">=12"
}
},
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -3786,6 +3802,12 @@
"resolved": "https://registry.npmjs.org/@types/javascript-color-gradient/-/javascript-color-gradient-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@types/javascript-color-gradient/-/javascript-color-gradient-1.3.0.tgz",
"integrity": "sha512-wIzCbAXQPgWvAvwnJIRAy+RwMkAMp9Cv/BiQg4GQq7Vrnu9J9U3l7LbcP+UgwkkNOAXPq59jfQcPRGgPBgIAWA==" "integrity": "sha512-wIzCbAXQPgWvAvwnJIRAy+RwMkAMp9Cv/BiQg4GQq7Vrnu9J9U3l7LbcP+UgwkkNOAXPq59jfQcPRGgPBgIAWA=="
}, },
"@types/js-cookie": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.2.tgz",
"integrity": "sha512-6+0ekgfusHftJNYpihfkMu8BWdeHs9EOJuGcSofErjstGPfPGEu9yTu4t460lTzzAMl2cM5zngQJqPMHbbnvYA==",
"dev": true
},
"@types/json5": { "@types/json5": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -5087,6 +5109,11 @@
"resolved": "https://registry.npmjs.org/javascript-color-gradient/-/javascript-color-gradient-1.3.2.tgz", "resolved": "https://registry.npmjs.org/javascript-color-gradient/-/javascript-color-gradient-1.3.2.tgz",
"integrity": "sha512-P/VjoTPdfRmMOkfR65m1BQTlX/hYphZIj5u1Ntvpxf+9011uXjazbEOQ63g3EhlgzHYa2uwVU3RVgy3gJuLdlQ==" "integrity": "sha512-P/VjoTPdfRmMOkfR65m1BQTlX/hYphZIj5u1Ntvpxf+9011uXjazbEOQ63g3EhlgzHYa2uwVU3RVgy3gJuLdlQ=="
}, },
"js-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz",
"integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw=="
},
"js-tokens": { "js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",

View File

@ -15,6 +15,7 @@
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"downshift": "^6.1.7", "downshift": "^6.1.7",
"javascript-color-gradient": "^1.3.2", "javascript-color-gradient": "^1.3.2",
"js-cookie": "^3.0.1",
"mapbox-gl": "^2.6.1", "mapbox-gl": "^2.6.1",
"minisearch": "^3.2.0", "minisearch": "^3.2.0",
"next": "12.1.1-canary.15", "next": "12.1.1-canary.15",
@ -25,6 +26,7 @@
"swr": "^1.1.2" "swr": "^1.1.2"
}, },
"devDependencies": { "devDependencies": {
"@types/js-cookie": "^3.0.2",
"@types/node": "17.0.8", "@types/node": "17.0.8",
"@types/react": "17.0.38", "@types/react": "17.0.38",
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",

View File

@ -9,3 +9,27 @@
.break-word { .break-word {
word-break: break-word; word-break: break-word;
} }
.dialog {
top: 12px;
z-index: 8;
background-color: #fbefd5;
box-shadow: 0 0 1em black;
max-width: 400px;
}
.dialog label {
user-select: none;
cursor: pointer;
}
.dialog menu {
padding: 0;
display: flex;
justify-content: center;
}
.dialog menu button {
font-size: 14px;
padding: 4px 8px;
}