Skip to content

Commit

Permalink
Fix issue FreeTubeApp#6194: Add filters functionality and apply button
Browse files Browse the repository at this point in the history
  • Loading branch information
Alban Dumas committed Jan 25, 2025
1 parent a9a64b3 commit fdd890b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 28 deletions.
17 changes: 17 additions & 0 deletions src/renderer/components/FtSearchFilters/FtSearchFilters.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<!-- eslint-disable @intlify/vue-i18n/no-missing-keys -->
<template>
<FtPrompt
theme="slim"
Expand Down Expand Up @@ -56,6 +57,12 @@
text-color="var(--text-with-main-color)"
@click="hideSearchFilters"
/>
<FtButton
:label="$t('Apply')"
background-color="var(--primary-color)"
text-color="var(--text-with-main-color)"
@click="applyFilters"
/>
</div>
</FtPrompt>
</template>
Expand Down Expand Up @@ -173,6 +180,16 @@ const featureLabels = computed(() => [

const searchSettings = store.getters.getSearchSettings

function applyFilters() {
const queryText = store.getters.getTopNavInstance?.$refs.searchInput.inputData || ''
const searchSettings = store.getters.getSearchSettings
if (!queryText) {
console.error('No queryText found during Apply Filters')
return
}
store.dispatch('applyFilters', { queryText, searchSettings })
}

/** @type {import('vue').Ref<'relevance' | 'rating' | 'upload_date' | 'view_count'>} */
const sortByValue = ref(searchSettings.sortBy)

Expand Down
40 changes: 12 additions & 28 deletions src/renderer/components/top-nav/top-nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ export default defineComponent({
},
},
mounted: function () {
this.$store.commit('setTopNavInstance', this)
let previousWidth = window.innerWidth
if (window.innerWidth <= MOBILE_WIDTH_THRESHOLD) {
this.showSearchContainer = false
Expand All @@ -209,35 +210,29 @@ export default defineComponent({
previousWidth = window.innerWidth
}
})

this.debounceSearchResults = debounce(this.getSearchSuggestions, 200)
},
methods: {
goToSearch: async function (queryText, { event }) {
goToSearch: async function (queryText, { event, searchSettings = null } = {}) {
const doCreateNewWindow = event && event.shiftKey

if (window.innerWidth <= MOBILE_WIDTH_THRESHOLD) {
this.$refs.searchContainer.blur()
this.showSearchContainer = false
} else {
this.$refs.searchInput.blur()
}

clearLocalSearchSuggestionsSession()

this.getYoutubeUrlInfo(queryText).then((result) => {
switch (result.urlType) {
case 'video': {
const { videoId, timestamp, playlistId } = result

const query = {}
if (timestamp) {
query.timestamp = timestamp
}
if (playlistId && playlistId.length > 0) {
query.playlistId = playlistId
}

openInternalPath({
path: `/watch/${videoId}`,
query,
Expand All @@ -246,10 +241,8 @@ export default defineComponent({
})
break
}

case 'playlist': {
const { playlistId, query } = result

openInternalPath({
path: `/playlist/${playlistId}`,
query,
Expand All @@ -258,10 +251,8 @@ export default defineComponent({
})
break
}

case 'search': {
const { searchQuery, query } = result

openInternalPath({
path: `/search/${encodeURIComponent(searchQuery)}`,
query,
Expand All @@ -270,21 +261,17 @@ export default defineComponent({
})
break
}

case 'hashtag': {
const { hashtag } = result
openInternalPath({
path: `/hashtag/${encodeURIComponent(hashtag)}`,
doCreateNewWindow,
searchQueryText: `#${hashtag}`,
})

break
}

case 'post': {
const { postId, query } = result

openInternalPath({
path: `/post/${postId}`,
query,
Expand All @@ -293,10 +280,8 @@ export default defineComponent({
})
break
}

case 'channel': {
const { channelId, subPath, url } = result

openInternalPath({
path: `/channel/${channelId}/${subPath}`,
doCreateNewWindow,
Expand All @@ -307,31 +292,30 @@ export default defineComponent({
})
break
}

case 'invalid_url':
default: {
// If searchSettings is provided (e.g., from the Apply button), use it.
const queryParams = searchSettings || {
sortBy: this.searchSettings.sortBy,
time: this.searchSettings.time,
type: this.searchSettings.type,
duration: this.searchSettings.duration,
features: this.searchSettings.features,
}
openInternalPath({
path: `/search/${encodeURIComponent(queryText)}`,
query: {
sortBy: this.searchSettings.sortBy,
time: this.searchSettings.time,
type: this.searchSettings.type,
duration: this.searchSettings.duration,
features: this.searchSettings.features,
},
query: queryParams,
doCreateNewWindow,
searchQueryText: queryText,
})
}
}

if (doCreateNewWindow) {
// Query text copied to new window = can be removed from current window
// Query text copied to new window = can be removed from the current window
this.updateSearchInputText('')
}
})
},

focusSearch: function () {
if (!this.hideSearchBar) {
// In order to prevent Klipper's "Synchronize contents of the clipboard
Expand Down
26 changes: 26 additions & 0 deletions src/renderer/store/modules/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from '../../helpers/utils'

const state = {
topNavInstance: null,
isSideNavOpen: false,
outlinesHidden: true,
sessionSearchHistory: [],
Expand Down Expand Up @@ -65,6 +66,10 @@ const state = {
}

const getters = {
getTopNavInstance(state) {
return state.topNavInstance
},

getIsSideNavOpen(state) {
return state.isSideNavOpen
},
Expand Down Expand Up @@ -280,6 +285,23 @@ const actions = {
}
},

applyFilters({ state, rootGetters }, { queryText, searchSettings }) {
const topNavInstance = rootGetters.getTopNavInstance
if (topNavInstance && topNavInstance.goToSearch) {
topNavInstance.goToSearch(queryText, { searchSettings })
} else {
console.error('Unable to find goToSearch method in top-nav instance.')
}
this.dispatch('hideSearchFilters')
},
performSearch({ state }) {
const searchSettings = state.searchSettings
const queryText = state.sessionSearchHistory.length
? state.sessionSearchHistory[0].query
: ''
this.dispatch('goToSearch', { queryText, searchSettings })
},

parseScreenshotCustomFileName: function({ rootState }, payload) {
const { pattern = rootState.settings.screenshotFilenamePattern, date, playerTime, videoId } = payload
const keywords = [
Expand Down Expand Up @@ -805,6 +827,10 @@ const actions = {
}

const mutations = {
setTopNavInstance(state, instance) {
state.topNavInstance = instance
},

toggleSideNav (state) {
state.isSideNavOpen = !state.isSideNavOpen
},
Expand Down
2 changes: 2 additions & 0 deletions static/locales/en-GB.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Search Filters:
4K: 4K
3D: 3D
Location: Location
Apply: 'Apply'
Close: 'Close'
Subscriptions:
# On Subscriptions Page
Subscriptions: 'Subscriptions'
Expand Down
2 changes: 2 additions & 0 deletions static/locales/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ Search Filters:
Location: Location
HDR: HDR
VR180: VR180
Apply: 'Apply'
Close: 'Close'
# On Search Page
Search Results: Search Results
Fetching results. Please wait: Fetching results. Please wait
Expand Down

0 comments on commit fdd890b

Please sign in to comment.