diff --git a/plugins/data-management/src/HierarchicalTrackSelectorWidget/model.ts b/plugins/data-management/src/HierarchicalTrackSelectorWidget/model.ts index 2b47732b30..0d18c5a843 100644 --- a/plugins/data-management/src/HierarchicalTrackSelectorWidget/model.ts +++ b/plugins/data-management/src/HierarchicalTrackSelectorWidget/model.ts @@ -40,8 +40,7 @@ function postF() { : 'empty' } -const lsKeyFavoritesF = () => `favoriteTracks-${postF()}}` -const lsKeyRecentlyUsedF = () => `recentlyUsedTracks-${postF()}}` +const MAX_RECENTLY_USED = 10 /** * #stateModel HierarchicalTrackSelectorWidget @@ -79,29 +78,14 @@ export default function stateTreeFactory(pluginManager: PluginManager) { view: types.safeReference( pluginManager.pluggableMstType('view', 'stateModel'), ), - /** - * #property - * this is removed in postProcessSnapshot, so is generally only loaded - * from localstorage - */ - favorites: types.optional(types.array(types.string), () => - JSON.parse(localStorageGetItem(lsKeyFavoritesF()) || '[]'), - ), - /** - * #property - * this is removed in postProcessSnapshot, so is generally only loaded - * from localstorage - */ - recentlyUsed: types.optional(types.array(types.string), () => - JSON.parse(localStorageGetItem(lsKeyRecentlyUsedF()) || '[]'), - ), - /** * #property */ faceted: types.optional(facetedStateTreeF(), {}), }) .volatile(() => ({ + favorites: [] as string[], + recentlyUsed: [] as string[], selection: [] as AnyConfigurationModel[], filterText: '', recentlyUsedCounter: 0, @@ -177,13 +161,13 @@ export default function stateTreeFactory(pluginManager: PluginManager) { * #action */ removeFromFavorites(trackId: string) { - self.favorites.remove(trackId) + self.favorites = self.favorites.filter(f => f !== trackId) }, /** * #action */ clearFavorites() { - self.favorites.clear() + self.favorites = [] }, /** @@ -192,6 +176,18 @@ export default function stateTreeFactory(pluginManager: PluginManager) { setRecentlyUsedCounter(val: number) { self.recentlyUsedCounter = val }, + /** + * #action + */ + setRecentlyUsed(str: string[]) { + self.recentlyUsed = str + }, + /** + * #action + */ + setFavorites(str: string[]) { + self.favorites = str + }, /** * #action */ @@ -202,20 +198,22 @@ export default function stateTreeFactory(pluginManager: PluginManager) { * #action */ addToRecentlyUsed(id: string) { - self.recentlyUsedCounter += 1 if (!self.recentlyUsed.includes(id)) { - if (self.recentlyUsed.length >= 10) { - self.recentlyUsed.shift() - } - self.recentlyUsed.push(id) + self.recentlyUsedCounter = Math.min( + self.recentlyUsedCounter + 1, + MAX_RECENTLY_USED, + ) + self.recentlyUsed = + self.recentlyUsed.length >= MAX_RECENTLY_USED + ? [...self.recentlyUsed.slice(1), id] + : [...self.recentlyUsed, id] } }, - /** * #action */ clearRecentlyUsed() { - self.recentlyUsed.clear() + self.recentlyUsed = [] }, /** * #action @@ -241,7 +239,6 @@ export default function stateTreeFactory(pluginManager: PluginManager) { expandAllCategories() { self.collapsed.clear() }, - /** * #action */ @@ -302,6 +299,22 @@ export default function stateTreeFactory(pluginManager: PluginManager) { }, })) .views(self => ({ + /** + * #getter + */ + get recentlyUsedLocalStorageKey() { + return `recentlyUsedTracks-${[postF(), self.assemblyNames.join(',')] + .filter(f => !!f) + .join('-')}` + }, + /** + * #getter + */ + get favoritesLocalStorageKey() { + // this has a extra } at the end because that's how it was initially + // released + return `favoriteTracks-${postF()}}` + }, /** * #getter */ @@ -331,7 +344,9 @@ export default function stateTreeFactory(pluginManager: PluginManager) { ...filterTracks(getSession(self).tracks, self), ].filter(notEmpty) }, - + /** + * #getter + */ get allTrackConfigurations() { const { connectionInstances = [] } = getSession(self) return [ @@ -339,6 +354,13 @@ export default function stateTreeFactory(pluginManager: PluginManager) { ...connectionInstances?.flatMap(c => c.tracks), ] }, + + /** + * #getter + */ + get allTrackConfigurationTrackIdSet() { + return new Map(this.allTrackConfigurations.map(t => [t.trackId, t])) + }, })) .views(self => ({ /** @@ -346,9 +368,9 @@ export default function stateTreeFactory(pluginManager: PluginManager) { * filters out tracks that are not in the favorites group */ get favoriteTracks() { - return self.allTrackConfigurations.filter(t => - self.favoritesSet.has(t.trackId), - ) + return self.favorites + .filter(t => self.allTrackConfigurationTrackIdSet.has(t)) + .map(t => self.allTrackConfigurationTrackIdSet.get(t)!) }, /** @@ -356,9 +378,9 @@ export default function stateTreeFactory(pluginManager: PluginManager) { * filters out tracks that are not in the recently used group */ get recentlyUsedTracks() { - return self.allTrackConfigurations.filter(t => - self.recentlyUsedSet.has(t.trackId), - ) + return self.recentlyUsed + .filter(t => self.allTrackConfigurationTrackIdSet.has(t)) + .map(t => self.allTrackConfigurationTrackIdSet.get(t)!) }, })) .views(self => ({ @@ -480,29 +502,40 @@ export default function stateTreeFactory(pluginManager: PluginManager) { })) .actions(self => ({ afterAttach() { + // this should be the first autorun to properly initialize addDisposer( self, autorun(() => { - localStorageSetItem( - lsKeyFavoritesF(), - JSON.stringify(self.favorites), + self.setRecentlyUsed( + JSON.parse( + localStorageGetItem(self.recentlyUsedLocalStorageKey) || '[]', + ), + ) + self.setFavorites( + JSON.parse( + localStorageGetItem(self.favoritesLocalStorageKey) || '[]', + ), ) + }), + ) + // this should be the second autorun + addDisposer( + self, + autorun(() => { localStorageSetItem( - lsKeyRecentlyUsedF(), - JSON.stringify(self.recentlyUsed), + self.favoritesLocalStorageKey, + JSON.stringify(self.favorites), ) + if (self.recentlyUsed) { + localStorageSetItem( + self.recentlyUsedLocalStorageKey, + JSON.stringify(self.recentlyUsed), + ) + } }), ) }, })) - .postProcessSnapshot(snap => { - const { - favorites: _, - recentlyUsed: __, - ...rest - } = snap as Omit - return rest - }) } export type HierarchicalTrackSelectorStateModel = ReturnType<