Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion TablePro/Core/Storage/FilterSettingsStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ final class FilterSettingsStorage {
/// Cached settings to avoid repeated UserDefaults read + JSON decode
private var cachedSettings: FilterSettings?

/// Per-table filter cache to avoid JSON decode on every table switch
private var lastFiltersCache: [String: [TableFilter]] = [:]

/// In-memory cache for tracked filter keys. Lazy-loaded on first access
/// so that `trackKey`/`removeTrackedKey` avoid redundant UserDefaults reads.
private var _trackedKeys: Set<String>?
Expand Down Expand Up @@ -160,12 +163,18 @@ final class FilterSettingsStorage {
func loadLastFilters(for tableName: String) -> [TableFilter] {
let key = lastFiltersKeyPrefix + sanitizeTableName(tableName)

if let cached = lastFiltersCache[key] {
return cached
}

guard let data = defaults.data(forKey: key) else {
return []
}

do {
return try decoder.decode([TableFilter].self, from: data)
let filters = try decoder.decode([TableFilter].self, from: data)
lastFiltersCache[key] = filters
return filters
} catch {
Self.logger.error("Failed to decode last filters for \(tableName): \(error)")
return []
Expand All @@ -180,13 +189,15 @@ final class FilterSettingsStorage {
guard !filters.isEmpty else {
defaults.removeObject(forKey: key)
removeTrackedKey(key)
lastFiltersCache.removeValue(forKey: key)
return
}

do {
let data = try encoder.encode(filters)
defaults.set(data, forKey: key)
trackKey(key)
lastFiltersCache[key] = filters
} catch {
Self.logger.error("Failed to encode last filters for \(tableName): \(error)")
}
Expand All @@ -197,6 +208,7 @@ final class FilterSettingsStorage {
let key = lastFiltersKeyPrefix + sanitizeTableName(tableName)
defaults.removeObject(forKey: key)
removeTrackedKey(key)
lastFiltersCache.removeValue(forKey: key)
}

/// Clear all stored last filters using the tracked key set instead of
Expand Down
12 changes: 9 additions & 3 deletions TablePro/Models/UI/FilterState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,23 @@ final class FilterStateManager {

/// Toggle filter panel visibility
func toggle() {
isVisible.toggle()
withAnimation(.easeInOut(duration: 0.15)) {
isVisible.toggle()
}
}

/// Show panel
func show() {
isVisible = true
withAnimation(.easeInOut(duration: 0.15)) {
isVisible = true
}
}

/// Close panel
func close() {
isVisible = false
withAnimation(.easeInOut(duration: 0.15)) {
isVisible = false
}
}

// MARK: - Selection
Expand Down
2 changes: 0 additions & 2 deletions TablePro/Views/Main/Child/MainEditorContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,6 @@ struct MainEditorContentView: View {
statusBar(tab: tab)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.animation(.easeInOut(duration: 0.2), value: filterStateManager.isVisible)
.animation(.easeInOut(duration: 0.2), value: tab.errorMessage)
}

private func resultTabBar(tab: QueryTab) -> some View {
Expand Down
Loading