feat(Content): Add menu to set file priority (#1333)

This commit is contained in:
Rémi Marseault 2023-11-20 21:57:48 +01:00 committed by GitHub
parent 02c049692b
commit f83fe0691a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 80 additions and 30 deletions

View file

@ -5,21 +5,26 @@ import { useTreeBuilder } from '@/composables'
import { FilePriority } from '@/constants/qbit'
import { useDialogStore, useMaindataStore, useVueTorrentStore } from '@/stores'
import { TorrentFile } from '@/types/qbit/models'
import { Torrent, TreeNode } from '@/types/vuetorrent'
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
import { Torrent, TreeFile, TreeNode } from '@/types/vuetorrent'
import { useIntervalFn } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
const props = defineProps<{ torrent: Torrent; isActive: boolean }>()
const dialogStore = useDialogStore()
const maindataStore = useMaindataStore()
const vuetorrentStore = useVueTorrentStore()
const { fileContentInterval } = storeToRefs(useVueTorrentStore())
const timer = ref<NodeJS.Timeout | null>(null)
const { pause: pauseTimer, resume: resumeTimer } = useIntervalFn(updateFileTree, fileContentInterval,{
immediate: false,
immediateCallback: true
})
const apiLock = ref(false)
const loading = ref(false)
const cachedFiles = ref<TorrentFile[]>([])
const { tree } = useTreeBuilder(cachedFiles)
const openedItems = ref<string[]>([])
const openedItems = ref(['(root)'])
const renameDialog = ref('')
const renamePayload = reactive({
hash: '',
@ -60,6 +65,11 @@ async function renameNode(node: TreeNode) {
renameDialog.value = dialogStore.createDialog(MoveTorrentFileDialog, renamePayload)
}
async function setFilePriority(node: TreeFile, priority: FilePriority) {
await maindataStore.setTorrentFilePriority(props.torrent.hash, [node.index], priority)
await updateFileTree()
}
async function updateFileTree() {
if (apiLock.value) return
apiLock.value = true
@ -77,13 +87,14 @@ watch(
() => props.isActive,
newValue => {
if (newValue) {
timer.value = setInterval(updateFileTree, vuetorrentStore.fileContentInterval)
updateFileTree().then(() => openedItems.value.push('(root)'))
resumeTimer()
updateFileTree()
} else {
clearInterval(timer.value as NodeJS.Timeout)
pauseTimer()
}
}
)
watch(
() => dialogStore.isDialogOpened(renameDialog.value),
v => {
@ -93,19 +104,15 @@ watch(
}
)
onBeforeUnmount(() => {
clearInterval(timer.value as NodeJS.Timeout)
})
onMounted(() => {
timer.value = setInterval(updateFileTree, vuetorrentStore.fileContentInterval)
updateFileTree().then(() => openedItems.value.push('(root)'))
resumeTimer()
})
</script>
<template>
<v-card :loading="loading" flat>
<RootNode v-model:opened="openedItems" v-model:selected="fileSelection" :root="tree" @renameFolder="renameNode"
@renameFile="renameNode" />
<RootNode v-model:opened="openedItems" v-model:selected="fileSelection" :root="tree"
@renameFolder="renameNode" @renameFile="renameNode" @setFilePriority="setFilePriority" />
<!--
TODO: add treeview after merge
https://github.com/vuetifyjs/vuetify/issues/13518

View file

@ -10,7 +10,8 @@ defineProps<{
node: TreeFile
}>()
defineEmits<{
renameFile: [node: TreeFile]
renameFile: [node: TreeFile],
setFilePriority: [node: TreeFile, priority: FilePriority]
}>()
const { t } = useI18n()
@ -34,8 +35,19 @@ function getNodePriority(node: TreeFile) {
<span class="mr-2">[ {{ formatData(node.size, vuetorrentStore.useBinarySize) }} ]</span>
<span class="mr-2">{{ formatPercent(node.progress) }}</span>
<span class="mr-4">[ {{ getNodePriority(node) }} ]</span>
<v-btn class="mr-2" color="accent" size="x-small" icon="mdi-trending-up" />
<!-- TODO: prio menu -->
<v-menu open-on-hover open-on-click open-delay="0" close-delay="0">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" class="mr-2" color="accent" size="x-small" icon="mdi-trending-up" />
</template>
<v-list>
<v-list-item v-for="prio in filePriorityOptions" @click="$emit('setFilePriority', node, prio.value)">
<v-list-item-title>
<v-icon>{{ prio.icon }}</v-icon>
<span class="ml-2">{{ prio.name }}</span>
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
<v-btn color="accent" size="x-small" icon="mdi-pencil" @click.stop="$emit('renameFile', node)" />
</template>
</v-list-item>

View file

@ -1,14 +1,16 @@
<script setup lang="ts">
import { FilePriority } from '@/constants/qbit'
import { TreeFile, TreeFolder, TreeRoot } from '@/types/vuetorrent'
import { useI18n } from 'vue-i18n'
import FileNode from './FileNode.vue'
import { TreeFile, TreeFolder, TreeRoot } from '@/types/vuetorrent'
defineProps<{
node: TreeRoot | TreeFolder
}>()
defineEmits<{
renameFolder: [node: TreeFolder]
renameFile: [node: TreeFile]
renameFile: [node: TreeFile],
setFilePriority: [node: TreeFile, priority: FilePriority]
}>()
const { t } = useI18n()
@ -46,15 +48,21 @@ function getNodeDescription(node: TreeRoot | TreeFolder) {
:value="node.type === 'root' ? '(root)' : node.fullName">
<template v-slot:append="{ isActive }">
<span class="mr-2">{{ getNodeDescription(node) }}</span>
<v-btn v-if="node.type === 'folder'" color="accent" size="x-small" icon="mdi-pencil" @click.stop="$emit('renameFolder', node)" />
<v-btn v-if="node.type === 'folder'" color="accent" size="x-small" icon="mdi-pencil"
@click.stop="$emit('renameFolder', node)" />
<v-icon :icon="isActive ? 'mdi-chevron-up' : 'mdi-chevron-down'" />
</template>
</v-list-item>
</template>
<template v-for="child in node.children">
<FolderNode v-if="child.type === 'folder'" :node="child as TreeFolder" @renameFolder="n => $emit('renameFolder', n)" @renameFile="n => $emit('renameFile', n)" />
<FileNode v-if="child.type === 'file'" :node="child as TreeFile" @renameFile="n => $emit('renameFile', n)" />
<FolderNode v-if="child.type === 'folder'" :node="child as TreeFolder"
@renameFolder="n => $emit('renameFolder', n)"
@renameFile="n => $emit('renameFile', n)"
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
<FileNode v-if="child.type === 'file'" :node="child as TreeFile"
@renameFile="n => $emit('renameFile', n)"
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
</template>
</v-list-group>
</template>

View file

@ -1,4 +1,5 @@
<script setup lang="ts">
import { FilePriority } from '@/constants/qbit'
import FolderNode from './FolderNode.vue'
import { TreeFile, TreeFolder, TreeRoot } from '@/types/vuetorrent'
@ -7,13 +8,17 @@ defineProps<{
}>()
defineEmits<{
renameFolder: [node: TreeFolder]
renameFile: [node: TreeFile]
renameFile: [node: TreeFile],
setFilePriority: [node: TreeFile, priority: FilePriority]
}>()
</script>
<template>
<v-list density="compact" select-strategy="classic">
<FolderNode :node="root" @renameFolder="n => $emit('renameFolder', n)" @renameFile="n => $emit('renameFile', n)" />
<FolderNode :node="root"
@renameFolder="n => $emit('renameFolder', n)"
@renameFile="n => $emit('renameFile', n)"
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
</v-list>
</template>

View file

@ -15,6 +15,7 @@ import {
import { useDialogStore, useMaindataStore, useTorrentStore, useVueTorrentStore } from '@/stores'
import { TorrentFile } from '@/types/qbit/models'
import { Torrent } from '@/types/vuetorrent'
import { useIntervalFn } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useTheme } from 'vuetify'
@ -137,14 +138,31 @@ function openMoveTorrentFileDialog() {
})
}
const { resume: resumeTimer, pause: pauseTimer } = useIntervalFn(async () => {
await updateTorrentFiles()
if (shouldRefreshPieceState.value) {
await renderTorrentPieceStates()
}
}, vuetorrentStore.fileContentInterval, {
immediate: true,
immediateCallback: true
})
watch(
() => props.isActive,
newValue => {
if (newValue) {
resumeTimer()
} else {
pauseTimer()
}
}
)
watch(
() => props.torrent,
async () => {
await getTorrentProperties()
await updateTorrentFiles()
if (shouldRefreshPieceState.value) {
await renderTorrentPieceStates()
}
}
)
</script>

View file

@ -64,7 +64,7 @@ const handleKeyboardShortcut = (e: KeyboardEvent) => {
onBeforeMount(() => {
document.addEventListener('keydown', handleKeyboardShortcut)
useIntervalFn(() => logStore.fetchLogs(), 15000)
useIntervalFn(logStore.fetchLogs, 15000)
logStore.fetchLogs(-1)
})
onUnmounted(() => {