feat: add drag-and-drop in web interface (#5082)

This commit is contained in:
Derek Reiff 2023-04-15 13:45:57 -07:00 committed by GitHub
parent 06c784f639
commit 60d4bedf33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 34 deletions

View File

@ -4,9 +4,11 @@
// Colors related to torrent status
$blue-100: #dbedff;
$blue-300: #79b8ff;
$blue-500: #0366d6;
$green-200: #bef5cb;
$green-300: #85e89d;
$green-500: #28a745;
$green-700: #22863a;
$grey-200: #e1e4e8;
$grey-500: #828282;
$grey-700: #373737;
@ -14,6 +16,7 @@ $grey-800: #292929;
$grey-900: #191919;
$red-500: #d73a49;
$white: #fff;
$dark-mode-white: #c9d1d9;
$yellow-300: #ffea7f;
$grey-40: #666;
$nice-grey: #f8f8f8;
@ -82,7 +85,7 @@ $image-play-circle-idle: '../img/play-circle-idle.svg';
@media (prefers-color-scheme: dark) {
--color-bg-hover: #{$grey-40};
--color-fg-primary: #fff;
--color-fg-primary: #{$dark-mode-white};
--color-bg-primary: #{$grey-800};
--color-bg-primary-hover: #{$grey-700};
--color-bg-odd: #{$grey-900};
@ -90,29 +93,38 @@ $image-play-circle-idle: '../img/play-circle-idle.svg';
--color-bg-menu: #{$grey-800};
--color-fg-secondary: #{$nice-grey};
--color-fg-on-popup: #{$nice-grey};
--color-fg-disabled: #{$nice-grey};
--color-fg-disabled: #{$dark-mode-white};
--color-bg-popup: #{$grey-800};
--color-bg-warn: #cf6679;
--color-fg-warn: #{$dark-mode-black};
--color-border: #{$nice-grey};
--color-border-selected: #d0d7de;
--color-border: #{$dark-mode-white};
--color-border-selected: #{$grey-500};
--color-fg-tertiary: #{$grey-500};
--color-toolbar-background: #{$grey-800};
--color-inspector-background: #{$grey-800};
--color-inspector-tabs: #{$nice-grey};
--color-bg-selected: #{$default-accent-color-dark};
--color-bg-tabs: #{$grey-700};
--color-progressbar-background-1: #426389;
--color-default-border: #{$default-border-dark};
--color-progressbar-seed-1: #{$green-500};
--color-progressbar-seed-2: #{$green-300};
--color-progressbar-seed-1: #{$green-700};
--color-progressbar-seed-2: #{$green-500};
--color-progressbar-paused: #{$grey-500};
--color-progressbar-leech: #{$blue-500};
--color-progressbar-seed-paused: #{$grey-500};
}
@media (prefers-color-scheme: light) {
--progress: 100%;
--color-fg-error: #{$red-500};
--color-fg-port-closed: #{$red-500};
--color-fg-port-open: #{$green-500};
--color-progressbar-verify: #{$yellow-300};
--color-progressbar-magnet: #{$yellow-300};
--color-progressbar-paused: #{$grey-200};
--color-progressbar-leech: #{$blue-300};
--color-progressbar-queued: #{$blue-100};
--color-bg-hover: #{$nice-grey};
--color-fg-primary: #404040;
--color-bg-primary: #fff;
--color-bg-primary: #{$white};
--color-bg-even: #{$white};
--color-bg-odd: #{$nice-grey};
--color-bg-menu: #{$nice-grey};
@ -130,7 +142,6 @@ $image-play-circle-idle: '../img/play-circle-idle.svg';
--color-bg-tabs: #{$nice-grey-darker};
--color-inspector-tabs: #{$nice-grey};
--color-bg-selected: #{$default-accent-color};
--color-progressbar-background-1: #{$nice-grey};
--color-default-border: #{$default-border-light};
--color-dialog-border: #{$nice-grey};
--color-progressbar-seed-1: #{$green-300};
@ -467,7 +478,7 @@ $video-image: '../img/film.svg';
.torrent-progress-details,
.torrent-peer-details {
color: var(--color-fg-primary);
font-size: x-small;
font-size: small;
}
&.compact {
@ -880,6 +891,7 @@ $video-image: '../img/film.svg';
border: 1px solid transparent;
border-radius: 6px;
color: var(--color-fg-primary);
font-weight: 400;
}
}
@ -908,7 +920,6 @@ $video-image: '../img/film.svg';
background-color: var(--color-bg-even);
border: 1px solid var(--color-fg-primary);
border-radius: 6px;
font-weight: 500;
}
}
@ -1314,6 +1325,7 @@ $video-image: '../img/film.svg';
a,
button,
label {
color: var(--color-fg-primary);
display: inline-flex;
font-size: 1em;
width: 100%;
@ -1646,18 +1658,28 @@ dialog {
font-style: italic;
}
#torrent-upload-frame {
border: 0;
display: block; /* Don't change this : safari forms won't target hidden frames (they open a new window) */
height: 0;
left: -1000px;
margin: 0;
padding: 0;
position: absolute;
top: -1000px;
width: 0;
}
.ui-menu {
width: 200px;
}
.upload-div {
display: none;
}
.dropzone {
background: var(--color-bg-primary);
border: 2px dashed var(--color-border);
border-radius: 5px;
color: var(--color-fg-primary);
cursor: pointer;
display: flex;
flex-direction: column;
font-size: 1.2em;
font-weight: bold;
height: 100%;
justify-content: center;
margin: 0;
padding: 0;
text-align: center;
width: 100%;
}

View File

@ -212,12 +212,9 @@
</div>
</main>
<iframe
name="torrent-upload-frame"
id="torrent-upload-frame"
src="about:blank"
title="Add Torrent"
></iframe>
<div class="upload-div">
<h2>Drag your torrent files here to add them to Transmission.</h2>
</div>
</div>
</body>
</html>

View File

@ -8,7 +8,7 @@ import { Formatter } from './formatter.js';
import { createDialogContainer, makeUUID } from './utils.js';
export class OpenDialog extends EventTarget {
constructor(controller, remote, url = '') {
constructor(controller, remote, url = '', files = []) {
super();
this.controller = controller;
@ -17,8 +17,11 @@ export class OpenDialog extends EventTarget {
this.elements = this._create(url);
this.elements.dismiss.addEventListener('click', () => this._onDismiss());
this.elements.confirm.addEventListener('click', () => this._onConfirm());
this._updateFreeSpaceInAddDialog();
document.body.append(this.elements.root);
if (files.length > 0) {
this.elements.file_input.files = files;
}
this._updateFreeSpaceInAddDialog();
this.elements.url_input.focus();
}

View File

@ -557,7 +557,10 @@ export class Transmission extends EventTarget {
static _dragenter(event_) {
if (event_.dataTransfer && event_.dataTransfer.types) {
const copy_types = new Set(['text/uri-list', 'text/plain']);
if (event_.dataTransfer.types.some((type) => copy_types.has(type))) {
if (
event_.dataTransfer.types.some((type) => copy_types.has(type)) ||
event_.dataTransfer.types.includes('Files')
) {
event_.stopPropagation();
event_.preventDefault();
event_.dataTransfer.dropEffect = 'copy';
@ -589,8 +592,8 @@ export class Transmission extends EventTarget {
return true;
}
const type = event_.data.Transfer.types
.filter((t) => ['text/uri-list', 'text/plain'].contains(t))
const type = event_.dataTransfer.types
.filter((t) => ['text/uri-list', 'text/plain'].includes(t))
.pop();
for (const uri of event_.dataTransfer
.getData(type)
@ -600,6 +603,11 @@ export class Transmission extends EventTarget {
this.remote.addTorrentByUrl(uri, paused);
}
const { files } = event_.dataTransfer;
if (files.length > 0) {
this.openDialog = new OpenDialog(this, this.remote, '', files);
}
event_.preventDefault();
return false;
}