diff --git a/frontend/public/themes/dark.css b/frontend/public/themes/dark.css index eb887bfe..526abf48 100644 --- a/frontend/public/themes/dark.css +++ b/frontend/public/themes/dark.css @@ -184,6 +184,12 @@ table th { border-top: 1px solid var(--divider); } +.context-menu { + background: var(--surfacePrimary); + border: 1px solid var(--divider); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + #editor-container { background: var(--background); } diff --git a/frontend/src/components/ContextMenu.vue b/frontend/src/components/ContextMenu.vue new file mode 100644 index 00000000..5855882d --- /dev/null +++ b/frontend/src/components/ContextMenu.vue @@ -0,0 +1,48 @@ + + + diff --git a/frontend/src/components/files/ListingItem.vue b/frontend/src/components/files/ListingItem.vue index 71813bcf..310d629a 100644 --- a/frontend/src/components/files/ListingItem.vue +++ b/frontend/src/components/files/ListingItem.vue @@ -8,6 +8,7 @@ @dragover="dragOver" @drop="drop" @click="itemClick" + @contextmenu="contextMenu" :data-dir="isDir" :data-type="type" :aria-label="name" @@ -194,6 +195,25 @@ export default { if (this.singleClick && !this.$store.state.multiple) this.open(); else this.click(event); }, + contextMenu: function (event) { + const to = setTimeout(() => { + this.touches = 0; + }, 300); + + this.touches++; + if (this.touches > 1) return; + + event.preventDefault(); + if ( + this.selected.length < 2 || + event.ctrlKey || + this.$store.state.selected.indexOf(this.index) === -1 + ) { + this.touches--; + clearTimeout(to); + this.click(event); + } + }, click: function (event) { if (!this.singleClick && this.selectedCount !== 0) event.preventDefault(); diff --git a/frontend/src/css/context-menu.css b/frontend/src/css/context-menu.css new file mode 100644 index 00000000..1d9f1413 --- /dev/null +++ b/frontend/src/css/context-menu.css @@ -0,0 +1,16 @@ +.context-menu { + position: fixed; + background: #ffffff; + min-width: 180px; + border: 1px solid rgba(0, 0, 0, 0.05); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + z-index: 1000; +} + +.context-menu .action { + display: block; + width: 100%; + border-radius: 0; + display: flex; + align-items: center; +} \ No newline at end of file diff --git a/frontend/src/css/styles.css b/frontend/src/css/styles.css index 00442507..9674fa66 100644 --- a/frontend/src/css/styles.css +++ b/frontend/src/css/styles.css @@ -15,6 +15,7 @@ @import "./dashboard.css"; @import "./login.css"; @import "./mobile.css"; +@import "./context-menu.css"; .link { color: var(--blue); @@ -434,4 +435,4 @@ body.rtl .card-content .small + input { body.rtl .card.floating .card-content .file-list { direction: ltr; text-align: left; -} +} \ No newline at end of file diff --git a/frontend/src/views/files/Listing.vue b/frontend/src/views/files/Listing.vue index c204de45..c94260ea 100644 --- a/frontend/src/views/files/Listing.vue +++ b/frontend/src/views/files/Listing.vue @@ -198,39 +198,88 @@ -

{{ $t("files.folders") }}

-
- - -
+ +

{{ $t("files.folders") }}

+
+ + +
-

{{ $t("files.files") }}

-
- {{ $t("files.files") }} +
+ + +
+ -
-
+ + + + + + + + +
totalItems ? totalItems : showQuantity; }, + showContextMenu(event) { + this.isContextMenuVisible = true; + this.contextMenuPos = { + x: event.clientX, + y: event.clientY, + }; + }, + hideContextMenu() { + this.isContextMenuVisible = false; + }, }, };