perf(Info): add torrent properties (#1528)

This commit is contained in:
Rémi Marseault 2024-02-20 19:56:06 +01:00 committed by GitHub
parent 8a9bf16710
commit 196f5e33f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 427 additions and 304 deletions

View file

@ -1,233 +0,0 @@
<script setup lang="ts">
import InfoBase from '@/components/TorrentDetail/InfoBase.vue'
import { formatData, formatSpeed } from '@/helpers'
import dayjs from '@/plugins/dayjs'
import { useMaindataStore, useTorrentStore, useVueTorrentStore } from '@/stores'
import { Torrent } from '@/types/vuetorrent'
import { computed } from 'vue'
const props = defineProps<{ torrent: Torrent; isActive: boolean }>()
const maindataStore = useMaindataStore()
const torrentStore = useTorrentStore()
const vuetorrentStore = useVueTorrentStore()
const auto_tmm = computed({
get: () => props.torrent.auto_tmm,
set: value => maindataStore.toggleAutoTmm([props.torrent.hash], value)
})
const f_l_piece_prio = computed({
get: () => props.torrent.f_l_piece_prio,
set: () => maindataStore.toggleFLPiecePrio([props.torrent.hash])
})
const forced = computed({
get: () => props.torrent.forced,
set: value => {
if (value) {
torrentStore.forceResumeTorrents([props.torrent.hash])
} else {
torrentStore.resumeTorrents([props.torrent.hash])
}
}
})
const seq_dl = computed({
get: () => props.torrent.seq_dl,
set: () => maindataStore.toggleSeqDl([props.torrent.hash])
})
const super_seeding = computed({
get: () => props.torrent.super_seeding,
set: value => maindataStore.setSuperSeeding([props.torrent.hash], value)
})
const datetimePpts = [
{ title: 'added_on', text: 'added_on' },
{ title: 'completed_on', text: 'completed_on' },
{ title: 'last_activity', text: 'last_activity' },
{ title: 'seen_complete', text: 'seen_complete' }
]
const durationPpts = [
{ title: 'ratio_time_limit', text: 'ratio_time_limit' },
{ title: 'seeding_time', text: 'seeding_time' },
{ title: 'time_active', text: 'time_active' }
]
const dataPpts = [
{ title: 'downloaded', text: 'downloaded' },
{ title: 'downloaded_session', text: 'downloaded_session' },
{ title: 'uploaded', text: 'uploaded' },
{ title: 'uploaded_session', text: 'uploaded_session' },
{ title: 'size', text: 'size' },
{ title: 'total_size', text: 'total_size' },
{ title: 'amount_left', text: 'amount_left' },
{ title: 'global_volume', text: 'globalVolume' }
]
const speedPpts = [
{ title: 'download_limit', text: 'dl_limit' },
{ title: 'download_speed', text: 'dlspeed' },
{ title: 'upload_limit', text: 'up_limit' },
{ title: 'upload_speed', text: 'upspeed' },
{ title: 'avg_download_speed', text: 'avgDownloadSpeed' },
{ title: 'avg_upload_speed', text: 'avgUploadSpeed' },
{ title: 'global_speed', text: 'globalSpeed' }
]
const textPpts = [
{ title: 'available_peers', text: 'available_peers' },
{ title: 'available_seeds', text: 'available_seeds' },
{ title: 'num_leechs', text: 'num_leechs' },
{ title: 'num_seeds', text: 'num_seeds' },
{ title: 'ratio', text: 'ratio' },
{ title: 'ratio_limit', text: 'ratio_limit' },
{ title: 'availability', text: 'availability' },
{ title: 'eta', text: 'eta' },
{ title: 'category', text: 'category' },
{ title: 'state', text: 'stateString' },
{ title: 'trackers_count', text: 'trackers_count' },
{ title: 'priority', text: 'priority' }
]
const longTextPpts = [
{ title: 'content_path', text: 'content_path' },
{ title: 'download_path', text: 'download_path' },
{ title: 'hash', text: 'hash' },
{ title: 'infohash_v1', text: 'infohash_v1' },
{ title: 'infohash_v2', text: 'infohash_v2' },
{ title: 'magnet', text: 'magnet' },
{ title: 'name', text: 'name' },
{ title: 'save_path', text: 'savePath' },
{ title: 'tracker', text: 'tracker' }
]
</script>
<template>
<v-list>
<v-list-item>
<v-expansion-panels>
<v-expansion-panel :title="$t('torrentDetail.info.datetime_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in datetimePpts">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-if="torrent[ppt.text] > 0" v-slot:text>
{{ dayjs(torrent[ppt.text] * 1000).format(vuetorrentStore.dateFormat ?? 'DD/MM/YYYY, HH:mm:ss') }}
</template>
<template v-else v-slot:text> {{ $t('common.NA') }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel :title="$t('torrentDetail.info.duration_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in durationPpts">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-slot:text>{{ dayjs.duration(torrent[ppt.text], 's').humanize() }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel :title="$t('torrentDetail.info.boolean_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="auto_tmm" hide-details density="compact" :label="$t('torrent.properties.auto_tmm')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="f_l_piece_prio" hide-details density="compact" :label="$t('torrent.properties.f_l_piece_prio')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="forced" hide-details density="compact" :label="$t('torrent.properties.forced')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="seq_dl" hide-details density="compact" :label="$t('torrent.properties.seq_dl')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="super_seeding" hide-details density="compact" :label="$t('torrent.properties.super_seeding')" />
</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel :title="$t('torrentDetail.info.data_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in dataPpts">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-slot:text>{{ formatData(torrent[ppt.text], vuetorrentStore.useBinarySize) }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel :title="$t('torrentDetail.info.speed_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in speedPpts">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-slot:text>{{ formatSpeed(torrent[ppt.text], vuetorrentStore.useBitSpeed) }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel :title="$t('torrentDetail.info.text_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in textPpts">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-slot:text>{{ torrent[ppt.text] }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel :title="$t('torrentDetail.info.long_text_values')">
<v-expansion-panel-text>
<v-list>
<v-list-item v-for="ppt in longTextPpts" :title="$t(`torrent.properties.${ppt.title}`)">
<v-list-item-subtitle>{{ torrent[ppt.text] }}</v-list-item-subtitle>
</v-list-item>
<v-list-item :title="$t('torrent.properties.tags')">
<div v-if="torrent.tags?.length" class="d-flex gap">
<v-chip v-for="tag in torrent.tags" variant="flat" color="tag">
{{ tag }}
</v-chip>
</div>
<v-list-item-subtitle v-else>{{ $t('torrent.properties.empty_tags') }}</v-list-item-subtitle>
</v-list-item>
</v-list>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
</v-list-item>
</v-list>
</template>
<style scoped>
.gap {
gap: 8px;
}
</style>

View file

@ -0,0 +1,28 @@
<script setup lang="ts">
import { Torrent } from '@/types/vuetorrent'
import PanelBoolean from './PanelBoolean.vue'
import PanelData from './PanelData.vue'
import PanelDatetime from './PanelDatetime.vue'
import PanelDuration from './PanelDuration.vue'
import PanelLongText from './PanelLongText.vue'
import PanelSpeed from './PanelSpeed.vue'
import PanelText from './PanelText.vue'
defineProps<{ torrent: Torrent; isActive: boolean }>()
</script>
<template>
<v-list>
<v-list-item>
<v-expansion-panels>
<PanelDatetime :torrent="torrent" />
<PanelDuration :torrent="torrent" />
<PanelBoolean :torrent="torrent" />
<PanelData :torrent="torrent" />
<PanelSpeed :torrent="torrent" />
<PanelText :torrent="torrent" />
<PanelLongText :torrent="torrent" />
</v-expansion-panels>
</v-list-item>
</v-list>
</template>

View file

@ -1,7 +1,3 @@
<script setup lang="ts">
defineProps<{ compact?: boolean }>()
</script>
<template>
<v-col cols="12" sm="6" lg="3">
<v-sheet rounded="xl" class="d-flex align-center py-2 border">
@ -15,5 +11,3 @@ defineProps<{ compact?: boolean }>()
</v-sheet>
</v-col>
</template>
<style scoped></style>

View file

@ -0,0 +1,88 @@
<script setup lang="ts">
import { useMaindataStore, useTorrentDetailStore, useTorrentStore } from '@/stores'
import { Torrent } from '@/types/vuetorrent'
import { storeToRefs } from 'pinia'
import { computed } from 'vue'
import InfoBase from './InfoBase.vue'
const props = defineProps<{ torrent: Torrent }>()
const maindataStore = useMaindataStore()
const torrentStore = useTorrentStore()
const { properties } = storeToRefs(useTorrentDetailStore())
const auto_tmm = computed({
get: () => props.torrent.auto_tmm,
set: value => maindataStore.toggleAutoTmm([props.torrent.hash], value)
})
const f_l_piece_prio = computed({
get: () => props.torrent.f_l_piece_prio,
set: () => maindataStore.toggleFLPiecePrio([props.torrent.hash])
})
const forced = computed({
get: () => props.torrent.forced,
set: value => {
if (value) {
torrentStore.forceResumeTorrents([props.torrent.hash])
} else {
torrentStore.resumeTorrents([props.torrent.hash])
}
}
})
const seq_dl = computed({
get: () => props.torrent.seq_dl,
set: () => maindataStore.toggleSeqDl([props.torrent.hash])
})
const super_seeding = computed({
get: () => props.torrent.super_seeding,
set: value => maindataStore.setSuperSeeding([props.torrent.hash], value)
})
</script>
<template>
<v-expansion-panel :title="$t('torrentDetail.info.boolean_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="auto_tmm" hide-details density="compact" :label="$t('torrent.properties.auto_tmm')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="f_l_piece_prio" hide-details density="compact" :label="$t('torrent.properties.f_l_piece_prio')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="forced" hide-details density="compact" :label="$t('torrent.properties.forced')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="seq_dl" hide-details density="compact" :label="$t('torrent.properties.seq_dl')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox v-model="super_seeding" hide-details density="compact" :label="$t('torrent.properties.super_seeding')" />
</template>
</InfoBase>
<InfoBase>
<template v-slot:title>
<v-checkbox disabled :model-value="properties?.is_private" hide-details density="compact" :label="$t('torrent.properties.is_private')" />
</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
</template>

View file

@ -0,0 +1,37 @@
<script setup lang="ts">
import { formatData } from '@/helpers'
import { useTorrentDetailStore, useVueTorrentStore } from '@/stores'
import { Torrent } from '@/types/vuetorrent'
import { storeToRefs } from 'pinia'
import InfoBase from './InfoBase.vue'
const props = defineProps<{ torrent: Torrent }>()
const { properties } = storeToRefs(useTorrentDetailStore())
const { useBinarySize } = storeToRefs(useVueTorrentStore())
const torrentValues = [
{ title: 'downloaded', getter: () => props.torrent.downloaded },
{ title: 'downloaded_session', getter: () => props.torrent.downloaded_session },
{ title: 'uploaded', getter: () => props.torrent.uploaded },
{ title: 'uploaded_session', getter: () => props.torrent.uploaded_session },
{ title: 'size', getter: () => props.torrent.size },
{ title: 'total_size', getter: () => props.torrent.total_size },
{ title: 'total_wasted', getter: () => properties.value?.total_wasted ?? 0 },
{ title: 'amount_left', getter: () => props.torrent.amount_left },
{ title: 'global_volume', getter: () => props.torrent.globalVolume }
]
</script>
<template>
<v-expansion-panel :title="$t('torrentDetail.info.data_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in torrentValues">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-slot:text>{{ formatData(ppt.getter(), useBinarySize) }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
</template>

View file

@ -0,0 +1,36 @@
<script setup lang="ts">
import InfoBase from './InfoBase.vue'
import dayjs from '@/plugins/dayjs'
import { useTorrentDetailStore, useVueTorrentStore } from '@/stores'
import { Torrent } from '@/types/vuetorrent'
import { storeToRefs } from 'pinia'
const props = defineProps<{ torrent: Torrent }>()
const { properties } = storeToRefs(useTorrentDetailStore())
const { dateFormat } = storeToRefs(useVueTorrentStore())
const torrentValues = [
{ title: 'added_on', getter: () => props.torrent.added_on },
{ title: 'completed_on', getter: () => props.torrent.completed_on },
{ title: 'creation_date', getter: () => properties.value?.creation_date ?? 0 },
{ title: 'last_activity', getter: () => props.torrent.last_activity },
{ title: 'seen_complete', getter: () => props.torrent.seen_complete }
]
</script>
<template>
<v-expansion-panel :title="$t('torrentDetail.info.datetime_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in torrentValues">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-if="ppt.getter() > 0" v-slot:text>
{{ dayjs(ppt.getter() * 1000).format(dateFormat ?? 'DD/MM/YYYY, HH:mm:ss') }}
</template>
<template v-else v-slot:text> {{ $t('common.NA') }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
</template>

View file

@ -0,0 +1,31 @@
<script setup lang="ts">
import { useTorrentDetailStore } from '@/stores'
import { storeToRefs } from 'pinia'
import InfoBase from './InfoBase.vue'
import dayjs from '@/plugins/dayjs'
import { Torrent } from '@/types/vuetorrent'
const props = defineProps<{ torrent: Torrent }>()
const { properties } = storeToRefs(useTorrentDetailStore())
const torrentValues = [
{ title: 'ratio_time_limit', getter: () => props.torrent.ratio_time_limit },
{ title: 'seeding_time', getter: () => props.torrent.seeding_time },
{ title: 'time_active', getter: () => props.torrent.time_active },
{ title: 'reannounce', getter: () => properties.value?.reannounce ?? 0 }
]
</script>
<template>
<v-expansion-panel :title="$t('torrentDetail.info.duration_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in torrentValues">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-slot:text>{{ dayjs.duration(ppt.getter(), 's').humanize() }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
</template>

View file

@ -0,0 +1,50 @@
<script setup lang="ts">
import { useTorrentDetailStore } from '@/stores'
import { Torrent } from '@/types/vuetorrent'
import { storeToRefs } from 'pinia'
const props = defineProps<{ torrent: Torrent }>()
const { properties } = storeToRefs(useTorrentDetailStore())
const values = [
{ title: 'content_path', getter: () => props.torrent.content_path },
{ title: 'download_path', getter: () => props.torrent.download_path },
{ title: 'hash', getter: () => props.torrent.hash },
{ title: 'infohash_v1', getter: () => props.torrent.infohash_v1 },
{ title: 'infohash_v2', getter: () => props.torrent.infohash_v2 },
{ title: 'magnet', getter: () => props.torrent.magnet },
{ title: 'name', getter: () => props.torrent.name },
{ title: 'save_path', getter: () => props.torrent.savePath },
{ title: 'tracker', getter: () => props.torrent.tracker },
{ title: 'comment', getter: () => properties.value?.comment ?? '' },
{ title: 'created_by', getter: () => properties.value?.created_by ?? '' }
]
</script>
<template>
<v-expansion-panel :title="$t('torrentDetail.info.long_text_values')">
<v-expansion-panel-text>
<v-list>
<v-list-item v-for="ppt in values" :title="$t(`torrent.properties.${ppt.title}`)">
<v-list-item-subtitle>{{ ppt.getter() }}</v-list-item-subtitle>
</v-list-item>
<v-list-item :title="$t('torrent.properties.tags')">
<div v-if="torrent.tags?.length" class="d-flex gap">
<v-chip v-for="tag in torrent.tags" variant="flat" color="tag">
{{ tag }}
</v-chip>
</div>
<v-list-item-subtitle v-else>{{ $t('torrent.properties.empty_tags') }}</v-list-item-subtitle>
</v-list-item>
</v-list>
</v-expansion-panel-text>
</v-expansion-panel>
</template>
<style scoped>
.gap {
gap: 8px;
}
</style>

View file

@ -0,0 +1,35 @@
<script setup lang="ts">
import { useTorrentDetailStore, useVueTorrentStore } from '@/stores'
import { storeToRefs } from 'pinia'
import InfoBase from './InfoBase.vue'
import { formatSpeed } from '@/helpers'
import { Torrent } from '@/types/vuetorrent'
const props = defineProps<{ torrent: Torrent }>()
const { properties } = storeToRefs(useTorrentDetailStore())
const { useBitSpeed } = storeToRefs(useVueTorrentStore())
const torrentValues = [
{ title: 'download_limit', getter: () => props.torrent.dl_limit },
{ title: 'download_speed', getter: () => props.torrent.dlspeed },
{ title: 'avg_download_speed', getter: () => properties.value?.dl_speed_avg ?? 0 },
{ title: 'upload_limit', getter: () => props.torrent.up_limit },
{ title: 'upload_speed', getter: () => props.torrent.upspeed },
{ title: 'avg_upload_speed', getter: () => properties.value?.up_speed_avg ?? 0 },
{ title: 'global_speed', getter: () => props.torrent.globalSpeed }
]
</script>
<template>
<v-expansion-panel :title="$t('torrentDetail.info.speed_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in torrentValues">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-slot:text>{{ formatSpeed(ppt.getter(), useBitSpeed) }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
</template>

View file

@ -0,0 +1,40 @@
<script setup lang="ts">
import { useTorrentDetailStore } from '@/stores'
import { Torrent } from '@/types/vuetorrent'
import { storeToRefs } from 'pinia'
import InfoBase from './InfoBase.vue'
const props = defineProps<{ torrent: Torrent }>()
const { properties } = storeToRefs(useTorrentDetailStore())
const torrentValues = [
{ title: 'available_peers', getter: () => props.torrent.available_peers },
{ title: 'available_seeds', getter: () => props.torrent.available_seeds },
{ title: 'ratio', getter: () => props.torrent.ratio },
{ title: 'ratio_limit', getter: () => props.torrent.ratio_limit },
{ title: 'num_leechs', getter: () => props.torrent.num_leechs },
{ title: 'num_seeds', getter: () => props.torrent.num_seeds },
{ title: 'availability', getter: () => props.torrent.availability },
{ title: 'eta', getter: () => props.torrent.eta },
{ title: 'category', getter: () => props.torrent.category },
{ title: 'state', getter: () => props.torrent.stateString },
{ title: 'trackers_count', getter: () => props.torrent.trackers_count },
{ title: 'priority', getter: () => props.torrent.priority },
{ title: 'nb_connections', getter: () => properties.value?.nb_connections ?? 0 },
{ title: 'nb_connections_limit', getter: () => properties.value?.nb_connections_limit ?? 0 }
]
</script>
<template>
<v-expansion-panel :title="$t('torrentDetail.info.text_values')">
<v-expansion-panel-text>
<v-row>
<InfoBase v-for="ppt in torrentValues">
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
<template v-slot:text>{{ ppt.getter() }}</template>
</InfoBase>
</v-row>
</v-expansion-panel-text>
</v-expansion-panel>
</template>

View file

@ -3,10 +3,11 @@ import MoveTorrentDialog from '@/components/Dialogs/MoveTorrentDialog.vue'
import MoveTorrentFileDialog from '@/components/Dialogs/MoveTorrentFileDialog.vue'
import { FilePriority, PieceState, TorrentState } from '@/constants/qbit'
import { formatData, formatDataUnit, formatDataValue, formatPercent, formatSpeed, getDomainBody, splitByUrl, stringContainsUrl } from '@/helpers'
import { useDialogStore, useMaindataStore, useTorrentStore, useVueTorrentStore } from '@/stores'
import { useDialogStore, useMaindataStore, useTorrentDetailStore, useVueTorrentStore } from '@/stores'
import { TorrentFile } from '@/types/qbit/models'
import { Torrent } from '@/types/vuetorrent'
import { useIntervalFn } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { toast } from 'vue3-toastify'
@ -18,21 +19,22 @@ const { t } = useI18n()
const theme = useTheme()
const dialogStore = useDialogStore()
const maindataStore = useMaindataStore()
const torrentStore = useTorrentStore()
const { properties } = storeToRefs(useTorrentDetailStore())
const vuetorrentStore = useVueTorrentStore()
const canvas = ref<HTMLCanvasElement>()
const comment = ref('')
const downloadSpeedAvg = ref(0)
const files = ref<TorrentFile[]>([])
const selectedFileCount = ref(0)
const torrentFileCount = ref(0)
const torrentFileName = ref('')
const torrentPieceSize = ref(0)
const torrentPieceOwned = ref(0)
const torrentPieceCount = ref(0)
const uploadSpeedAvg = ref(0)
const comment = computed(() => properties.value?.comment ?? '')
const downloadSpeedAvg = computed(() => properties.value?.dl_speed_avg ?? 0)
const torrentPieceSize = computed(() => properties.value?.piece_size ?? 0)
const torrentPieceOwned = computed(() => properties.value?.pieces_have ?? 0)
const torrentPieceCount = computed(() => properties.value?.pieces_num ?? 0)
const uploadSpeedAvg = computed(() => properties.value?.up_speed_avg ?? 0)
const torrentStateColor = computed(() => `torrent-${props.torrent.state}`)
const pieceSize = computed(() => `${parseInt(formatDataValue(torrentPieceSize.value, true))} ${formatDataUnit(torrentPieceSize.value, true)}`)
@ -40,16 +42,6 @@ const isFetchingMetadata = computed(() => props.torrent.state === TorrentState.M
const shouldRenderPieceState = computed(() => !isFetchingMetadata.value && torrentPieceCount.value > 0 && torrentPieceCount.value < vuetorrentStore.canvasRenderThreshold)
const shouldRefreshPieceState = computed(() => shouldRenderPieceState.value && torrentPieceCount.value < vuetorrentStore.canvasRefreshThreshold)
async function getTorrentProperties() {
const ppts = await torrentStore.getTorrentProperties(props.torrent.hash)
comment.value = ppts.comment
downloadSpeedAvg.value = ppts.dl_speed_avg
torrentPieceCount.value = ppts.pieces_num
torrentPieceOwned.value = ppts.pieces_have
torrentPieceSize.value = ppts.piece_size
uploadSpeedAvg.value = ppts.up_speed_avg
}
async function updateTorrentFiles() {
files.value = await maindataStore.fetchFiles(props.torrent.hash)
torrentFileCount.value = files.value.length
@ -162,13 +154,6 @@ watch(
}
)
watch(
() => props.torrent,
async () => {
await getTorrentProperties()
}
)
function handleKeyboardShortcuts(e: KeyboardEvent) {
if (dialogStore.hasActiveDialog) return false

View file

@ -1175,13 +1175,16 @@
"avg_download_speed": "Average Download Speed",
"avg_upload_speed": "Average Upload Speed",
"category": "Category",
"comment": "Comment",
"completed_on": "Completed On",
"content_path": "Content Path",
"downloaded": "Downloaded (global)",
"downloaded_session": "Downloaded (session)",
"created_by": "Created by",
"creation_date": "Creation Date",
"download_limit": "Download Limit",
"download_path": "Download Path",
"download_speed": "Download Speed",
"downloaded": "Downloaded (global)",
"downloaded_session": "Downloaded (session)",
"empty_category": "(no category)",
"empty_tags": "(no tags)",
"empty_tracker_domain": "(no tracker)",
@ -1193,9 +1196,12 @@
"hash": "Hash",
"infohash_v1": "Infohash v1",
"infohash_v2": "Infohash v2",
"is_private": "Private torrent",
"last_activity": "Last Activity",
"magnet": "Magnet Link",
"name": "Torrent Title",
"nb_connections": "Total connections",
"nb_connections_limit": "Connection limit",
"num_leechs": "Peers (connected)",
"num_seeds": "Seeds (connected)",
"peers": "Peers",
@ -1205,6 +1211,7 @@
"ratio": "Ratio",
"ratio_limit": "Ratio limit",
"ratio_time_limit": "Ratio time limit",
"reannounce": "Next reannounce in",
"save_path": "Save Path",
"seeding_time": "Seeding time",
"seeds": "Seeds",
@ -1216,12 +1223,13 @@
"tags": "Tags",
"time_active": "Time Active",
"total_size": "Total Size",
"total_wasted": "Wasted data",
"tracker": "Tracker",
"trackers_count": "Trackers Count",
"uploaded": "Uploaded (global)",
"uploaded_session": "Uploaded (session)",
"upload_limit": "Upload Limit",
"upload_speed": "Upload Speed"
"upload_speed": "Upload Speed",
"uploaded": "Uploaded (global)",
"uploaded_session": "Uploaded (session)"
},
"state": {
"allocating": "Allocating",

View file

@ -2,13 +2,13 @@
import RightClickMenu from '@/components/Core/RightClickMenu'
import ConfirmDeleteDialog from '@/components/Dialogs/ConfirmDeleteDialog.vue'
import Content from '@/components/TorrentDetail/Content'
import Info from '@/components/TorrentDetail/Info.vue'
import Info from '@/components/TorrentDetail/Info/Info.vue'
import Overview from '@/components/TorrentDetail/Overview.vue'
import Peers from '@/components/TorrentDetail/Peers.vue'
import TagsAndCategories from '@/components/TorrentDetail/TagsAndCategories.vue'
import Trackers from '@/components/TorrentDetail/Trackers.vue'
import { useContentStore, useDialogStore, useTorrentStore } from '@/stores'
import { computed, onBeforeUnmount, onMounted, ref, watchEffect } from 'vue'
import { useContentStore, useDialogStore, useTorrentDetailStore, useTorrentStore } from '@/stores'
import { computed, onBeforeUnmount, onMounted, ref, watch, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
@ -17,6 +17,7 @@ const { t } = useI18n()
const contentStore = useContentStore()
const dialogStore = useDialogStore()
const torrentStore = useTorrentStore()
const torrentDetailStore = useTorrentDetailStore()
const tabs = [
{ text: t('torrentDetail.tabs.overview'), value: 'overview' },
@ -63,12 +64,18 @@ watchEffect(() => {
updateTabHandle()
})
watch(torrent, () => {
torrentDetailStore.fetchProperties(hash.value)
})
onMounted(() => {
document.addEventListener('keydown', handleKeyboardShortcut)
updateTabHandle()
torrentDetailStore.fetchProperties(hash.value)
})
onBeforeUnmount(() => {
document.removeEventListener('keydown', handleKeyboardShortcut)
torrentDetailStore.$reset()
})
</script>

View file

@ -12,7 +12,7 @@ import { computed, nextTick, reactive, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute } from 'vue-router'
export const useContentStore = defineStore('torrentDetail', () => {
export const useContentStore = defineStore('content', () => {
const { t } = useI18n()
const route = useRoute()
const dialogStore = useDialogStore()

View file

@ -11,6 +11,7 @@ import { useNavbarStore } from './navbar'
import { usePreferenceStore } from './preferences'
import { useRssStore } from './rss'
import { useSearchEngineStore } from './searchEngine'
import { useTorrentDetailStore } from './torrentDetail'
import { useTorrentStore } from './torrents'
import { useVueTorrentStore } from './vuetorrent'
@ -28,6 +29,7 @@ export {
usePreferenceStore,
useRssStore,
useSearchEngineStore,
useTorrentDetailStore,
useTorrentStore,
useVueTorrentStore
}

View file

@ -0,0 +1,20 @@
import { qbit } from '@/services'
import { TorrentProperties } from '@/types/qbit/models'
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useTorrentDetailStore = defineStore('torrentDetail', () => {
const properties = ref<TorrentProperties>()
async function fetchProperties(hash: string) {
properties.value = await qbit.getTorrentProperties(hash)
}
return {
properties,
fetchProperties,
$reset: () => {
properties.value = undefined
}
}
})

View file

@ -110,10 +110,6 @@ export const useTorrentStore = defineStore(
return await qbit.addTorrents(torrents, urls, payload)
}
async function getTorrentProperties(hash: string) {
return await qbit.getTorrentProperties(hash)
}
async function renameTorrent(hash: string, newName: string) {
await qbit.setTorrentName(hash, newName)
}
@ -167,7 +163,6 @@ export const useTorrentStore = defineStore(
deleteTorrents,
moveTorrents,
addTorrents,
getTorrentProperties,
renameTorrent,
resumeTorrents,
forceResumeTorrents,

View file

@ -1,43 +1,43 @@
export default interface TorrentProperties {
/** When this torrent was added (unix timestamp) */
/** When this torrent was added (unix timestamp), similar to `added_on` */
addition_date: number
/** Torrent comment */
comment: string
/** Torrent completion date (unix timestamp) */
/** Torrent completion date (unix timestamp), similar to `completed_on` */
completion_date: number
/** Torrent creator */
created_by: string
/** Torrent creation date (Unix timestamp) */
creation_date: number
/** Torrent download limit (bytes/s) */
/** Torrent download limit (bytes/s), similar to `dl_limit` */
dl_limit: number
/** Torrent download speed (bytes/second) */
/** Torrent download speed (bytes/second), similar to `dlspeed` */
dl_speed: number
/** Torrent average download speed (bytes/second) */
dl_speed_avg: number
/** Torrent download path */
/** Torrent download path, similar to `download_path` */
download_path: string
/** Torrent ETA (seconds) */
/** Torrent ETA (seconds), similar to `eta` */
eta: number
/** Torrent hash */
/** Torrent hash, similar to `hash` */
hash: string
/** Torrent Infohash V1 */
/** Torrent Infohash V1, similar to `infohash_v1` */
infohash_v1: string
/** Torrent Infohash V2 */
/** Torrent Infohash V2, similar to `infohash_v2` */
infohash_v2: string
/** Whether torrent is private or not */
is_private: boolean
/** Last seen complete date (unix timestamp) */
/** Last seen complete date (unix timestamp), similar to `seen_complete` */
last_seen: number
/** Torrent name */
/** Torrent name, similar to `name` */
name: string
/** Torrent connection count */
nb_connections: number
/** Torrent connection count limit */
nb_connections_limit: number
/** Number of peers connected to */
/** Number of peers connected to, similar to `num_leechs` */
peers: number
/** Number of peers in the swarm */
/** Number of peers in the swarm, similar to `available_peers` */
peers_total: number
/** Torrent piece size (bytes) */
piece_size: number
@ -47,33 +47,33 @@ export default interface TorrentProperties {
pieces_num: number
/** Number of seconds until the next announce */
reannounce: number
/** Torrent save path */
/** Torrent save path, similar to `save_path` */
save_path: string
/** Torrent elapsed time while complete (seconds) */
/** Torrent elapsed time while complete (seconds), similar to `seeding_time` */
seeding_time: number
/** Number of seeds connected to */
/** Number of seeds connected to, similar to `num_seeds` */
seeds: number
/** Number of seeds in the swarm */
/** Number of seeds in the swarm, similar to `available_seeds` */
seeds_total: number
/** Torrent share ratio */
/** Torrent share ratio, similar to `ratio` */
share_ratio: number
/** Torrent elapsed time (seconds) */
/** Torrent elapsed time (seconds), similar to `time_active` */
time_elapsed: number
/** Total data downloaded for torrent (bytes) */
/** Total data downloaded for torrent (bytes), similar to `downloaded` */
total_downloaded: number
/** Total data downloaded this session (bytes) */
/** Total data downloaded this session (bytes), similar to `downloaded_session` */
total_downloaded_session: number
/** Torrent total size (bytes) */
/** Torrent total size (bytes), similar to `total_size` */
total_size: number
/** Total data uploaded for torrent (bytes) */
/** Total data uploaded for torrent (bytes), similar to `uploaded` */
total_uploaded: number
/** Total data uploaded this session (bytes) */
/** Total data uploaded this session (bytes), similar to `uploaded_session` */
total_uploaded_session: number
/** Total data wasted for torrent (bytes) */
total_wasted: number
/** Torrent upload limit (bytes/s) */
/** Torrent upload limit (bytes/s), similar to `up_limit` */
up_limit: number
/** Torrent upload speed (bytes/second) */
/** Torrent upload speed (bytes/second), similar to `upspeed` */
up_speed: number
/** Torrent average upload speed (bytes/second) */
up_speed_avg: number