diff --git a/packages/frontend-2/lib/viewer/composables/filtering/filtering.ts b/packages/frontend-2/lib/viewer/composables/filtering/filtering.ts index 89555b1c5..b0c91b0e8 100644 --- a/packages/frontend-2/lib/viewer/composables/filtering/filtering.ts +++ b/packages/frontend-2/lib/viewer/composables/filtering/filtering.ts @@ -4,6 +4,7 @@ import type { StringPropertyInfo } from '@speckle/viewer' import { difference, uniq, partition } from 'lodash-es' +import { whenever } from '@vueuse/core' import { useInjectedViewerState, type InjectableViewerState @@ -597,6 +598,15 @@ export function useFilterUtilities( explodeFactor.value = 0 } + // Store filters that need to be restored once data store is ready + const pendingFiltersToRestore = ref | null>(null) + /** * Restores filters from serialized state */ @@ -615,6 +625,28 @@ export function useFilterUtilities( const availableProperties = getPropertyOptionsFromDataStore() + // If data store is ready, restore immediately + if (availableProperties.length > 0) { + applyFiltersFromSerialized(serializedFilters, availableProperties) + } else { + // Store filters to restore later when data store is ready + pendingFiltersToRestore.value = serializedFilters + } + } + + /** + * Actually applies the filters once we have the property data + */ + const applyFiltersFromSerialized = ( + serializedFilters: Array<{ + key: string | null + isApplied: boolean + selectedValues: string[] + id: string + condition: 'AND' | 'OR' + }>, + availableProperties: PropertyInfo[] + ) => { for (const serializedFilter of serializedFilters) { if (serializedFilter.key) { const propertyInfo = availableProperties.find( @@ -731,6 +763,19 @@ export function useFilterUtilities( } } + // Watch for data store to become ready and restore pending filters + const shouldRestoreFilters = computed(() => { + return pendingFiltersToRestore.value && getPropertyOptionsFromDataStore().length > 0 + }) + + whenever(shouldRestoreFilters, () => { + if (pendingFiltersToRestore.value) { + const availableProperties = getPropertyOptionsFromDataStore() + applyFiltersFromSerialized(pendingFiltersToRestore.value, availableProperties) + pendingFiltersToRestore.value = null + } + }) + return { isolateObjects, unIsolateObjects, diff --git a/packages/frontend-2/lib/viewer/composables/serialization.ts b/packages/frontend-2/lib/viewer/composables/serialization.ts index 074a37ec3..72db60740 100644 --- a/packages/frontend-2/lib/viewer/composables/serialization.ts +++ b/packages/frontend-2/lib/viewer/composables/serialization.ts @@ -114,6 +114,18 @@ export function useStateSerialization() { : ('OR' as const) })) + // Create legacy-compatible propertyFilter from first item in propertyFilters + const propertyFilter = + propertyFilters.length > 0 + ? { + key: propertyFilters[0].key, + isApplied: propertyFilters[0].isApplied + } + : { + key: null, + isApplied: false + } + return { isolatedObjectIds: state.ui.filters.isolatedObjectIds.value, hiddenObjectIds: state.ui.filters.hiddenObjectIds.value, @@ -121,6 +133,7 @@ export function useStateSerialization() { ret[obj.id] = obj.applicationId ?? null return ret }, {} as Record), + propertyFilter, // ← Preserve legacy format for backwards compatibility propertyFilters } })(),