add history buttons and navigator

This commit is contained in:
Salem Yaslem 2023-05-29 19:51:08 +03:00
parent a06b9b7f67
commit a30eff90a6
4 changed files with 120 additions and 25 deletions

57
app.vue
View File

@ -17,7 +17,8 @@ let files = ref([]);
let filesList = ref<any>([]);
let selectedItem = useSelectedItem();
let filesGridList = ref<any>([])
let selectedList = ref<any>([])
let selectedList = ref<any>([]);
let history = new HistorySwitcher(selectedItem);
watchEffect(async () => {
if (files.value?.[0]) {
@ -47,7 +48,7 @@ watchEffect(async () => {
})
function onDrop(e: any) {
if(!e.dataTransfer.files.length) return;
if (!e.dataTransfer.files.length) return;
files.value = e.dataTransfer.files;
selectedItem.value = '/';
}
@ -102,11 +103,6 @@ watchEffect(() => {
}
})
watchEffect(() => {
console.log(selectedList.value)
})
let dragContainer = document.querySelector(".select-area");
function onSelectStart(e: any) {
@ -131,6 +127,16 @@ function onSelectEnd(e: any) {
});
}
// step up from current path
function stepUp(path: string) {
let pathArray = path.split("/");
if(path.endsWith("/")) {
pathArray.pop();
}
pathArray.pop();
return (pathArray.join("/") || "")+ "/";
}
</script>
<template>
<v-layout @drop.prevent="onDrop">
@ -147,16 +153,30 @@ function onSelectEnd(e: any) {
<TreeView :filesList="filesList" :nav=true></TreeView>
</v-navigation-drawer>
<v-main class="select-area" style="height: 100vh;">
<v-toolbar class="px-5" density="comfortable">
<v-text-field hide-details single-line placeholder="location" v-model="selectedItem"></v-text-field>
<v-toolbar class="px-5" height="auto">
<v-row align="center" justify="center">
<v-col cols="12" lg="2" md="12">
<v-btn title="Back" aria-label="Back" icon="mdi-arrow-left" :disabled="!history.hasUndo.value"
@click="history.undo()"></v-btn>
<v-btn title="Forward" aria-label="Forward" icon="mdi-arrow-right" :disabled="!history.hasRedo.value"
@click="history.redo()"></v-btn>
<v-btn title="Refresh" aria-label="Refresh" icon="mdi-refresh" @click="history.refresh()"></v-btn>
<v-btn title="Parent Folder" aria-label="Parent Folder" icon="mdi-arrow-up"
:disabled="selectedItem == '/'" @click="selectedItem = stepUp(selectedItem)"></v-btn>
</v-col>
<v-col cols="12" lg="10" md="12">
<v-text-field hide-details single-line placeholder="location" v-model="selectedItem"></v-text-field>
</v-col>
</v-row>
</v-toolbar>
<template v-if="selectedItem.endsWith('/')">
<v-container>
<v-list :selected="[selectedItem]">
<v-row no-gutters>
<v-col cols="6" lg="2" md="3" sm="6" v-for="file of filesGridList" style="text-align: center;">
<v-list-item class="ma-2 pa-5 selectable" active-color="light-blue-darken-4" :value="file.path"
rounded @click="() => {
<v-list-item class="ma-2 pa-5 selectable" active-color="light-blue-darken-4" :value="file.path" rounded
@click="() => {
selectedItem = file.path;
}">
<v-avatar class="mb-2" :color="file.isFolder ? 'light-blue-accent-4' : 'blue-grey-darken-1'">
@ -188,26 +208,19 @@ function onSelectEnd(e: any) {
</v-card-text>
<!-- file input -->
<v-file-input class="mx-5" v-model="files" accept=".zip,.7z,.rar,.tar.bz2,.tar.gz,.tar.xz" label="or select a file..." variant="outlined"></v-file-input>
<v-file-input class="mx-5" v-model="files" accept=".zip,.7z,.rar,.tar.bz2,.tar.gz,.tar.xz"
label="or select a file..." variant="outlined"></v-file-input>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
</v-main>
<v-dialog
v-model="loadingModel"
persistent
width="auto"
>
<v-dialog v-model="loadingModel" persistent width="auto">
<v-card>
<v-card-text>
Please stand by
<v-progress-linear
indeterminate
color="light-blue-darken-1"
class="mb-0"
></v-progress-linear>
<v-progress-linear indeterminate color="light-blue-darken-1" class="mb-0"></v-progress-linear>
</v-card-text>
</v-card>
</v-dialog>

View File

@ -0,0 +1,75 @@
// class to manage undo and redo history
export class HistorySwitcher {
// path to the current file
public path: Ref<String>
// history of paths
history: Ref<String[]>
// index of the current path in the history
index: Ref<number>
public readonly hasUndo: ComputedRef<boolean> = computed(() => this.index.value !== 0);
public readonly hasRedo: ComputedRef<boolean> = computed(() => this.index.value !== this.history.value.length - 1);
// constructor
constructor(path: Ref<String>) {
this.path = path
this.history = ref([path.value])
this.index = ref(0);
watchEffect(() => {
this.add(path.value)
})
}
// add a new path to the history
add(path: String) {
// if the path is the same as the previous path, do nothing
if (path === this.history.value[this.index.value]) return
// if the path is the same as the last path in the history, do nothing
if (path === this.history.value[this.history.value.length - 1]) return
// if the index is not at the end of the history, remove all paths after the index
if (this.index.value !== this.history.value.length - 1) {
this.history.value.splice(this.index.value + 1)
}
// add the path to the history
this.history.value.push(path)
// move the index forward one
this.index.value++
}
// undo the last action
undo() {
// if the index is 0, do nothing
if (this.index.value === 0) return
// move the index back one
this.index.value--
// set the path to the path at the index
this.path.value = this.history.value[this.index.value]
}
// can undo the last action
canUndo() {
// return true if the index is not 0
return this.index.value !== 0
}
// redo the last action
redo() {
// if the index is at the end of the history, do nothing
if (this.index.value === this.history.value.length - 1) return
// move the index forward one
this.index.value++
// set the path to the path at the index
this.path.value = this.history.value[this.index.value]
}
canRedo() {
// return true if the index is not at the end of the history
return this.index.value !== this.history.value.length - 1
}
refresh() {
this.path.value = this.history.value[this.index.value]
}
}

6
package-lock.json generated
View File

@ -12,6 +12,7 @@
"moveable": "^0.47.7",
"sass": "^1.62.1",
"selecto": "^1.22.3",
"stateshot": "^1.3.5",
"uuid": "^9.0.0",
"vue3-selecto": "^1.8.4",
"vuetify": "^3.2.4"
@ -7324,6 +7325,11 @@
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==",
"dev": true
},
"node_modules/stateshot": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/stateshot/-/stateshot-1.3.5.tgz",
"integrity": "sha512-A/I230vCzTBDHAc2wzCXrH3ofcNnMd9Cs/HhRrxjWJ1YI90cOklljX9XATTdU45T4W/c/+g+jBtS/oQLs+Wkdw=="
},
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",

View File

@ -22,6 +22,7 @@
"moveable": "^0.47.7",
"sass": "^1.62.1",
"selecto": "^1.22.3",
"stateshot": "^1.3.5",
"uuid": "^9.0.0",
"vue3-selecto": "^1.8.4",
"vuetify": "^3.2.4"