@@ -7,74 +7,133 @@ import { subscribe } from '@nextcloud/event-bus'
77import { getFileListFilters } from '@nextcloud/files'
88import { defineStore } from 'pinia'
99import logger from '../logger'
10+ import { computed , ref } from 'vue'
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+ /**
27+ * Currently active filter chips
28+ */
29+ const activeChips = computed < IFileListFilterChip [ ] > (
30+ ( ) => Object . values ( chips . value ) . flat ( ) ,
31+ )
32+
33+ /**
34+ * Filters sorted by order
35+ */
36+ const sortedFilters = computed < IFileListFilter [ ] > (
37+ ( ) => filters . value . sort ( ( a , b ) => a . order - b . order ) ,
38+ )
39+
40+ /**
41+ * All filters that provide a UI for visual controlling the filter state
42+ */
43+ const filtersWithUI = computed < Required < IFileListFilter > [ ] > (
44+ ( ) => sortedFilters . value . filter ( isFileListFilterWithUi )
45+ )
46+
47+ /**
48+ * Register a new filter on the store.
49+ * This will subscribe the store to the filters events.
50+ *
51+ * @param filter The filter to add
52+ */
53+ function addFilter ( filter : IFileListFilter ) {
54+ filter . addEventListener ( 'update:chips' , onFilterUpdateChips )
55+ filter . addEventListener ( 'update:filter' , onFilterUpdate )
6056
61- onFilterUpdate ( ) {
62- this . filtersChanged = true
63- } ,
57+ filters . value . push ( filter )
58+ logger . debug ( 'New file list filter registered' , { id : filter . id } )
59+ }
6460
65- onFilterUpdateChips ( event : FilterUpdateChipsEvent ) {
66- const id = ( event . target as IFileListFilter ) . id
67- this . chips = { ...this . chips , [ id ] : [ ...event . detail ] }
61+ /**
62+ * Unregister a filter from the store.
63+ * This will remove the filter from the store and unsubscribe the store from the filer events.
64+ * @param filterId Id of the filter to remove
65+ */
66+ function removeFilter ( filterId : string ) {
67+ const index = filters . value . findIndex ( ( { id } ) => id === filterId )
68+ if ( index > - 1 ) {
69+ const [ filter ] = filters . value . splice ( index , 1 )
70+ filter . removeEventListener ( 'update:chips' , onFilterUpdateChips )
71+ filter . removeEventListener ( 'update:filter' , onFilterUpdate )
72+ logger . debug ( 'Files list filter unregistered' , { id : filterId } )
73+ }
74+ }
6875
69- logger . debug ( 'File list filter chips updated' , { filter : id , chips : event . detail } )
70- } ,
76+ /**
77+ * Event handler for filter update events
78+ * @private
79+ */
80+ function onFilterUpdate ( ) {
81+ filtersChanged . value = true
82+ }
7183
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 )
84+ /**
85+ * Event handler for filter chips updates
86+ * @param event The update event
87+ * @private
88+ */
89+ function onFilterUpdateChips ( event : FilterUpdateChipsEvent ) {
90+ const id = ( event . target as IFileListFilter ) . id
91+ chips . value = {
92+ ...chips . value ,
93+ [ id ] : [ ...event . detail ] ,
94+ }
95+
96+ logger . debug ( 'File list filter chips updated' , { filter : id , chips : event . detail } )
97+ }
98+
99+ /**
100+ * Event handler that resets all filters if the file list view was changed.
101+ * @private
102+ */
103+ function onViewChanged ( ) {
104+ logger . debug ( 'Reset all file list filters - view changed' )
105+
106+ for ( const filter of filters . value ) {
107+ if ( filter . reset !== undefined ) {
108+ filter . reset ( )
77109 }
78- } ,
79- } ,
110+ }
111+ }
112+
113+ // Initialize the store
114+ {
115+ subscribe ( 'files:filter:added' , addFilter )
116+ subscribe ( 'files:filter:removed' , removeFilter )
117+ for ( const filter of getFileListFilters ( ) ) {
118+ addFilter ( filter )
119+ }
120+
121+ subscribe ( 'files:navigation:changed' , onViewChanged )
122+ }
123+
124+ return {
125+ // state
126+ chips,
127+ filters,
128+ filtersWithUI,
129+ filtersChanged,
130+
131+ // getters / computed
132+ activeChips,
133+ sortedFilters,
134+
135+ // actions / methods
136+ addFilter,
137+ removeFilter,
138+ }
80139} )
0 commit comments