@@ -23,9 +23,9 @@ import IconChevronUp from '~/components/icons/IconChevronUpSmall.vue';
23
23
import IconList from ' ~/components/icons/IconList.vue' ;
24
24
import IconLoop from ' ~/components/icons/IconLoop.vue' ;
25
25
import IconMovie from ' ~/components/icons/IconMovie.vue' ;
26
+ import IconRestore from ' ~/components/icons/IconRestore.vue' ;
26
27
import IconScreen from ' ~/components/icons/IconScreen.vue' ;
27
28
import IconYoutube from ' ~/components/icons/IconYoutube.vue' ;
28
-
29
29
import { ResolveExternalLinks } from ' ~/settings/external.links' ;
30
30
import { SupportedSearchType , useSearchStoreRefs } from ' ~/stores/data/search.store' ;
31
31
import { debounce } from ' ~/utils/debounce.utils' ;
@@ -34,34 +34,6 @@ import { useDebouncedSearch } from '~/utils/store.utils';
34
34
35
35
const i18n = useI18n (' navbar' , ' search' );
36
36
37
- const { search, types, query, pageSize, loading, history } = useSearchStoreRefs ();
38
-
39
- const typeOptions = ref <TraktSearchType []>(SupportedSearchType );
40
-
41
- const inputFocus = ref (false );
42
- const toggleFocus = (focus : boolean ) => {
43
- inputFocus .value = focus ;
44
- };
45
-
46
- const debouncedSearch = useDebouncedSearch (search , 1000 );
47
- const external = computed (() => ResolveExternalLinks .trakt .query (debouncedSearch .value ));
48
-
49
- const filteredHistory = computed (() =>
50
- [... history .value ]
51
- .filter (val => {
52
- const _search = debouncedSearch .value ?.toLowerCase ().trim ();
53
- if (! _search ) return false ;
54
- const _val = val .toLowerCase ().trim ();
55
- if (_val === _search ) return false ;
56
- return _val .includes (_search ) || _search .includes (_val );
57
- })
58
- .slice (0 , 10 ),
59
- );
60
-
61
- const historyOptions = computed (() =>
62
- filteredHistory .value .map (value => ({ value , label: value })),
63
- );
64
-
65
37
const { reverse } = defineProps ({
66
38
parentElement: {
67
39
type: HTMLElement ,
@@ -74,6 +46,63 @@ const { reverse } = defineProps({
74
46
},
75
47
});
76
48
49
+ const { search, types, query, pageSize, loading, history } = useSearchStoreRefs ();
50
+
51
+ const typeOptions = ref <TraktSearchType []>(SupportedSearchType );
52
+
53
+ const debouncedSearch = useDebouncedSearch (search , 1000 );
54
+ const external = computed (() => ResolveExternalLinks .trakt .query (debouncedSearch .value ));
55
+
56
+ const filteredHistory = computed (() => {
57
+ const _search = debouncedSearch .value ?.toLowerCase ().trim ();
58
+
59
+ if (! _search || ! history .value ) {
60
+ return { filter: [], recent: Array .from (history .value ) };
61
+ }
62
+
63
+ const filter: string [] = [];
64
+ const recent: string [] = [];
65
+
66
+ history .value .forEach (value => {
67
+ const _val = value .toLowerCase ().trim ();
68
+ if (_val === _search ) return ;
69
+ if (_val .includes (_search ) || _search .includes (_val )) {
70
+ filter .push (value );
71
+ } else if (recent .length < 5 ) {
72
+ recent .push (value );
73
+ }
74
+ });
75
+
76
+ return { filter , recent };
77
+ });
78
+ const historyOptions = computed (() => {
79
+ const results = [];
80
+ const filter = {
81
+ type: ' group' ,
82
+ label: i18n (' option_group_filter' ),
83
+ key: ' filter' ,
84
+ children: filteredHistory .value .filter .map (value => ({
85
+ value ,
86
+ label: value ,
87
+ key: ` filter-${value } ` ,
88
+ })),
89
+ };
90
+ if (filter .children .length ) results .push (filter );
91
+ const recent = {
92
+ type: ' group' ,
93
+ label: i18n (' option_group_recent' ),
94
+ key: ' recent' ,
95
+ children: filteredHistory .value .recent .map (value => ({
96
+ value ,
97
+ label: value ,
98
+ key: ` recent-${value } ` ,
99
+ icon: IconRestore ,
100
+ })),
101
+ };
102
+ if (recent .children .length ) results .push (recent );
103
+ return results ;
104
+ });
105
+
77
106
const selectedValues = computed ({
78
107
get : () => types .value ,
79
108
set : selected => {
@@ -98,8 +127,11 @@ const getIcon = (type: TraktSearchType) => {
98
127
99
128
const open = ref (false );
100
129
101
- type SearchOption = SelectOption & { value: TraktSearchType ; icon: Component };
102
- const searchOptions = computed <SearchOption []>(() =>
130
+ type SearchOption <T extends string = string > = SelectOption & {
131
+ value: T ;
132
+ icon: Component ;
133
+ };
134
+ const searchOptions = computed <SearchOption <TraktSearchType >[]>(() =>
103
135
typeOptions .value .map (type => ({
104
136
label: i18n (type , ' navbar' , ' search' , ' type' ),
105
137
value: type ,
@@ -169,7 +201,9 @@ const placement = computed(() => (reverse ? 'top' : 'bottom'));
169
201
170
202
onActivated (() => {
171
203
if (! search .value ) inputRef .value ?.focus ();
172
- if (typeof route ?.query ?.search === ' string' ) search .value = route .query .search ;
204
+ const _search = route ?.query ?.search ;
205
+ if (typeof _search !== ' string' ) return ;
206
+ search .value = _search .trim ();
173
207
});
174
208
</script >
175
209
@@ -218,12 +252,9 @@ onActivated(() => {
218
252
v-model:value =" debouncedSearch"
219
253
class =" search-input"
220
254
:loading =" loading"
221
- :disabled =" loading"
222
255
:placeholder =" i18n('search', 'navbar')"
223
256
autosize
224
257
clearable
225
- :on-input-focus =" () => toggleFocus(true)"
226
- :on-input-blur =" () => toggleFocus(false)"
227
258
:options =" historyOptions"
228
259
:to =" parentElement"
229
260
>
0 commit comments