mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2025-02-26 20:31:13 +03:00
perf(Info): add torrent properties (#1528)
This commit is contained in:
parent
8a9bf16710
commit
196f5e33f3
18 changed files with 427 additions and 304 deletions
|
@ -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>
|
28
src/components/TorrentDetail/Info/Info.vue
Normal file
28
src/components/TorrentDetail/Info/Info.vue
Normal 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>
|
|
@ -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>
|
88
src/components/TorrentDetail/Info/PanelBoolean.vue
Normal file
88
src/components/TorrentDetail/Info/PanelBoolean.vue
Normal 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>
|
37
src/components/TorrentDetail/Info/PanelData.vue
Normal file
37
src/components/TorrentDetail/Info/PanelData.vue
Normal 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>
|
36
src/components/TorrentDetail/Info/PanelDatetime.vue
Normal file
36
src/components/TorrentDetail/Info/PanelDatetime.vue
Normal 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>
|
31
src/components/TorrentDetail/Info/PanelDuration.vue
Normal file
31
src/components/TorrentDetail/Info/PanelDuration.vue
Normal 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>
|
50
src/components/TorrentDetail/Info/PanelLongText.vue
Normal file
50
src/components/TorrentDetail/Info/PanelLongText.vue
Normal 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>
|
35
src/components/TorrentDetail/Info/PanelSpeed.vue
Normal file
35
src/components/TorrentDetail/Info/PanelSpeed.vue
Normal 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>
|
40
src/components/TorrentDetail/Info/PanelText.vue
Normal file
40
src/components/TorrentDetail/Info/PanelText.vue
Normal 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>
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
20
src/stores/torrentDetail.ts
Normal file
20
src/stores/torrentDetail.ts
Normal 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
|
||||
}
|
||||
}
|
||||
})
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue