diff --git a/README.md b/README.md index 61a5407..9d2930f 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,11 @@ Developed based on [Snapdrop](https://github.com/RobinLinus/snapdrop) * On iOS and Android the devices share menu is opened instead of downloading the files * Multiple files are transferred at once with an overall progress indicator -### Share Files Directly From Share / Context Menu -* [Share files directly from context menu on Windows](/docs/how-to.md#share-files-directly-from-context-menu-on-windows) -* [Share directly from share menu on iOS](/docs/how-to.md#share-directly-from-share-menu-on-ios) -* [Share directly from share menu on Android](/docs/how-to.md#share-directly-from-share-menu-on-android) - +### Send Files or Text Directly From Share Menu, Context Menu or CLI +* [Send files directly from context menu on Windows](/docs/how-to.md#send-files-directly-from-context-menu-on-windows) +* [Send directly from share menu on iOS](/docs/how-to.md#send-directly-from-share-menu-on-ios) +* [Send directly from share menu on Android](/docs/how-to.md#send-directly-from-share-menu-on-android) +* [Send directly via command-line interface](/docs/how-to.md#send-directly-via-command-line-interface) ### Other changes * [Paste Mode](https://github.com/RobinLinus/snapdrop/pull/534) diff --git a/docs/faq.md b/docs/faq.md index 2385a47..e19770e 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -33,12 +33,16 @@ iOS Shortcuts to the win: I created a simple iOS shortcut that takes your photos and saves them to your gallery: https://routinehub.co/shortcut/13988/ -### Is it possible to share files directly from the context / share menu? -Yes it finally is! -* [Share files directly from context menu on Windows](/docs/how-to.md#share-files-directly-from-context-menu-on-windows) -* [Share directly from share menu on iOS](/docs/how-to.md#share-directly-from-share-menu-on-ios) -* [Share directly from share menu on Android](/docs/how-to.md#share-directly-from-share-menu-on-android) +### Is it possible to send files or text directly from the context or share menu? +Yes, it finally is! +* [Send files directly from context menu on Windows](/docs/how-to.md#send-files-directly-from-context-menu-on-windows) +* [Send directly from share menu on iOS](/docs/how-to.md#send-directly-from-share-menu-on-ios) +* [Send directly from share menu on Android](/docs/how-to.md#send-directly-from-share-menu-on-android) +### Is it possible to send files or text directly via CLI? +Yes, it is! + +* [Send directly from command-line interface](/docs/how-to.md#send-directly-via-command-line-interface) ### What about the connection? Is it a P2P-connection directly from device to device or is there any third-party-server? It uses a P2P connection if WebRTC is supported by the browser. WebRTC needs a Signaling Server, but it is only used to establish a connection and is not involved in the file transfer. diff --git a/docs/how-to.md b/docs/how-to.md index 18c0fbd..621ce5a 100644 --- a/docs/how-to.md +++ b/docs/how-to.md @@ -1,5 +1,5 @@ # How-To -## Share files directly from context menu on Windows +## Send files directly from context menu on Windows ### Registering to open files with PairDrop The [File Handling API](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/handle-files) is implemented @@ -25,17 +25,58 @@ Outstandingly, it is also possible to send multiple files to PairDrop via the co [//]: # (Todo: add screenshots) -## Share directly from share menu on iOS +## Send directly from share menu on iOS I created an iOS shortcut to send images, files, folder, URLs or text directly from the share-menu https://routinehub.co/shortcut/13990/ [//]: # (Todo: add doku with screenshots) -## Share directly from share menu on Android +## Send directly from share menu on Android The [Web Share Target API](https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target) is implemented but not yet tested. When the PWA is installed, it should register itself to the share-menu of the device automatically. -Please test this feature and create an issue if it does not work. +This feature is still under development. Please test this feature and create an issue if it does not work. + +## Send directly via command-line interface +Send files or text with PairDrop via command-line interface. + +This opens PairDrop in the default browser where you can choose the receiver. + +### Usage +```bash +$ pairdrop -h +Current domain: https://pairdrop.net/ + +Usage: +Open PairDrop: pairdrop +Send files: pairdrop file/directory +Send text: pairdrop -t "text" +Specify domain: pairdrop -d "https://pairdrop.net/" +Show this help text: pairdrop (-h|--help) +``` + +On Windows Command Prompt you need to use bash: `bash pairdrop -h` + + +### Setup +Download the bash file: [pairdrop-cli/pairdrop](/pairdrop-cli/pairdrop). + +#### Linux +1. Put file in a preferred folder e.g. `/usr/local/bin` +2. Make sure the bash file is executable. Otherwise, use `chmod +x pairdrop` +3. Add absolute path of the folder to PATH variable to make `pairdrop` available globally by executing + `export PATH=$PATH:/opt/pairdrop-cli` + +#### Mac +1. add bash file to `/usr/local/bin` + +#### Windows +1. Put file in a preferred folder e.g. `C:\Users\Public\pairdrop-cli` +2. Search for and open `Edit environment variables for your account` +3. Click `Environment Variables...` +4. Under *System Variables* select `Path` and click *Edit...* +5. Click *New*, insert the preferred folder (`C:\Users\Public\pairdrop-cli`), click *OK* until all windows are closed +6. Reopen Command prompt window [< Back](/README.md) diff --git a/pairdrop-cli/pairdrop b/pairdrop-cli/pairdrop new file mode 100644 index 0000000..5a36d2e --- /dev/null +++ b/pairdrop-cli/pairdrop @@ -0,0 +1,199 @@ +#!/bin/bash +set -e + +############################################################ +# Help # +############################################################ +help() +{ + # Display Help + echo "Send files or text with PairDrop via command-line interface." + echo "Current domain: ${DOMAIN}" + echo + echo "Usage:" + echo -e "Open PairDrop:\t\t$(basename "$0")" + echo -e "Send files:\t\t$(basename "$0") file/directory" + echo -e "Send text:\t\t$(basename "$0") -t \"text\"" + echo -e "Specify domain:\t\t$(basename "$0") -d \"https://pairdrop.net/\"" + echo -e "Show this help text:\t$(basename "$0") (-h|--help)" +} + +openPairDrop() +{ + url="$DOMAIN" + if [[ -n $params ]];then + url="${url}?${params}" + fi + if [[ -n $hash ]];then + url="${url}#${hash}" + fi + + echo "PairDrop is opening at $DOMAIN" + if [[ $OS == "Windows" ]];then + start "$url" + elif [[ $OS == "Mac" ]];then + open "$url" + elif [[ $OS == "WSL" || $OS == "WSL2" ]];then + powershell.exe /c "Start-Process ${url}" + else + xdg-open "$url" + fi + exit +} + +setOs() +{ + unameOut=$(uname -a) + case "${unameOut}" in + *Microsoft*) OS="WSL";; #must be first since Windows subsystem for linux will have Linux in the name too + *microsoft*) OS="WSL2";; #WARNING: My v2 uses ubuntu 20.4 at the moment slightly different name may not always work + Linux*) OS="Linux";; + Darwin*) OS="Mac";; + CYGWIN*) OS="Cygwin";; + MINGW*) OS="Windows";; + *Msys) OS="Windows";; + *) OS="UNKNOWN:${unameOut}" + esac +} + +specifyDomain() +{ + [[ ! $1 = http* ]] || [[ ! $1 = */ ]] && echo "Incorrect format. Specify domain like https://pairdrop.net/" && exit + echo "DOMAIN=${1}" > "$CONFIGPATH" + echo -e "Domain is now set to:\n$1\n" +} + +sendText() +{ + params="base64text=hash" + hash=$(echo -n "${OPTARG}" | base64) + + if [[ $(echo -n "$hash" | wc -m) -gt 32600 ]];then + params="base64text=paste" + if [[ $OS == "Windows" || $OS == "WSL" || $OS == "WSL2" ]];then + echo -n "$hash" | clip.exe + elif [[ $OS == "Mac" ]];then + echo -n "$hash" | pbcopy + else + (echo -n "$hash" | xclip) || echo "You need to install xclip for sending bigger files from cli" + fi + hash= + fi + + openPairDrop + exit +} + +sendFiles() +{ + params="base64zip=hash" + if [[ $1 == */ ]]; then + path="${1::-1}" + else + path=$1 + fi + zipPath="${path}_pairdrop.zip" + zipPath=${zipPath// /_} + + [[ -a "$zipPath" ]] && echo "Cannot overwrite $zipPath. Please remove first." && exit + + if [[ -d $path ]]; then + zipPathTemp="temp_${zipPath}" + [[ -a "$zipPathTemp" ]] && echo "Cannot overwrite $zipPathTemp. Please remove first." && exit + echo "Processing directory..." + + # Create zip files temporarily to send directory + zip -q -b /tmp/ -r "$zipPath" "$path" + zip -q -b /tmp/ "$zipPathTemp" "$zipPath" + + hash=$(base64 -w 0 "$zipPathTemp") + + # remove temporary temp file + rm "$zipPathTemp" + else + echo "Processing file..." + + # Create zip file temporarily to send file + zip -q -b /tmp/ "$zipPath" "$path" + + hash=$(base64 -w 0 "$zipPath") + fi + + # remove temporary temp file + rm "$zipPath" + + if [[ $(echo -n "$hash" | wc -m) -gt 32600 ]];then + params="base64zip=paste" + if [[ $OS == "Windows" || $OS == "WSL" || $OS == "WSL2" ]];then + echo -n "$hash" | clip.exe + elif [[ $OS == "Mac" ]];then + echo -n "$hash" | pbcopy + else + (echo -n "$hash" | xclip) || echo "You need to install xclip for sending bigger files from cli" + fi + hash= + fi + + openPairDrop + exit +} + +############################################################ +############################################################ +# Main program # +############################################################ +############################################################ +SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + +pushd . > '/dev/null'; +SCRIPTPATH="${BASH_SOURCE[0]:-$0}"; + +while [ -h "$SCRIPTPATH" ]; +do + cd "$( dirname -- "$SCRIPTPATH"; )"; + SCRIPTPATH="$( readlink -f -- "$SCRIPTPATH"; )"; +done + +cd "$( dirname -- "$SCRIPTPATH"; )" > '/dev/null'; +SCRIPTPATH="$( pwd; )"; +popd > '/dev/null'; + +CONFIGPATH="${SCRIPTPATH}/.pairdrop-cli-config" + +[ ! -f "$CONFIGPATH" ] && + specifyDomain "https://pairdrop.net/" && + [ ! -f "$CONFIGPATH" ] && + echo "Could not create config file. Add 'DOMAIN=https://pairdrop.net/' to a file called .pairdrop-cli-config in the same file as this 'pairdrop' bash file" + +[ ! -f "$CONFIGPATH" ] || export "$(grep -v '^#' "$CONFIGPATH" | xargs)" + +setOs +############################################################ +# Process the input options. Add options as needed. # +############################################################ +# Get the options +# open PairDrop if no options are given +[[ $# -eq 0 ]] && openPairDrop && exit + +# display help and exit if first argument is "--help" or more than 2 arguments are given +[ "$1" == "--help" ] || [[ $# -gt 2 ]] && help && exit + +while getopts "d:ht:*" option; do + case $option in + d) # specify domain + specifyDomain "$2" + exit;; + t) # Send text + sendText + exit;; + h | ?) # display help and exit + help + exit;; + esac +done + +# Send file(s) +# display help and exit if 2 arguments are given or if file does not exist +[[ $# -eq 2 ]] || [[ ! -a $1 ]] && help && exit + +sendFiles "$1" diff --git a/public/index.html b/public/index.html index 08eed7d..14d50cf 100644 --- a/public/index.html +++ b/public/index.html @@ -213,11 +213,11 @@ - - + + - + diff --git a/public/scripts/ui.js b/public/scripts/ui.js index ce484e4..f829f32 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -143,7 +143,7 @@ class PeersUI { descriptor = `${files[0].name} and ${files.length-1} other files`; noPeersMessage = `Open PairDrop on other devices to send
${descriptor}`; } else { - descriptor = "pasted text"; + descriptor = "shared text"; noPeersMessage = `Open PairDrop on other devices to send
${descriptor}`; } @@ -1081,67 +1081,135 @@ class ReceiveTextDialog extends Dialog { class Base64ZipDialog extends Dialog { constructor() { - super('base64ZipDialog'); + super('base64PasteDialog'); const urlParams = new URL(window.location).searchParams; - const base64Zip = urlParams.get('base64zip'); const base64Text = urlParams.get('base64text'); - this.$pasteBtn = this.$el.querySelector('#base64ZipPasteBtn') - this.$pasteBtn.addEventListener('click', _ => this.processClipboard()) + const base64Zip = urlParams.get('base64zip'); + const base64Hash = window.location.hash.substring(1); + + this.$pasteBtn = this.$el.querySelector('#base64PasteBtn'); if (base64Text) { - this.processBase64Text(base64Text); - } else if (base64Zip) { - if (!navigator.clipboard.readText) { - setTimeout(_ => Events.fire('notify-user', 'This feature is not available on your device.'), 500); - this.clearBrowserHistory(); - return; - } this.show(); + if (base64Text === "paste") { + // ?base64text=paste + // base64 encoded string is ready to be pasted from clipboard + this.$pasteBtn.innerText = 'Tap here to paste text'; + this.$pasteBtn.addEventListener('click', _ => this.processClipboard('text')); + } else if (base64Text === "hash") { + // ?base64text=hash#BASE64ENCODED + // base64 encoded string is url hash which is never sent to server and faster (recommended) + this.processBase64Text(base64Hash) + .catch(_ => { + Events.fire('notify-user', 'Text content is incorrect.'); + console.log("Text content incorrect.") + }).finally(_ => { + this.hide(); + }); + } else { + // ?base64text=BASE64ENCODED + // base64 encoded string was part of url param (not recommended) + this.processBase64Text(base64Text) + .catch(_ => { + Events.fire('notify-user', 'Text content is incorrect.'); + console.log("Text content incorrect.") + }).finally(_ => { + this.hide(); + }); + } + } else if (base64Zip) { + this.show(); + if (base64Zip === "hash") { + // ?base64zip=hash#BASE64ENCODED + // base64 encoded zip file is url hash which is never sent to the server + this.processBase64Zip(base64Hash) + .catch(_ => { + Events.fire('notify-user', 'File content is incorrect.'); + console.log("File content incorrect.") + }).finally(_ => { + this.hide(); + }); + } else { + // ?base64zip=paste || ?base64zip=true + this.$pasteBtn.innerText = 'Tap here to paste files'; + this.$pasteBtn.addEventListener('click', _ => this.processClipboard('file')); + } + } + } + + _setPasteBtnToProcessing() { + this.$pasteBtn.pointerEvents = "none"; + this.$pasteBtn.innerText = "Processing..."; + } + + async processClipboard(type) { + if (!navigator.clipboard.readText) { + Events.fire('notify-user', 'This feature is not available on your browser.'); + console.log("navigator.clipboard.readText() is not available on your browser.") + this.hide(); + return; + } + + this._setPasteBtnToProcessing(); + + const base64 = await navigator.clipboard.readText(); + + if (!base64) return; + + if (type === "text") { + this.processBase64Text(base64) + .catch(_ => { + Events.fire('notify-user', 'Clipboard content is incorrect.'); + console.log("Clipboard content is incorrect.") + }).finally(_ => { + this.hide(); + }); + } else { + this.processBase64Zip(base64) + .catch(_ => { + Events.fire('notify-user', 'Clipboard content is incorrect.'); + console.log("Clipboard content is incorrect.") + }).finally(_ => { + this.hide(); + }); } } processBase64Text(base64Text){ - try { + return new Promise((resolve) => { + this._setPasteBtnToProcessing(); let decodedText = decodeURIComponent(escape(window.atob(base64Text))); Events.fire('activate-paste-mode', {files: [], text: decodedText}); - } catch (e) { - setTimeout(_ => Events.fire('notify-user', 'Content incorrect.'), 500); - } finally { - this.clearBrowserHistory(); - this.hide(); - } + resolve(); + }); } - async processClipboard() { - this.$pasteBtn.pointerEvents = "none"; - this.$pasteBtn.innerText = "Processing..."; - try { - const base64zip = await navigator.clipboard.readText(); - let bstr = atob(base64zip), n = bstr.length, u8arr = new Uint8Array(n); - while (n--) { - u8arr[n] = bstr.charCodeAt(n); - } - - const zipBlob = new File([u8arr], 'archive.zip'); - - let files = []; - const zipEntries = await zipper.getEntries(zipBlob); - for (let i = 0; i < zipEntries.length; i++) { - let fileBlob = await zipper.getData(zipEntries[i]); - files.push(new File([fileBlob], zipEntries[i].filename)); - } - Events.fire('activate-paste-mode', {files: files, text: ""}) - } catch (e) { - Events.fire('notify-user', 'Clipboard content is incorrect.') - } finally { - this.clearBrowserHistory(); - this.hide(); + async processBase64Zip(base64zip) { + this._setPasteBtnToProcessing(); + let bstr = atob(base64zip), n = bstr.length, u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); } + + const zipBlob = new File([u8arr], 'archive.zip'); + + let files = []; + const zipEntries = await zipper.getEntries(zipBlob); + for (let i = 0; i < zipEntries.length; i++) { + let fileBlob = await zipper.getData(zipEntries[i]); + files.push(new File([fileBlob], zipEntries[i].filename)); + } + Events.fire('activate-paste-mode', {files: files, text: ""}); } clearBrowserHistory() { window.history.replaceState({}, "Rewrite URL", '/'); } + + hide() { + this.clearBrowserHistory(); + super.hide(); + } } class Toast extends Dialog { diff --git a/public/styles.css b/public/styles.css index 7497b77..dcec033 100644 --- a/public/styles.css +++ b/public/styles.css @@ -605,21 +605,21 @@ x-dialog .row-reverse { margin-bottom: 25px; } -#base64ZipPasteBtn { +#base64PasteBtn { width: 100%; height: 40vh; border: solid 12px #438cff; } -#base64ZipDialog button { +#base64PasteDialog button { margin: auto; border-radius: 8px; } -#base64ZipDialog button[close] { +#base64PasteDialog button[close] { margin-top: 20px; } -#base64ZipDialog button[close]:before { +#base64PasteDialog button[close]:before { border-radius: 8px; } diff --git a/public_included_ws_fallback/index.html b/public_included_ws_fallback/index.html index 534d06d..bc7bc22 100644 --- a/public_included_ws_fallback/index.html +++ b/public_included_ws_fallback/index.html @@ -216,11 +216,11 @@
- - + + - + diff --git a/public_included_ws_fallback/scripts/ui.js b/public_included_ws_fallback/scripts/ui.js index ba48292..796230f 100644 --- a/public_included_ws_fallback/scripts/ui.js +++ b/public_included_ws_fallback/scripts/ui.js @@ -143,7 +143,7 @@ class PeersUI { descriptor = `${files[0].name} and ${files.length-1} other files`; noPeersMessage = `Open PairDrop on other devices to send
${descriptor}`; } else { - descriptor = "pasted text"; + descriptor = "shared text"; noPeersMessage = `Open PairDrop on other devices to send
${descriptor}`; } @@ -1082,67 +1082,135 @@ class ReceiveTextDialog extends Dialog { class Base64ZipDialog extends Dialog { constructor() { - super('base64ZipDialog'); + super('base64PasteDialog'); const urlParams = new URL(window.location).searchParams; - const base64Zip = urlParams.get('base64zip'); const base64Text = urlParams.get('base64text'); - this.$pasteBtn = this.$el.querySelector('#base64ZipPasteBtn') - this.$pasteBtn.addEventListener('click', _ => this.processClipboard()) + const base64Zip = urlParams.get('base64zip'); + const base64Hash = window.location.hash.substring(1); + + this.$pasteBtn = this.$el.querySelector('#base64PasteBtn'); if (base64Text) { - this.processBase64Text(base64Text); - } else if (base64Zip) { - if (!navigator.clipboard.readText) { - setTimeout(_ => Events.fire('notify-user', 'This feature is not available on your device.'), 500); - this.clearBrowserHistory(); - return; - } this.show(); + if (base64Text === "paste") { + // ?base64text=paste + // base64 encoded string is ready to be pasted from clipboard + this.$pasteBtn.innerText = 'Tap here to paste text'; + this.$pasteBtn.addEventListener('click', _ => this.processClipboard('text')); + } else if (base64Text === "hash") { + // ?base64text=hash#BASE64ENCODED + // base64 encoded string is url hash which is never sent to server and faster (recommended) + this.processBase64Text(base64Hash) + .catch(_ => { + Events.fire('notify-user', 'Text content is incorrect.'); + console.log("Text content incorrect.") + }).finally(_ => { + this.hide(); + }); + } else { + // ?base64text=BASE64ENCODED + // base64 encoded string was part of url param (not recommended) + this.processBase64Text(base64Text) + .catch(_ => { + Events.fire('notify-user', 'Text content is incorrect.'); + console.log("Text content incorrect.") + }).finally(_ => { + this.hide(); + }); + } + } else if (base64Zip) { + this.show(); + if (base64Zip === "hash") { + // ?base64zip=hash#BASE64ENCODED + // base64 encoded zip file is url hash which is never sent to the server + this.processBase64Zip(base64Hash) + .catch(_ => { + Events.fire('notify-user', 'File content is incorrect.'); + console.log("File content incorrect.") + }).finally(_ => { + this.hide(); + }); + } else { + // ?base64zip=paste || ?base64zip=true + this.$pasteBtn.innerText = 'Tap here to paste files'; + this.$pasteBtn.addEventListener('click', _ => this.processClipboard('file')); + } + } + } + + _setPasteBtnToProcessing() { + this.$pasteBtn.pointerEvents = "none"; + this.$pasteBtn.innerText = "Processing..."; + } + + async processClipboard(type) { + if (!navigator.clipboard.readText) { + Events.fire('notify-user', 'This feature is not available on your browser.'); + console.log("navigator.clipboard.readText() is not available on your browser.") + this.hide(); + return; + } + + this._setPasteBtnToProcessing(); + + const base64 = await navigator.clipboard.readText(); + + if (!base64) return; + + if (type === "text") { + this.processBase64Text(base64) + .catch(_ => { + Events.fire('notify-user', 'Clipboard content is incorrect.'); + console.log("Clipboard content is incorrect.") + }).finally(_ => { + this.hide(); + }); + } else { + this.processBase64Zip(base64) + .catch(_ => { + Events.fire('notify-user', 'Clipboard content is incorrect.'); + console.log("Clipboard content is incorrect.") + }).finally(_ => { + this.hide(); + }); } } processBase64Text(base64Text){ - try { + return new Promise((resolve) => { + this._setPasteBtnToProcessing(); let decodedText = decodeURIComponent(escape(window.atob(base64Text))); Events.fire('activate-paste-mode', {files: [], text: decodedText}); - } catch (e) { - setTimeout(_ => Events.fire('notify-user', 'Content incorrect.'), 500); - } finally { - this.clearBrowserHistory(); - this.hide(); - } + resolve(); + }); } - async processClipboard() { - this.$pasteBtn.pointerEvents = "none"; - this.$pasteBtn.innerText = "Processing..."; - try { - const base64zip = await navigator.clipboard.readText(); - let bstr = atob(base64zip), n = bstr.length, u8arr = new Uint8Array(n); - while (n--) { - u8arr[n] = bstr.charCodeAt(n); - } - - const zipBlob = new File([u8arr], 'archive.zip'); - - let files = []; - const zipEntries = await zipper.getEntries(zipBlob); - for (let i = 0; i < zipEntries.length; i++) { - let fileBlob = await zipper.getData(zipEntries[i]); - files.push(new File([fileBlob], zipEntries[i].filename)); - } - Events.fire('activate-paste-mode', {files: files, text: ""}) - } catch (e) { - Events.fire('notify-user', 'Clipboard content is incorrect.') - } finally { - this.clearBrowserHistory(); - this.hide(); + async processBase64Zip(base64zip) { + this._setPasteBtnToProcessing(); + let bstr = atob(base64zip), n = bstr.length, u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); } + + const zipBlob = new File([u8arr], 'archive.zip'); + + let files = []; + const zipEntries = await zipper.getEntries(zipBlob); + for (let i = 0; i < zipEntries.length; i++) { + let fileBlob = await zipper.getData(zipEntries[i]); + files.push(new File([fileBlob], zipEntries[i].filename)); + } + Events.fire('activate-paste-mode', {files: files, text: ""}); } clearBrowserHistory() { window.history.replaceState({}, "Rewrite URL", '/'); } + + hide() { + this.clearBrowserHistory(); + super.hide(); + } } class Toast extends Dialog { diff --git a/public_included_ws_fallback/styles.css b/public_included_ws_fallback/styles.css index 8d3c5e0..9df5852 100644 --- a/public_included_ws_fallback/styles.css +++ b/public_included_ws_fallback/styles.css @@ -614,21 +614,21 @@ x-dialog .row-reverse { margin-bottom: 25px; } -#base64ZipPasteBtn { +#base64PasteBtn { width: 100%; height: 40vh; border: solid 12px #438cff; } -#base64ZipDialog button { +#base64PasteDialog button { margin: auto; border-radius: 8px; } -#base64ZipDialog button[close] { +#base64PasteDialog button[close] { margin-top: 20px; } -#base64ZipDialog button[close]:before { +#base64PasteDialog button[close]:before { border-radius: 8px; }