mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2025-02-26 04:10:52 +03:00
feat(Content): Add menu to set file priority (#1333)
This commit is contained in:
parent
02c049692b
commit
f83fe0691a
6 changed files with 80 additions and 30 deletions
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
Loading…
Add table
Reference in a new issue