Skip to content

Commit

Permalink
Make history page remember last query string & search limit (FreeTube…
Browse files Browse the repository at this point in the history
…App#5192)

* $ Simplify boolean assignment, rename session storage key

* * Make history page remember last query string & search limit only when going back

* ! Fix restoring filtered history having unnecessary delay

* * Make subscribed channels page remember last query string only when going back

* * Make user playlists page remember last query string only when going back

* * Make playlist page remember last query string only when going back

* * Make channel page remember last query string only when going back

* * Save more options

* ! Fix strange outline on nav buttons

* * Put `currentTab` value into proper place params instead of query

* ! Fix search tab showing "0 results" before search done

* - Remove useless file after merging dev

* $ Change code style

* * Put event listener back to mounted
  • Loading branch information
PikachuEXE authored and JL committed Dec 7, 2024
1 parent 8e10825 commit f892e31
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 51 deletions.
7 changes: 6 additions & 1 deletion src/renderer/components/ChannelDetails/ChannelDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
v-if="showSearchBar"
ref="searchBar"
:placeholder="$t('Channel.Search Channel')"
:value="query"
:show-clear-text-button="true"
class="channelSearch"
:maxlength="255"
Expand Down Expand Up @@ -291,7 +292,11 @@ const props = defineProps({
currentTab: {
type: String,
default: 'videos'
}
},
query: {
type: String,
default: ''
},
})
const emit = defineEmits(['change-tab', 'search', 'subscribed'])
Expand Down
86 changes: 74 additions & 12 deletions src/renderer/views/Channel/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
parseLocalPlaylistVideo,
parseChannelHomeTab
} from '../../helpers/api/local'
import { isNavigationFailure, NavigationFailureType } from 'vue-router'

export default defineComponent({
name: 'Channel',
Expand All @@ -62,8 +63,10 @@ export default defineComponent({
},
data: function () {
return {
skipRouteChangeWatcherOnce: false,
isLoading: true,
isElementListLoading: false,
isSearchTabLoading: false,
currentTab: 'videos',
id: '',
/** @type {import('youtubei.js').YT.Channel|null} */
Expand Down Expand Up @@ -306,10 +309,22 @@ export default defineComponent({

return values
},

isCurrentTabLoading() {
if (this.currentTab === 'search') {
return this.isSearchTabLoading
}

return this.isElementListLoading
},
},
watch: {
$route() {
// react to route changes...
if (this.skipRouteChangeWatcherOnce) {
this.skipRouteChangeWatcherOnce = false
return
}
this.isLoading = true

if (this.$route.query.url) {
Expand Down Expand Up @@ -366,8 +381,9 @@ export default defineComponent({

// Re-enable auto refresh on sort value change AFTER update done
if (!process.env.SUPPORTS_LOCAL_API || this.backendPreference === 'invidious') {
this.getChannelInfoInvidious()
this.autoRefreshOnSortByChangeEnabled = true
this.getChannelInfoInvidious().finally(() => {
this.autoRefreshOnSortByChangeEnabled = true
})
} else {
this.getChannelLocal().finally(() => {
this.autoRefreshOnSortByChangeEnabled = true
Expand Down Expand Up @@ -444,9 +460,9 @@ export default defineComponent({
}
}
},
mounted: function () {
mounted: async function () {
if (this.$route.query.url) {
this.resolveChannelUrl(this.$route.query.url, this.$route.params.currentTab)
await this.resolveChannelUrl(this.$route.query.url, this.$route.params.currentTab)
return
}

Expand All @@ -462,13 +478,19 @@ export default defineComponent({

// Enable auto refresh on sort value change AFTER initial update done
if (!process.env.SUPPORTS_LOCAL_API || this.backendPreference === 'invidious') {
this.getChannelInfoInvidious()
this.autoRefreshOnSortByChangeEnabled = true
await this.getChannelInfoInvidious().finally(() => {
this.autoRefreshOnSortByChangeEnabled = true
})
} else {
this.getChannelLocal().finally(() => {
await this.getChannelLocal().finally(() => {
this.autoRefreshOnSortByChangeEnabled = true
})
}

const oldQuery = this.$route.query.searchQueryText ?? ''
if (oldQuery !== null && oldQuery !== '') {
this.newSearch(oldQuery)
}
},
methods: {
resolveChannelUrl: async function (url, tab = undefined) {
Expand Down Expand Up @@ -1027,7 +1049,7 @@ export default defineComponent({
this.channelInstance = null

const expectedId = this.id
invidiousGetChannelInfo(this.id).then((response) => {
return invidiousGetChannelInfo(this.id).then((response) => {
if (expectedId !== this.id) {
return
}
Expand Down Expand Up @@ -1889,13 +1911,14 @@ export default defineComponent({
const newTabNode = document.getElementById(`${tab}Tab`)
this.currentTab = tab
newTabNode?.focus()
this.showOutlines()
// Prevents outline shown in strange places
if (newTabNode != null) { this.showOutlines() }
},

newSearch: function (query) {
this.lastSearchQuery = query
this.searchContinuationData = null
this.isElementListLoading = true
this.isSearchTabLoading = true
this.searchPage = 1
this.searchResults = []
this.changeTab('search')
Expand All @@ -1908,6 +1931,10 @@ export default defineComponent({
break
}
},
newSearchWithStatePersist(query) {
this.saveStateInRouter(query)
this.newSearch(query)
},

searchChannelLocal: async function () {
const isNewSearch = this.searchContinuationData === null
Expand Down Expand Up @@ -1946,7 +1973,7 @@ export default defineComponent({
}

this.searchContinuationData = result.has_continuation ? result : null
this.isElementListLoading = false
this.isSearchTabLoading = false
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
Expand Down Expand Up @@ -1982,7 +2009,7 @@ export default defineComponent({
} else {
this.searchResults = this.searchResults.concat(response)
}
this.isElementListLoading = false
this.isSearchTabLoading = false
this.searchPage++
}).catch((err) => {
console.error(err)
Expand Down Expand Up @@ -2026,6 +2053,41 @@ export default defineComponent({
})
},

async saveStateInRouter(query) {
this.skipRouteChangeWatcherOnce = true
if (query === '') {
try {
await this.$router.replace({ path: `/channel/${this.id}` })
} catch (failure) {
if (isNavigationFailure(failure, NavigationFailureType.duplicated)) {
return
}

throw failure
}
return
}

try {
await this.$router.replace({
path: `/channel/${this.id}`,
params: {
currentTab: 'search',
},
query: {
searchQueryText: query,
},
})
} catch (failure) {
if (isNavigationFailure(failure, NavigationFailureType.duplicated)) {
return
}

throw failure
}
this.skipRouteChangeWatcherOnce = false
},

getIconForSortPreference: (s) => getIconForSortPreference(s),

...mapActions([
Expand Down
7 changes: 4 additions & 3 deletions src/renderer/views/Channel/Channel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
:is-subscribed="isSubscribed"
:visible-tabs="tabInfoValues"
:current-tab="currentTab"
:query="lastSearchQuery"
class="card channelDetails"
@change-tab="changeTab"
@search="newSearch"
@search="newSearchWithStatePersist"
@subscribed="handleSubscription"
/>
<ft-card
Expand Down Expand Up @@ -80,7 +81,7 @@
/>
</div>
<ft-loader
v-if="isElementListLoading"
v-if="isCurrentTabLoading"
/>
<div
v-if="currentTab !== 'about' && !isElementListLoading"
Expand Down Expand Up @@ -207,7 +208,7 @@
:use-channels-hidden-preference="false"
/>
<ft-flex-box
v-if="currentTab === 'search' && searchResults.length === 0"
v-if="currentTab === 'search' && !isSearchTabLoading && searchResults.length === 0"
>
<p class="message">
{{ $t("Channel.Your search results have returned 0 results") }}
Expand Down
89 changes: 75 additions & 14 deletions src/renderer/views/History/History.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineComponent } from 'vue'
import { isNavigationFailure, NavigationFailureType } from 'vue-router'
import debounce from 'lodash.debounce'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
import FtSelect from '../../components/ft-select/ft-select.vue'
Expand Down Expand Up @@ -76,42 +77,68 @@ export default defineComponent({
}
},
watch: {
query() {
this.searchDataLimit = 100
this.filterHistoryAsync()
},
fullData() {
this.filterHistory()
},
doCaseSensitiveSearch() {
this.filterHistory()
}
this.saveStateInRouter()
},
},
mounted: function () {
created: function () {
document.addEventListener('keydown', this.keyboardShortcutHandler)
const limit = sessionStorage.getItem('historyLimit')

if (limit !== null) {
this.dataLimit = limit
const oldDataLimit = sessionStorage.getItem('History/dataLimit')
if (oldDataLimit !== null) {
this.dataLimit = oldDataLimit
}

this.activeData = this.fullData

this.showLoadMoreButton = this.activeData.length < this.historyCacheSorted.length

this.filterHistoryDebounce = debounce(this.filterHistory, 500)

const oldQuery = this.$route.query.searchQueryText ?? ''
if (oldQuery !== null && oldQuery !== '') {
// `handleQueryChange` must be called after `filterHistoryDebounce` assigned
this.handleQueryChange(
oldQuery,
{
limit: this.$route.query.searchDataLimit,
doCaseSensitiveSearch: this.$route.query.doCaseSensitiveSearch === 'true',
filterNow: true,
},
)
} else {
// Only display unfiltered data when no query used last time
this.filterHistory()
}
},
beforeDestroy: function () {
document.removeEventListener('keydown', this.keyboardShortcutHandler)
},
methods: {
handleQueryChange(query, { limit = null, doCaseSensitiveSearch = null, filterNow = false } = {}) {
this.query = query

const newLimit = limit ?? 100
this.searchDataLimit = newLimit
const newDoCaseSensitiveSearch = doCaseSensitiveSearch ?? this.doCaseSensitiveSearch
this.doCaseSensitiveSearch = newDoCaseSensitiveSearch

this.saveStateInRouter({
query: query,
searchDataLimit: newLimit,
doCaseSensitiveSearch: newDoCaseSensitiveSearch,
})

filterNow ? this.filterHistory() : this.filterHistoryAsync()
},

increaseLimit: function () {
if (this.query !== '') {
this.searchDataLimit += 100
this.filterHistory()
} else {
this.dataLimit += 100
sessionStorage.setItem('historyLimit', this.dataLimit)
sessionStorage.setItem('History/dataLimit', this.dataLimit)
}
},
filterHistoryAsync: function() {
Expand All @@ -135,6 +162,40 @@ export default defineComponent({
this.activeData = filteredQuery.length < this.searchDataLimit ? filteredQuery : filteredQuery.slice(0, this.searchDataLimit)
this.showLoadMoreButton = this.activeData.length > this.searchDataLimit
},

async saveStateInRouter({ query = this.query, searchDataLimit = this.searchDataLimit, doCaseSensitiveSearch = this.doCaseSensitiveSearch } = {}) {
if (query === '') {
try {
await this.$router.replace({ name: 'history' })
} catch (failure) {
if (isNavigationFailure(failure, NavigationFailureType.duplicated)) {
return
}

throw failure
}
return
}

const routerQuery = {
searchQueryText: query,
searchDataLimit: searchDataLimit,
}
if (doCaseSensitiveSearch) { routerQuery.doCaseSensitiveSearch = 'true' }
try {
await this.$router.replace({
name: 'history',
query: routerQuery,
})
} catch (failure) {
if (isNavigationFailure(failure, NavigationFailureType.duplicated)) {
return
}

throw failure
}
},

keyboardShortcutHandler: function (event) {
ctrlFHandler(event, this.$refs.searchBar)
},
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/views/History/History.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
:placeholder="$t('History.Search bar placeholder')"
:show-clear-text-button="true"
:show-action-button="false"
@input="(input) => query = input"
@clear="query = ''"
:value="query"
@input="(input) => handleQueryChange(input)"
@clear="() => handleQueryChange('')"
/>
<div
class="optionsRow"
Expand Down
Loading

0 comments on commit f892e31

Please sign in to comment.