feat(history): Add history to some fields (#1361)

This commit is contained in:
Rémi Marseault 2023-11-28 18:45:22 +01:00 committed by GitHub
parent 988ecaaa03
commit ef50c6c341
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 142 additions and 30 deletions

View file

@ -0,0 +1,41 @@
<script setup lang="ts">
import { HistoryKey } from '@/constants/vuetorrent'
import { useHistoryStore } from '@/stores'
import { computed, ref } from 'vue'
const props = defineProps<{
modelValue?: string
historyKey: HistoryKey
}>()
const emit = defineEmits<{
'update:modelValue': [value: string]
}>()
const historyStore = useHistoryStore()
const field = ref<HTMLInputElement>()
const historyValue = computed(() => historyStore.getHistory(props.historyKey))
const _value = computed({
get: () => props.modelValue ?? '',
set: (value: string) => emit('update:modelValue', value)
})
function saveValueToHistory() {
historyStore.pushValueToHistory(props.historyKey, _value.value)
}
defineExpose({
saveValueToHistory,
focus: () => field.value?.focus()
})
</script>
<template>
<v-combobox v-model="_value" ref="field" :items="historyValue" />
</template>
<style scoped>
</style>

View file

@ -1,6 +1,8 @@
<script lang="ts" setup>
import HistoryField from '@/components/Core/HistoryField.vue'
import { useDialog } from '@/composables'
import { AppPreferences } from '@/constants/qbit'
import { HistoryKey } from '@/constants/vuetorrent'
import { useAddTorrentStore, useMaindataStore, usePreferenceStore, useTorrentStore, useVueTorrentStore } from '@/stores'
import { storeToRefs } from 'pinia'
import { computed, ref } from 'vue'
@ -37,6 +39,10 @@ const stopConditionOptions = [
const isFormValid = computed(() => urls.value.length > 0 || files.value.length > 0)
const cookieField = ref<typeof HistoryField>()
const dlPathField = ref<typeof HistoryField>()
const savePathField = ref<typeof HistoryField>()
const cookie = computed({
get: () => form.value.cookie,
set: value => form.value.cookie = value || undefined
@ -145,6 +151,9 @@ function submit() {
autoClose: 1500
})
.then(() => {
cookieField.value?.saveValueToHistory()
dlPathField.value?.saveValueToHistory()
savePathField.value?.saveValueToHistory()
addTorrentStore.resetForm()
close()
})
@ -197,14 +206,13 @@ const onCategoryChanged = () => {
<v-icon color="accent">mdi-link</v-icon>
</template>
</v-textarea>
<v-text-field v-if="!!urls" v-model="cookie" clearable autocomplete="cookie"
<HistoryField v-if="!!urls" v-model="cookie" :historyKey="HistoryKey.COOKIE" ref="cookieField" clearable
:label="$t('dialogs.add.cookie')" :placeholder="$t('dialogs.add.cookiePlaceholder')">
<template v-slot:prepend>
<v-icon color="accent">mdi-cookie</v-icon>
</template>
</v-text-field>
<v-text-field v-model="rename" clearable hide-details autocomplete="rename"
:label="$t('dialogs.add.rename')">
</HistoryField>
<v-text-field v-model="rename" clearable hide-details :label="$t('dialogs.add.rename')">
<template v-slot:prepend>
<v-icon color="accent">mdi-rename</v-icon>
</template>
@ -251,21 +259,21 @@ const onCategoryChanged = () => {
</v-col>
<v-col cols="12">
<v-text-field v-model="downloadPath" :disabled="form.autoTMM" autocomplete="downloadPath"
:label="t('dialogs.add.downloadPath')" hide-details>
<HistoryField v-model="downloadPath" :history-key="HistoryKey.TORRENT_PATH" ref="dlPathField"
:disabled="form.autoTMM" :label="t('dialogs.add.downloadPath')" hide-details>
<template v-slot:prepend>
<v-icon color="accent">mdi-tray-arrow-down</v-icon>
</template>
</v-text-field>
</HistoryField>
</v-col>
<v-col cols="12">
<v-text-field v-model="form.savepath" :disabled="form.autoTMM" autocomplete="savepath"
:label="t('dialogs.add.savePath')" hide-details>
<HistoryField v-model="form.savepath" :history-key="HistoryKey.TORRENT_PATH" ref="savePathField"
:disabled="form.autoTMM" :label="t('dialogs.add.savePath')" hide-details>
<template v-slot:prepend>
<v-icon color="accent">mdi-content-save</v-icon>
</template>
</v-text-field>
</HistoryField>
</v-col>
<v-col cols="12" md="6">
@ -315,7 +323,7 @@ const onCategoryChanged = () => {
<v-expansion-panel-text>
<v-row>
<v-col cols="12" md="6">
<v-text-field v-model="dlLimit" :label="$t('dialogs.add.dlLimit')" autocomplete="dlLimit"
<v-text-field v-model="dlLimit" :label="$t('dialogs.add.dlLimit')"
hide-details suffix="KiB/s">
<template v-slot:prepend>
<v-icon color="accent">mdi-download</v-icon>
@ -323,7 +331,7 @@ const onCategoryChanged = () => {
</v-text-field>
</v-col>
<v-col cols="12" md="6">
<v-text-field v-model="upLimit" :label="$t('dialogs.add.upLimit')" autocomplete="upLimit"
<v-text-field v-model="upLimit" :label="$t('dialogs.add.upLimit')"
hide-details suffix="KiB/s">
<template v-slot:prepend>
<v-icon color="accent">mdi-upload</v-icon>
@ -332,18 +340,18 @@ const onCategoryChanged = () => {
</v-col>
<v-col cols="12" md="4">
<v-text-field v-model="ratioLimit" autocomplete="ratioLimit"
<v-text-field v-model="ratioLimit"
:hint="$t('dialogs.add.limitHint')" :label="$t('dialogs.add.ratioLimit')"
type="number" />
</v-col>
<v-col cols="12" md="4">
<v-text-field v-model="seedingTimeLimit" autocomplete="seedingTimeLimit"
<v-text-field v-model="seedingTimeLimit"
:label="$t('dialogs.add.seedingTimeLimit')"
:hint="$t('dialogs.add.limitHint')"
:suffix="$t('units.minutes')" type="number" />
</v-col>
<v-col cols="12" md="4">
<v-text-field v-model="inactiveSeedingTimeLimit" autocomplete="inactiveSeedingTimeLimit"
<v-text-field v-model="inactiveSeedingTimeLimit"
:label="$t('dialogs.add.inactiveSeedingTimeLimit')"
:hint="$t('dialogs.add.limitHint')"
:suffix="$t('units.minutes')" type="number" />

View file

@ -1,5 +1,7 @@
<script setup lang="ts">
import HistoryField from '@/components/Core/HistoryField.vue'
import { useDialog } from '@/composables'
import { HistoryKey } from '@/constants/vuetorrent'
import { useMaindataStore, useTorrentStore } from '@/stores'
import { computed, onBeforeMount, reactive, ref } from 'vue'
import { useI18n } from 'vue-i18n'
@ -17,6 +19,7 @@ const maindataStore = useMaindataStore()
const torrentStore = useTorrentStore()
const form = ref<VForm>()
const field = ref<typeof HistoryField>()
const isFormValid = ref(false)
const formData = reactive({
newPath: ''
@ -41,6 +44,8 @@ async function submit() {
await maindataStore.toggleAutoTmm(props.hashes, false)
await torrentStore.moveTorrents(props.mode, props.hashes, formData.newPath)
field.value?.saveValueToHistory()
close()
}
@ -60,7 +65,8 @@ onBeforeMount(() => {
<v-card-text>
<v-form v-model="isFormValid" ref="form" @submit.prevent>
<v-text-field v-if="oldPath" :model-value="oldPath" disabled :label="$t('dialogs.moveTorrent.oldPath')" />
<v-text-field v-model="formData.newPath" :rules="rules" autofocus :label="$t('dialogs.moveTorrent.newPath')"
<HistoryField v-model="formData.newPath" :historyKey="HistoryKey.TORRENT_PATH" ref="field"
:rules="rules" autofocus :label="$t('dialogs.moveTorrent.newPath')"
@keydown.enter="submit" />
</v-form>
</v-card-text>

View file

@ -1,13 +1,14 @@
<script setup lang="ts">
import { TitleOptions } from '@/constants/vuetorrent'
import { LOCALES } from '@/locales'
import { useAppStore, useVueTorrentStore } from '@/stores'
import { useAppStore, useHistoryStore, useVueTorrentStore } from '@/stores'
import { computed, onBeforeMount, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { toast } from 'vue3-toastify'
const { t } = useI18n()
const appStore = useAppStore()
const historyStore = useHistoryStore()
const vueTorrentStore = useVueTorrentStore()
const titleOptionsList = [
@ -142,14 +143,18 @@ onBeforeMount(() => {
<v-list-item>
<v-row>
<v-col cols="12" md="6">
<v-col cols="12" md="4">
<v-text-field v-model="vueTorrentStore.refreshInterval" type="number" hide-details suffix="ms"
:label="t('settings.vuetorrent.general.refreshInterval')" />
</v-col>
<v-col cols="12" md="6">
<v-col cols="12" md="4">
<v-text-field v-model="vueTorrentStore.fileContentInterval" type="number" hide-details suffix="ms"
:label="t('settings.vuetorrent.general.fileContentInterval')" />
</v-col>
<v-col cols="12" md="4">
<v-text-field v-model="historyStore.historySize" type="number" hide-details
:label="t('settings.vuetorrent.general.historySize')" />
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="6">

View file

@ -0,0 +1,5 @@
export enum HistoryKey {
COOKIE = 'cookie',
SEARCH_ENGINE_QUERY = 'searchEngineQuery',
TORRENT_PATH = 'torrentPath'
}

View file

@ -3,6 +3,7 @@ import { propsData, propsMetadata } from './DashboardDefaults'
import { DashboardProperty } from './DashboardProperty'
import { DashboardPropertyType } from './DashboardPropertyType'
import { typesMap, getFileIcon } from './FileIcon'
import { HistoryKey } from './HistoryKey'
import { TitleOptions } from './TitleOptions'
export { TorrentProperty, PropertyData, PropertyMetadata, propsData, propsMetadata, DashboardProperty, DashboardPropertyType, typesMap, getFileIcon, TitleOptions }
export { TorrentProperty, PropertyData, PropertyMetadata, propsData, propsMetadata, DashboardProperty, DashboardPropertyType, typesMap, getFileIcon, HistoryKey, TitleOptions }

View file

@ -1,6 +1,8 @@
<script setup lang="ts">
import HistoryField from '@/components/Core/HistoryField.vue'
import PluginManagerDialog from '@/components/Dialogs/PluginManagerDialog.vue'
import { useSearchQuery } from '@/composables'
import { HistoryKey } from '@/constants/vuetorrent'
import { formatData } from '@/helpers'
import { useAddTorrentStore, useDialogStore, useSearchEngineStore, useVueTorrentStore } from '@/stores'
import { SearchPlugin, SearchResult } from '@/types/qbit/models'
@ -17,7 +19,7 @@ const dialogStore = useDialogStore()
const searchEngineStore = useSearchEngineStore()
const vuetorrentStore = useVueTorrentStore()
const queryInput = ref<HTMLInputElement>()
const queryInput = ref<typeof HistoryField>()
const pluginManagerDialogVisible = ref(false)
const tabIndex = ref(0)
@ -85,6 +87,7 @@ function downloadTorrent(result: SearchResult) {
async function runNewSearch() {
await searchEngineStore.runNewSearch(selectedTab.value)
selectedTab.value.timer = setInterval(() => refreshResults(selectedTab.value), 1000)
queryInput.value?.saveValueToHistory()
}
async function stopSearch(tab: SearchData) {
@ -179,15 +182,9 @@ onBeforeUnmount(() => {
<v-list-item>
<v-row class="mt-1">
<v-col cols="12" md="6">
<v-text-field
v-model="selectedTab.query"
ref="queryInput"
autofocus
density="compact"
hide-details
clearable
:label="$t('searchEngine.query')"
@keydown.enter.prevent="runNewSearch" />
<HistoryField v-model="selectedTab.query" :history-key="HistoryKey.SEARCH_ENGINE_QUERY" ref="queryInput"
autofocus density="compact" hide-details clearable
:label="$t('searchEngine.query')" @keydown.enter.prevent="runNewSearch" />
</v-col>
<v-col cols="6" sm="5" md="2">

47
src/stores/history.ts Normal file
View file

@ -0,0 +1,47 @@
import { HistoryKey } from '@/constants/vuetorrent'
import { defineStore } from 'pinia'
import { reactive, ref } from 'vue'
type History = Partial<Record<HistoryKey, string[]>>
export const useHistoryStore = defineStore('history', () => {
const _history = reactive<History>({})
const historySize = ref(3)
function pushValueToHistory(key: HistoryKey, value: string) {
const historyValue = getHistory(key)
historyValue.splice(0, 0, value)
const valueIndex = historyValue.indexOf(value, 1)
if (valueIndex !== -1) {
historyValue.splice(valueIndex, 1)
}
if (historyValue.length > historySize.value) {
historyValue.splice(historySize.value, historyValue.length - historySize.value)
}
_history[key] = historyValue
}
function getHistory(key: HistoryKey) {
return _history[key] || []
}
return {
_history,
historySize,
pushValueToHistory,
getHistory
}
}, {
persist: {
enabled: true,
strategies: [
{
storage: localStorage,
key: 'vuetorrent_history'
}
]
}
})

View file

@ -3,6 +3,7 @@ import { useAppStore } from './app'
import { useAuthStore } from './auth'
import { useDashboardStore } from './dashboard'
import { useDialogStore } from './dialog'
import { useHistoryStore } from './history'
import { useLogStore } from './logs'
import { useMaindataStore } from './maindata'
import { useNavbarStore } from './navbar'
@ -18,6 +19,7 @@ export {
useAuthStore,
useDashboardStore,
useDialogStore,
useHistoryStore,
useLogStore,
useMaindataStore,
useNavbarStore,