feat: select item on file list after navigating back
This commit is contained in:
parent
bfbd78bee0
commit
9e18a2958f
@ -48,9 +48,9 @@ export default {
|
||||
"selectedCount",
|
||||
"req",
|
||||
"selected",
|
||||
"currentPrompt",
|
||||
]),
|
||||
...mapWritableState(useFileStore, ["reload"]),
|
||||
...mapState(useLayoutStore, ["currentPrompt"]),
|
||||
...mapWritableState(useFileStore, ["reload", "preselect"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
||||
@ -80,6 +80,12 @@ export default {
|
||||
|
||||
await Promise.all(promises);
|
||||
buttons.success("delete");
|
||||
|
||||
const nearbyItem =
|
||||
this.req.items[Math.max(0, Math.min(this.selected) - 1)];
|
||||
|
||||
this.preselect = nearbyItem?.path;
|
||||
|
||||
this.reload = true;
|
||||
} catch (e) {
|
||||
buttons.done("delete");
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
</button>
|
||||
<button
|
||||
id="focus-prompt"
|
||||
@click="submit"
|
||||
@click="currentPrompt.confirm"
|
||||
class="button button--flat button--red"
|
||||
:aria-label="$t('buttons.discardChanges')"
|
||||
:title="$t('buttons.discardChanges')"
|
||||
@ -30,22 +30,16 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from "pinia";
|
||||
import url from "@/utils/url";
|
||||
import { mapState, mapActions } from "pinia";
|
||||
import { useLayoutStore } from "@/stores/layout";
|
||||
import { useFileStore } from "@/stores/file";
|
||||
|
||||
export default {
|
||||
name: "discardEditorChanges",
|
||||
computed: {
|
||||
...mapState(useLayoutStore, ["currentPrompt"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
||||
...mapActions(useFileStore, ["updateRequest"]),
|
||||
submit: async function () {
|
||||
this.updateRequest(null);
|
||||
|
||||
const uri = url.removeLastDir(this.$route.path) + "/";
|
||||
this.$router.push({ path: uri });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -46,6 +46,7 @@ import { useFileStore } from "@/stores/file";
|
||||
import { useLayoutStore } from "@/stores/layout";
|
||||
import url from "@/utils/url";
|
||||
import { files as api } from "@/api";
|
||||
import { removePrefix } from "@/api/utils";
|
||||
|
||||
export default {
|
||||
name: "rename",
|
||||
@ -65,7 +66,7 @@ export default {
|
||||
"selectedCount",
|
||||
"isListing",
|
||||
]),
|
||||
...mapWritableState(useFileStore, ["reload"]),
|
||||
...mapWritableState(useFileStore, ["reload", "preselect"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
||||
@ -104,6 +105,8 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
this.preselect = removePrefix(newLink);
|
||||
|
||||
this.reload = true;
|
||||
} catch (e) {
|
||||
this.$showError(e);
|
||||
|
||||
@ -9,6 +9,7 @@ export const useFileStore = defineStore("file", {
|
||||
selected: number[];
|
||||
multiple: boolean;
|
||||
isFiles: boolean;
|
||||
preselect: string | null;
|
||||
} => ({
|
||||
req: null,
|
||||
oldReq: null,
|
||||
@ -16,6 +17,7 @@ export const useFileStore = defineStore("file", {
|
||||
selected: [],
|
||||
multiple: false,
|
||||
isFiles: false,
|
||||
preselect: null,
|
||||
}),
|
||||
getters: {
|
||||
selectedCount: (state) => state.selected.length,
|
||||
|
||||
@ -114,6 +114,32 @@ watch(uploadError, (newValue) => {
|
||||
|
||||
// Define functions
|
||||
|
||||
const applyPreSelection = () => {
|
||||
const preselect = fileStore.preselect;
|
||||
fileStore.preselect = null;
|
||||
|
||||
if (!fileStore.req?.isDir || fileStore.oldReq === null) return;
|
||||
|
||||
let index = -1;
|
||||
if (preselect) {
|
||||
// Find item with the specified path
|
||||
index = fileStore.req.items.findIndex((item) => item.path === preselect);
|
||||
} else if (fileStore.oldReq.path.startsWith(fileStore.req.path)) {
|
||||
// Get immediate child folder of the previous path
|
||||
const name = fileStore.oldReq.path
|
||||
.substring(fileStore.req.path.length)
|
||||
.split("/")
|
||||
.shift();
|
||||
|
||||
index = fileStore.req.items.findIndex(
|
||||
(val) => val.path == fileStore.req!.path + name
|
||||
);
|
||||
}
|
||||
|
||||
if (index === -1) return;
|
||||
fileStore.selected.push(index);
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
// Reset view information.
|
||||
fileStore.reload = false;
|
||||
@ -136,6 +162,9 @@ const fetchData = async () => {
|
||||
fileStore.updateRequest(res);
|
||||
document.title = `${res.name || t("sidebar.myFiles")} - ${t("files.files")} - ${name}`;
|
||||
layoutStore.loading = false;
|
||||
|
||||
// Selects the post-reload target item or the previously visited child folder
|
||||
applyPreSelection();
|
||||
} catch (err) {
|
||||
if (err instanceof StatusError && err.is_canceled) {
|
||||
return;
|
||||
|
||||
@ -146,12 +146,19 @@ onBeforeUnmount(() => {
|
||||
});
|
||||
|
||||
onBeforeRouteUpdate((to, from, next) => {
|
||||
if (!editor.value?.session.getUndoManager().isClean()) {
|
||||
layoutStore.showHover("discardEditorChanges");
|
||||
next(false);
|
||||
} else {
|
||||
if (editor.value?.session.getUndoManager().isClean()) {
|
||||
next();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
layoutStore.showHover({
|
||||
prompt: "discardEditorChanges",
|
||||
confirm: (event: Event) => {
|
||||
event.preventDefault();
|
||||
next();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const keyEvent = (event: KeyboardEvent) => {
|
||||
@ -216,13 +223,6 @@ const decreaseFontSize = () => {
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
if (!editor.value?.session.getUndoManager().isClean()) {
|
||||
layoutStore.showHover("discardEditorChanges");
|
||||
return;
|
||||
}
|
||||
|
||||
fileStore.updateRequest(null);
|
||||
|
||||
const uri = url.removeLastDir(route.path) + "/";
|
||||
router.push({ path: uri });
|
||||
};
|
||||
|
||||
@ -303,6 +303,7 @@ import {
|
||||
import { useRoute } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { removePrefix } from "@/api/utils";
|
||||
|
||||
const showLimit = ref<number>(50);
|
||||
const columnWidth = ref<number>(280);
|
||||
@ -427,8 +428,11 @@ watch(req, () => {
|
||||
// How much every listing item affects the window height
|
||||
setItemWeight();
|
||||
|
||||
// Fill and fit the window with listing items
|
||||
fillWindow(true);
|
||||
// Scroll to the item opened previously
|
||||
if (!revealPreviousItem()) {
|
||||
// Fill and fit the window with listing items
|
||||
fillWindow(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -439,8 +443,11 @@ onMounted(() => {
|
||||
// How much every listing item affects the window height
|
||||
setItemWeight();
|
||||
|
||||
// Fill and fit the window with listing items
|
||||
fillWindow(true);
|
||||
// Scroll to the item opened previously
|
||||
if (!revealPreviousItem()) {
|
||||
// Fill and fit the window with listing items
|
||||
fillWindow(true);
|
||||
}
|
||||
|
||||
// Add the needed event listeners to the window and document.
|
||||
window.addEventListener("keydown", keyEvent);
|
||||
@ -580,10 +587,13 @@ const paste = (event: Event) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const preselect = removePrefix(route.path) + items[0].name;
|
||||
|
||||
let action = (overwrite: boolean, rename: boolean) => {
|
||||
api
|
||||
.copy(items, overwrite, rename)
|
||||
.then(() => {
|
||||
fileStore.preselect = preselect;
|
||||
fileStore.reload = true;
|
||||
})
|
||||
.catch($showError);
|
||||
@ -595,6 +605,7 @@ const paste = (event: Event) => {
|
||||
.move(items, overwrite, rename)
|
||||
.then(() => {
|
||||
clipboardStore.resetClipboard();
|
||||
fileStore.preselect = preselect;
|
||||
fileStore.reload = true;
|
||||
})
|
||||
.catch($showError);
|
||||
@ -722,6 +733,8 @@ const drop = async (event: DragEvent) => {
|
||||
|
||||
const conflict = upload.checkConflict(files, items);
|
||||
|
||||
const preselect = removePrefix(path) + (files[0].fullPath || files[0].name);
|
||||
|
||||
if (conflict) {
|
||||
layoutStore.showHover({
|
||||
prompt: "replace",
|
||||
@ -729,11 +742,13 @@ const drop = async (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
layoutStore.closeHovers();
|
||||
upload.handleFiles(files, path, false);
|
||||
fileStore.preselect = preselect;
|
||||
},
|
||||
confirm: (event: Event) => {
|
||||
event.preventDefault();
|
||||
layoutStore.closeHovers();
|
||||
upload.handleFiles(files, path, true);
|
||||
fileStore.preselect = preselect;
|
||||
},
|
||||
});
|
||||
|
||||
@ -741,6 +756,7 @@ const drop = async (event: DragEvent) => {
|
||||
}
|
||||
|
||||
upload.handleFiles(files, path);
|
||||
fileStore.preselect = preselect;
|
||||
};
|
||||
|
||||
const uploadInput = (event: Event) => {
|
||||
@ -944,4 +960,21 @@ const fillWindow = (fit = false) => {
|
||||
// Set the number of displayed items
|
||||
showLimit.value = showQuantity > totalItems ? totalItems : showQuantity;
|
||||
};
|
||||
|
||||
const revealPreviousItem = () => {
|
||||
if (!fileStore.req || !fileStore.oldReq) return;
|
||||
|
||||
const index = fileStore.selected[0];
|
||||
if (index === undefined) return;
|
||||
|
||||
showLimit.value =
|
||||
index + Math.ceil((window.innerHeight * 2) / itemWeight.value);
|
||||
|
||||
nextTick(() => {
|
||||
const items = document.querySelectorAll("#listing .item");
|
||||
items[index].scrollIntoView({ block: "center" });
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -317,11 +317,16 @@ const deleteFile = () => {
|
||||
if (listing.value === null) {
|
||||
return;
|
||||
}
|
||||
listing.value = listing.value.filter((item) => item.name !== name.value);
|
||||
|
||||
const index = listing.value.findIndex((item) => item.name == name.value);
|
||||
listing.value.splice(index, 1);
|
||||
|
||||
if (hasNext.value) {
|
||||
next();
|
||||
} else if (!hasPrevious.value && !hasNext.value) {
|
||||
const nearbyItem = listing.value[Math.max(0, index - 1)];
|
||||
fileStore.preselect = nearbyItem?.path;
|
||||
|
||||
close();
|
||||
} else {
|
||||
prev();
|
||||
@ -427,8 +432,6 @@ const toggleNavigation = throttle(function () {
|
||||
}, 500);
|
||||
|
||||
const close = () => {
|
||||
fileStore.updateRequest(null);
|
||||
|
||||
const uri = url.removeLastDir(route.path) + "/";
|
||||
router.push({ path: uri });
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user