diff --git a/frontend/src/components/ContextMenu.vue b/frontend/src/components/ContextMenu.vue
new file mode 100644
index 00000000..14663fd9
--- /dev/null
+++ b/frontend/src/components/ContextMenu.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
diff --git a/frontend/src/components/files/ListingItem.vue b/frontend/src/components/files/ListingItem.vue
index 75326f4c..932bc4b1 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"
@@ -220,6 +221,17 @@ const itemClick = (event: Event | KeyboardEvent) => {
else click(event);
};
+const contextMenu = (event: MouseEvent) => {
+ event.preventDefault();
+ if (
+ fileStore.selected.length === 0 ||
+ event.ctrlKey ||
+ fileStore.selected.indexOf(props.index) === -1
+ ) {
+ click(event);
+ }
+};
+
const click = (event: Event | KeyboardEvent) => {
if (!singleClick.value && fileStore.selectedCount !== 0)
event.preventDefault();
diff --git a/frontend/src/components/prompts/Move.vue b/frontend/src/components/prompts/Move.vue
index 6591d09d..0cb0d599 100644
--- a/frontend/src/components/prompts/Move.vue
+++ b/frontend/src/components/prompts/Move.vue
@@ -5,6 +5,7 @@
+
{{ $t("prompts.moveMessage") }}
(dest = val)"
diff --git a/frontend/src/css/context-menu.css b/frontend/src/css/context-menu.css
new file mode 100644
index 00000000..cd791364
--- /dev/null
+++ b/frontend/src/css/context-menu.css
@@ -0,0 +1,17 @@
+.context-menu {
+ position: absolute;
+ background: var(--surfacePrimary);
+ min-width: 180px;
+ max-width: 220px;
+ border: 1px solid var(--borderSecondary);
+ box-shadow: 0 2px 4px var(--borderPrimary);
+ z-index: 999;
+}
+
+.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 19b94b95..024b4886 100644
--- a/frontend/src/css/styles.css
+++ b/frontend/src/css/styles.css
@@ -17,6 +17,7 @@
@import "./mobile.css";
@import "./epubReader.css";
@import "./mdPreview.css";
+@import "./context-menu.css";
/* For testing only
:focus {
@@ -456,4 +457,4 @@ html[dir="rtl"] .card-content .small + input {
html[dir="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/FileListing.vue b/frontend/src/views/files/FileListing.vue
index 8fa48f72..e5e929e3 100644
--- a/frontend/src/views/files/FileListing.vue
+++ b/frontend/src/views/files/FileListing.vue
@@ -208,7 +208,10 @@
{{ t("files.folders") }}
-
+
-
-
{{ t("files.files") }}
-
+
+ {{ t("files.files") }}
+
+
-
+
+
+
+
+
+
+
+
+
(280);
const dragCounter = ref
(0);
const width = ref(window.innerWidth);
const itemWeight = ref(0);
+const isContextMenuVisible = ref(false);
+const contextMenuPos = ref<{ x: number; y: number }>({ x: 0, y: 0 });
const $showError = inject("$showError")!;
@@ -444,7 +502,7 @@ watch(req, () => {
onMounted(() => {
// Check the columns size for the first time.
- colunmsResize();
+ columnsResize();
// How much every listing item affects the window height
setItemWeight();
@@ -638,7 +696,7 @@ const paste = (event: Event) => {
action(overwrite, rename);
};
-const colunmsResize = () => {
+const columnsResize = () => {
// Update the columns size based on the window width.
const items_ = css(["#listing.mosaic .item", ".mosaic#listing .item"]);
if (items_ === null) return;
@@ -841,7 +899,7 @@ const toggleMultipleSelection = () => {
};
const windowsResize = throttle(() => {
- colunmsResize();
+ columnsResize();
width.value = window.innerWidth;
// Listing element is not displayed
@@ -951,4 +1009,17 @@ const fillWindow = (fit = false) => {
// Set the number of displayed items
showLimit.value = showQuantity > totalItems ? totalItems : showQuantity;
};
+
+const showContextMenu = (event: MouseEvent) => {
+ event.preventDefault();
+ isContextMenuVisible.value = true;
+ contextMenuPos.value = {
+ x: event.clientX + 8,
+ y: event.clientY + Math.floor(window.scrollY),
+ };
+};
+
+const hideContextMenu = () => {
+ isContextMenuVisible.value = false;
+};