@@ -6,75 +6,130 @@ import type { FilterUpdateChipsEvent, IFileListFilter, IFileListFilterChip } fro
66import { subscribe } from '@nextcloud/event-bus'
77import { getFileListFilters } from '@nextcloud/files'
88import { defineStore } from 'pinia'
9+ import { computed , ref } from 'vue'
910import logger from '../logger'
1011
11- export const useFiltersStore = defineStore ( 'filters' , {
12- state : ( ) => ( {
13- chips : { } as Record < string , IFileListFilterChip [ ] > ,
14- filters : [ ] as IFileListFilter [ ] ,
15- filtersChanged : false ,
16- } ) ,
17-
18- getters : {
19- /**
20- * Currently active filter chips
21- * @param state Internal state
22- */
23- activeChips ( state ) : IFileListFilterChip [ ] {
24- return Object . values ( state . chips ) . flat ( )
25- } ,
26-
27- /**
28- * Filters sorted by order
29- * @param state Internal state
30- */
31- sortedFilters ( state ) : IFileListFilter [ ] {
32- return state . filters . sort ( ( a , b ) => a . order - b . order )
33- } ,
34-
35- /**
36- * All filters that provide a UI for visual controlling the filter state
37- */
38- filtersWithUI ( ) : Required < IFileListFilter > [ ] {
39- return this . sortedFilters . filter ( ( filter ) => 'mount' in filter ) as Required < IFileListFilter > [ ]
40- } ,
41- } ,
42-
43- actions : {
44- addFilter ( filter : IFileListFilter ) {
45- filter . addEventListener ( 'update:chips' , this . onFilterUpdateChips )
46- filter . addEventListener ( 'update:filter' , this . onFilterUpdate )
47- this . filters . push ( filter )
48- logger . debug ( 'New file list filter registered' , { id : filter . id } )
49- } ,
50-
51- removeFilter ( filterId : string ) {
52- const index = this . filters . findIndex ( ( { id } ) => id === filterId )
53- if ( index > - 1 ) {
54- const [ filter ] = this . filters . splice ( index , 1 )
55- filter . removeEventListener ( 'update:chips' , this . onFilterUpdateChips )
56- filter . removeEventListener ( 'update:filter' , this . onFilterUpdate )
57- logger . debug ( 'Files list filter unregistered' , { id : filterId } )
58- }
59- } ,
12+ /**
13+ * Check if the given value is an instance file list filter with mount function
14+ * @param value The filter to check
15+ */
16+ function isFileListFilterWithUi ( value : IFileListFilter ) : value is Required < IFileListFilter > {
17+ return 'mount' in value
18+ }
19+
20+ export const useFiltersStore = defineStore ( 'filters' , ( ) => {
21+ const chips = ref < Record < string , IFileListFilterChip [ ] > > ( { } )
22+ const filters = ref < IFileListFilter [ ] > ( [ ] )
23+ const filtersChanged = ref ( false )
24+
25+ /**
26+ * Currently active filter chips
27+ */
28+ const activeChips = computed < IFileListFilterChip [ ] > (
29+ ( ) => Object . values ( chips . value ) . flat ( ) ,
30+ )
31+
32+ /**
33+ * Filters sorted by order
34+ */
35+ const sortedFilters = computed < IFileListFilter [ ] > (
36+ ( ) => filters . value . sort ( ( a , b ) => a . order - b . order ) ,
37+ )
38+
39+ /**
40+ * All filters that provide a UI for visual controlling the filter state
41+ */
42+ const filtersWithUI = computed < Required < IFileListFilter > [ ] > (
43+ ( ) => sortedFilters . value . filter ( isFileListFilterWithUi )
44+ )
45+
46+ /**
47+ * Register a new filter on the store.
48+ * This will subscribe the store to the filters events.
49+ *
50+ * @param filter The filter to add
51+ */
52+ function addFilter ( filter : IFileListFilter ) {
53+ filter . addEventListener ( 'update:chips' , onFilterUpdateChips )
54+ filter . addEventListener ( 'update:filter' , onFilterUpdate )
6055
61- onFilterUpdate ( ) {
62- this . filtersChanged = true
63- } ,
56+ filters . value . push ( filter )
57+ logger . debug ( 'New file list filter registered' , { id : filter . id } )
58+ }
6459
65- onFilterUpdateChips ( event : FilterUpdateChipsEvent ) {
66- const id = ( event . target as IFileListFilter ) . id
67- this . chips = { ...this . chips , [ id ] : [ ...event . detail ] }
60+ /**
61+ * Unregister a filter from the store.
62+ * This will remove the filter from the store and unsubscribe the store from the filer events.
63+ * @param filterId Id of the filter to remove
64+ */
65+ function removeFilter ( filterId : string ) {
66+ const index = filters . value . findIndex ( ( { id } ) => id === filterId )
67+ if ( index > - 1 ) {
68+ const [ filter ] = filters . value . splice ( index , 1 )
69+ filter . removeEventListener ( 'update:chips' , onFilterUpdateChips )
70+ filter . removeEventListener ( 'update:filter' , onFilterUpdate )
71+ logger . debug ( 'Files list filter unregistered' , { id : filterId } )
72+ }
73+ }
6874
69- logger . debug ( 'File list filter chips updated' , { filter : id , chips : event . detail } )
70- } ,
75+ /**
76+ * Event handler for filter update events
77+ * @private
78+ */
79+ function onFilterUpdate ( ) {
80+ filtersChanged . value = true
81+ }
7182
72- init ( ) {
73- subscribe ( 'files:filter:added' , this . addFilter )
74- subscribe ( 'files:filter:removed' , this . removeFilter )
75- for ( const filter of getFileListFilters ( ) ) {
76- this . addFilter ( filter )
83+ /**
84+ * Event handler for filter chips updates
85+ * @param event The update event
86+ * @private
87+ */
88+ function onFilterUpdateChips ( event : FilterUpdateChipsEvent ) {
89+ const id = ( event . target as IFileListFilter ) . id
90+ chips . value = {
91+ ...chips . value ,
92+ [ id ] : [ ...event . detail ] ,
93+ }
94+
95+ logger . debug ( 'File list filter chips updated' , { filter : id , chips : event . detail } )
96+ }
97+
98+ /**
99+ * Event handler that resets all filters if the file list view was changed.
100+ * @private
101+ */
102+ function onViewChanged ( ) {
103+ logger . debug ( 'Reset all file list filters - view changed' )
104+
105+ for ( const filter of filters . value ) {
106+ if ( filter . reset !== undefined ) {
107+ filter . reset ( )
77108 }
78- } ,
79- } ,
109+ }
110+ }
111+
112+ // Initialize the store
113+ subscribe ( 'files:navigation:changed' , onViewChanged )
114+ subscribe ( 'files:filter:added' , addFilter )
115+ subscribe ( 'files:filter:removed' , removeFilter )
116+ for ( const filter of getFileListFilters ( ) ) {
117+ addFilter ( filter )
118+ }
119+
120+ return {
121+ // state
122+ chips,
123+ filters,
124+ filtersWithUI,
125+ filtersChanged,
126+
127+ // getters / computed
128+ activeChips,
129+ sortedFilters,
130+
131+ // actions / methods
132+ addFilter,
133+ removeFilter,
134+ }
80135} )
0 commit comments