Skip to content

Commit caa53c8

Browse files
authored
perf: scope filter animation to mutation site, cache per-table filters (#531)
1 parent 1496264 commit caa53c8

3 files changed

Lines changed: 22 additions & 6 deletions

File tree

TablePro/Core/Storage/FilterSettingsStorage.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ final class FilterSettingsStorage {
9696
/// Cached settings to avoid repeated UserDefaults read + JSON decode
9797
private var cachedSettings: FilterSettings?
9898

99+
/// Per-table filter cache to avoid JSON decode on every table switch
100+
private var lastFiltersCache: [String: [TableFilter]] = [:]
101+
99102
/// In-memory cache for tracked filter keys. Lazy-loaded on first access
100103
/// so that `trackKey`/`removeTrackedKey` avoid redundant UserDefaults reads.
101104
private var _trackedKeys: Set<String>?
@@ -160,12 +163,18 @@ final class FilterSettingsStorage {
160163
func loadLastFilters(for tableName: String) -> [TableFilter] {
161164
let key = lastFiltersKeyPrefix + sanitizeTableName(tableName)
162165

166+
if let cached = lastFiltersCache[key] {
167+
return cached
168+
}
169+
163170
guard let data = defaults.data(forKey: key) else {
164171
return []
165172
}
166173

167174
do {
168-
return try decoder.decode([TableFilter].self, from: data)
175+
let filters = try decoder.decode([TableFilter].self, from: data)
176+
lastFiltersCache[key] = filters
177+
return filters
169178
} catch {
170179
Self.logger.error("Failed to decode last filters for \(tableName): \(error)")
171180
return []
@@ -180,13 +189,15 @@ final class FilterSettingsStorage {
180189
guard !filters.isEmpty else {
181190
defaults.removeObject(forKey: key)
182191
removeTrackedKey(key)
192+
lastFiltersCache.removeValue(forKey: key)
183193
return
184194
}
185195

186196
do {
187197
let data = try encoder.encode(filters)
188198
defaults.set(data, forKey: key)
189199
trackKey(key)
200+
lastFiltersCache[key] = filters
190201
} catch {
191202
Self.logger.error("Failed to encode last filters for \(tableName): \(error)")
192203
}
@@ -197,6 +208,7 @@ final class FilterSettingsStorage {
197208
let key = lastFiltersKeyPrefix + sanitizeTableName(tableName)
198209
defaults.removeObject(forKey: key)
199210
removeTrackedKey(key)
211+
lastFiltersCache.removeValue(forKey: key)
200212
}
201213

202214
/// Clear all stored last filters using the tracked key set instead of

TablePro/Models/UI/FilterState.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,17 +171,23 @@ final class FilterStateManager {
171171

172172
/// Toggle filter panel visibility
173173
func toggle() {
174-
isVisible.toggle()
174+
withAnimation(.easeInOut(duration: 0.15)) {
175+
isVisible.toggle()
176+
}
175177
}
176178

177179
/// Show panel
178180
func show() {
179-
isVisible = true
181+
withAnimation(.easeInOut(duration: 0.15)) {
182+
isVisible = true
183+
}
180184
}
181185

182186
/// Close panel
183187
func close() {
184-
isVisible = false
188+
withAnimation(.easeInOut(duration: 0.15)) {
189+
isVisible = false
190+
}
185191
}
186192

187193
// MARK: - Selection

TablePro/Views/Main/Child/MainEditorContentView.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,6 @@ struct MainEditorContentView: View {
369369
statusBar(tab: tab)
370370
}
371371
.frame(maxWidth: .infinity, maxHeight: .infinity)
372-
.animation(.easeInOut(duration: 0.2), value: filterStateManager.isVisible)
373-
.animation(.easeInOut(duration: 0.2), value: tab.errorMessage)
374372
}
375373

376374
private func resultTabBar(tab: QueryTab) -> some View {

0 commit comments

Comments
 (0)