From 3dd520fda8da93a93eefc123f59d3c02fe6d4217 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Sat, 11 Apr 2026 17:16:13 +0700 Subject: [PATCH 1/2] fix: remove "Recently Opened Databases" from database switcher (#671) Remove the RECENT section from the database switcher sheet. The feature auto-selected recent databases by default, interfering with keyboard navigation. The flat alphabetical list is cleaner and more predictable. - Delete UserDefaults+RecentDatabases.swift - Remove recentDatabases, recentDatabaseMetadata, allDatabases, trackAccess from ViewModel - Replace RECENT + ALL sections with single flat filteredDatabases list --- .../UserDefaults+RecentDatabases.swift | 54 ------------------- .../DatabaseSwitcherViewModel.swift | 19 ------- .../DatabaseSwitcherSheet.swift | 37 ++----------- 3 files changed, 3 insertions(+), 107 deletions(-) delete mode 100644 TablePro/Extensions/UserDefaults+RecentDatabases.swift diff --git a/TablePro/Extensions/UserDefaults+RecentDatabases.swift b/TablePro/Extensions/UserDefaults+RecentDatabases.swift deleted file mode 100644 index 9eaeeb1ad..000000000 --- a/TablePro/Extensions/UserDefaults+RecentDatabases.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// UserDefaults+RecentDatabases.swift -// TablePro -// -// UserDefaults extension for tracking recently accessed databases per connection. -// - -import Foundation - -extension UserDefaults { - private static let recentDatabasesKey = "recentDatabases" - private static let maxRecentCount = 5 - - /// Get recent databases for a specific connection - /// - Parameter connectionId: The connection UUID - /// - Returns: Array of recently accessed database names (max 5, ordered by recency) - func recentDatabases(for connectionId: UUID) -> [String] { - guard let dict = dictionary(forKey: Self.recentDatabasesKey) as? [String: [String]] else { - return [] - } - return dict[connectionId.uuidString] ?? [] - } - - /// Track database access for a connection - /// - Parameters: - /// - database: Database name to track - /// - connectionId: The connection UUID - func trackDatabaseAccess(_ database: String, for connectionId: UUID) { - var dict = (dictionary(forKey: Self.recentDatabasesKey) as? [String: [String]]) ?? [:] - var recent = dict[connectionId.uuidString] ?? [] - - // Remove if already exists (will be added to front) - recent.removeAll { $0 == database } - - // Add to front - recent.insert(database, at: 0) - - // Keep only max count - if recent.count > Self.maxRecentCount { - recent = Array(recent.prefix(Self.maxRecentCount)) - } - - dict[connectionId.uuidString] = recent - set(dict, forKey: Self.recentDatabasesKey) - } - - /// Clear recent databases for a connection - /// - Parameter connectionId: The connection UUID - func clearRecentDatabases(for connectionId: UUID) { - var dict = (dictionary(forKey: Self.recentDatabasesKey) as? [String: [String]]) ?? [:] - dict.removeValue(forKey: connectionId.uuidString) - set(dict, forKey: Self.recentDatabasesKey) - } -} diff --git a/TablePro/ViewModels/DatabaseSwitcherViewModel.swift b/TablePro/ViewModels/DatabaseSwitcherViewModel.swift index 3d87267db..b66a66283 100644 --- a/TablePro/ViewModels/DatabaseSwitcherViewModel.swift +++ b/TablePro/ViewModels/DatabaseSwitcherViewModel.swift @@ -25,7 +25,6 @@ final class DatabaseSwitcherViewModel { // MARK: - Published State var databases: [DatabaseMetadata] = [] - var recentDatabases: [String] = [] var searchText = "" var selectedDatabase: String? var isLoading = false @@ -54,18 +53,6 @@ final class DatabaseSwitcherViewModel { } } - var recentDatabaseMetadata: [DatabaseMetadata] { - recentDatabases.compactMap { dbName in - databases.first { $0.name == dbName } - } - } - - var allDatabases: [DatabaseMetadata] { - // Filter out recent databases from "all" list - filteredDatabases.filter { db in - !recentDatabases.contains(db.name) - } - } // MARK: - Initialization @@ -78,7 +65,6 @@ final class DatabaseSwitcherViewModel { self.currentSchema = currentSchema self.databaseType = databaseType self.mode = PluginManager.shared.supportsSchemaSwitching(for: databaseType) ? .schema : .database - self.recentDatabases = UserDefaults.standard.recentDatabases(for: connectionId) } // MARK: - Public Methods @@ -152,11 +138,6 @@ final class DatabaseSwitcherViewModel { try await driver.createDatabase(name: name, charset: charset, collation: collation) } - /// Track database access - func trackAccess(database: String) { - UserDefaults.standard.trackDatabaseAccess(database, for: connectionId) - recentDatabases = UserDefaults.standard.recentDatabases(for: connectionId) - } // MARK: - Private Methods diff --git a/TablePro/Views/DatabaseSwitcher/DatabaseSwitcherSheet.swift b/TablePro/Views/DatabaseSwitcher/DatabaseSwitcherSheet.swift index da7c11bff..89f4b15d3 100644 --- a/TablePro/Views/DatabaseSwitcher/DatabaseSwitcherSheet.swift +++ b/TablePro/Views/DatabaseSwitcher/DatabaseSwitcherSheet.swift @@ -192,36 +192,8 @@ struct DatabaseSwitcherSheet: View { private var databaseList: some View { ScrollViewReader { proxy in List(selection: $viewModel.selectedDatabase) { - // Recent section - if !viewModel.recentDatabaseMetadata.isEmpty { - Section { - ForEach(viewModel.recentDatabaseMetadata) { db in - databaseRow(db) - } - } header: { - Text("RECENT") - .font( - .system(size: ThemeEngine.shared.activeTheme.typography.caption, weight: .semibold) - ) - .foregroundStyle(.secondary) - } - } - - // All databases - Section { - ForEach(viewModel.allDatabases) { db in - databaseRow(db) - } - } header: { - if !viewModel.recentDatabaseMetadata.isEmpty { - Text(isSchemaMode - ? String(localized: "ALL SCHEMAS") - : String(localized: "ALL DATABASES")) - .font( - .system(size: ThemeEngine.shared.activeTheme.typography.caption, weight: .semibold) - ) - .foregroundStyle(.secondary) - } + ForEach(viewModel.filteredDatabases) { db in + databaseRow(db) } } .listStyle(.sidebar) @@ -403,7 +375,7 @@ struct DatabaseSwitcherSheet: View { // MARK: - Actions private func moveSelection(up: Bool) { - let allDbs = viewModel.recentDatabaseMetadata + viewModel.allDatabases + let allDbs = viewModel.filteredDatabases guard !allDbs.isEmpty else { return } // Defer state update to avoid "Publishing changes from within view updates" warning @@ -433,9 +405,6 @@ struct DatabaseSwitcherSheet: View { return } - // Track access - viewModel.trackAccess(database: database) - // Call appropriate callback if viewModel.isSchemaMode, PluginManager.shared.supportsSchemaSwitching(for: databaseType), let onSelectSchema { onSelectSchema(database) From c56af027ab79eba45fdb51603f0d7420ddd8a2f6 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Sat, 11 Apr 2026 17:23:25 +0700 Subject: [PATCH 2/2] style: remove extra blank lines --- TablePro/ViewModels/DatabaseSwitcherViewModel.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/TablePro/ViewModels/DatabaseSwitcherViewModel.swift b/TablePro/ViewModels/DatabaseSwitcherViewModel.swift index b66a66283..bc8ea7fa3 100644 --- a/TablePro/ViewModels/DatabaseSwitcherViewModel.swift +++ b/TablePro/ViewModels/DatabaseSwitcherViewModel.swift @@ -53,7 +53,6 @@ final class DatabaseSwitcherViewModel { } } - // MARK: - Initialization init( @@ -138,7 +137,6 @@ final class DatabaseSwitcherViewModel { try await driver.createDatabase(name: name, charset: charset, collation: collation) } - // MARK: - Private Methods private func preselectDatabase() {