From 851e8987e4492dbb0ce31cbb3ebc09b6629b463a Mon Sep 17 00:00:00 2001 From: drull Date: Wed, 3 Jan 2024 15:42:35 -0300 Subject: [PATCH 1/9] New table for unique app names --- rem/DB.swift | 63 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/rem/DB.swift b/rem/DB.swift index 585fd0a..2533230 100644 --- a/rem/DB.swift +++ b/rem/DB.swift @@ -26,6 +26,8 @@ class DatabaseManager { private let videoChunks = Table("video_chunks") private let frames = Table("frames") + private let uniqueAppNames = Table("unique_application_names") + let allText = VirtualTable("allText") private let id = Expression("id") @@ -59,6 +61,7 @@ class DatabaseManager { try db.run(videoChunks.drop(ifExists: true)) try db.run(frames.drop(ifExists: true)) try db.run(allText.drop(ifExists: true)) + try db.run(uniqueAppNames.drop(ifExists: true)) } catch { print("Failed to delete tables") } @@ -83,6 +86,11 @@ class DatabaseManager { t.column(activeApplicationName) }) + try! db.run(uniqueAppNames.create(ifNotExists: true) { t in + t.column(id, primaryKey: .autoincrement) + t.column(activeApplicationName, unique: true) + }) + let config = FTS4Config() .column(frameId, [.unindexed]) .column(text) @@ -137,14 +145,42 @@ class DatabaseManager { } func insertFrame(activeApplicationName: String?) -> Int64 { - // logger.debug("inserting frame: \(self.lastFrameId + 1) at offset: \(self.currentFrameOffset)") let insert = frames.insert(chunkId <- currentChunkId, timestamp <- Date(), offsetIndex <- currentFrameOffset, self.activeApplicationName <- activeApplicationName) let id = try! db.run(insert) currentFrameOffset += 1 lastFrameId = id + + if let appName = activeApplicationName { + //will check if the app name is already in the database. + insertUniqueApplicationNamesIfNeeded(appName) + } + return id } + private func insertUniqueApplicationNamesIfNeeded(_ appName: String) { + let query = uniqueAppNames.filter(activeApplicationName == appName) + + do { + let count = try db.scalar(query.count) + if count == 0 { + print("insert") + insertUniqueApplicationNames(appName) + } + } catch { + print("Error checking existence of app name: \(error)") + } + } + + func insertUniqueApplicationNames(_ appName: String) { + let insert = uniqueAppNames.insert(activeApplicationName <- appName) + do { + try db.run(insert) + } catch { + print("Error inserting unique application name: \(error)") + } + } + func insertTextForFrame(frameId: Int64, text: String) { let insert = allText.insert(self.frameId <- frameId, self.text <- text) try! db.run(insert) @@ -292,23 +328,22 @@ class DatabaseManager { } func getAllApplicationNames() -> [String] { - var applicationNames: [String] = [] - - do { - let distinctAppsQuery = frames.select(distinct: activeApplicationName) - for row in try db.prepare(distinctAppsQuery) { - if let appName = row[activeApplicationName] { - applicationNames.append(appName) - } + var applicationNames: [String] = [] + + do { + let distinctAppsQuery = uniqueAppNames.select(activeApplicationName) + for row in try db.prepare(distinctAppsQuery) { + if let appName = row[activeApplicationName] { + applicationNames.append(appName) } - } catch { - print("Error fetching application names: \(error)") } - - return applicationNames + } catch { + print("Error fetching application names: \(error)") } - + return applicationNames + } + func getImage(index: Int64, maxSize: CGSize? = nil) -> CGImage? { guard let frameData = DatabaseManager.shared.getFrame(forIndex: index) else { return nil } From d5329aeffb60b5954c351254cfe0e6fb97e8a2a6 Mon Sep 17 00:00:00 2001 From: drull Date: Wed, 3 Jan 2024 15:43:14 -0300 Subject: [PATCH 2/9] Add state wrapper --- rem/Search.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rem/Search.swift b/rem/Search.swift index 4db24c1..a2c60b7 100644 --- a/rem/Search.swift +++ b/rem/Search.swift @@ -30,7 +30,7 @@ struct SearchBar: View { @Namespace var nspace @FocusState var focused: Bool? var debounceSearch = Debouncer(delay: 0.3) - var applicationNameFilter: [String] + @State var applicationNameFilter: [String] @Binding var selectedFilterAppIndex: Int @Binding var selectedFilterApp: String From a70cbb56b81b71b0722afa439d42eb873e85e137 Mon Sep 17 00:00:00 2001 From: drull Date: Thu, 4 Jan 2024 10:48:03 -0300 Subject: [PATCH 3/9] Renaming variable & updateFilterApp function --- rem/Search.swift | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/rem/Search.swift b/rem/Search.swift index a2c60b7..47204a3 100644 --- a/rem/Search.swift +++ b/rem/Search.swift @@ -30,9 +30,9 @@ struct SearchBar: View { @Namespace var nspace @FocusState var focused: Bool? var debounceSearch = Debouncer(delay: 0.3) - @State var applicationNameFilter: [String] @Binding var selectedFilterAppIndex: Int @Binding var selectedFilterApp: String + @State private var applicationFilterArray: [String] = [] var body: some View { HStack { @@ -73,7 +73,7 @@ struct SearchBar: View { .padding(.horizontal, 10) FilterPicker( - applicationNameFilter: applicationNameFilter, + applicationFilterArray: applicationFilterArray, selectedFilterAppIndex: $selectedFilterAppIndex, selectedFilterApp: $selectedFilterApp, debounceSearch: debounceSearch, @@ -84,7 +84,7 @@ struct SearchBar: View { } struct FilterPicker: View { - var applicationNameFilter: [String] + @State var applicationFilterArray: [String] @Binding var selectedFilterAppIndex: Int @Binding var selectedFilterApp: String var debounceSearch: Debouncer @@ -92,21 +92,30 @@ struct FilterPicker: View { var body: some View { Picker("Select App", selection: $selectedFilterAppIndex) { - ForEach(applicationNameFilter.indices, id: \.self) { index in - Text(applicationNameFilter[index]) + ForEach(applicationFilterArray.indices, id: \.self) { index in + Text(applicationFilterArray[index]) .tag(index) } } + .onHover(perform: { hovering in + updateAppFilterData() + }) .pickerStyle(.menu) .onChange(of: selectedFilterAppIndex) { newIndex in - guard newIndex >= 0 && newIndex < applicationNameFilter.count else { + guard newIndex >= 0 && newIndex < applicationFilterArray.count else { return } - selectedFilterApp = applicationNameFilter[selectedFilterAppIndex] + selectedFilterApp = applicationFilterArray[selectedFilterAppIndex] onSearch() } .frame(width: 200) } + private func updateAppFilterData() { + var appFilters = ["All apps"] + let allAppNames = DatabaseManager.shared.getAllApplicationNames() + appFilters.append(contentsOf: allAppNames) + applicationFilterArray = appFilters + } } @@ -304,7 +313,6 @@ struct ResultsView: View { SearchBar( text: $searchText, onSearch: performSearch, - applicationNameFilter: getAppFilterData(), selectedFilterAppIndex: $selectedFilterAppIndex, selectedFilterApp: $selectedFilterApp ) @@ -369,13 +377,6 @@ struct ResultsView: View { } } - private func getAppFilterData() -> [String] { - var appFilters = ["All apps"] - let allAppNames = DatabaseManager.shared.getAllApplicationNames() - appFilters.append(contentsOf: allAppNames) - return appFilters - } - private func mapResultsToSearchResult(_ data: [(frameId: Int64, fullText: String?, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)]) -> [SearchResult] { let searchResults = data.map { item in SearchResult(frameId: item.frameId, applicationName: item.applicationName, fullText: item.fullText?.split(separator: "\n").joined(separator: " "), searchText: searchText, timestamp: item.timestamp) From e28f3bacf45c456f0ee26382edd4d089b209ba76 Mon Sep 17 00:00:00 2001 From: drull Date: Thu, 4 Jan 2024 11:27:44 -0300 Subject: [PATCH 4/9] Optimizing search function --- rem/DB.swift | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ rem/Search.swift | 25 ++++++++++++------------ 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/rem/DB.swift b/rem/DB.swift index 2533230..78e5467 100644 --- a/rem/DB.swift +++ b/rem/DB.swift @@ -303,6 +303,55 @@ class DatabaseManager { } return results } + func searchFilteredByAppName(appName: String, limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { + let query = frames + .join(videoChunks, on: frames[chunkId] == videoChunks[id]) + .filter(frames[activeApplicationName].lowercaseString == appName.lowercased()) // Apply filter by application name + .select(frames[id], frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) + .limit(limit, offset: offset) + + var results: [(Int64, String, String?, Date, String, Int64)] = [] + do { + for row in try db.prepare(query) { + let frameId = row[frames[id]] + let applicationName = row[frames[activeApplicationName]] + let timestamp = row[frames[timestamp]] + let filePath = row[videoChunks[filePath]] + let offsetIndex = row[frames[offsetIndex]] + results.append((frameId, "", applicationName, timestamp, filePath, offsetIndex)) + } + } catch { + print("Search error: \(error)") + } + return results + } + + func searchFilteredByAppNameAndText(appName: String, searchText: String, limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { + let query = allText + .join(frames, on: frames[id] == allText[frameId]) + .join(videoChunks, on: frames[chunkId] == videoChunks[id]) + .filter(text.match("*\(searchText)*") && frames[activeApplicationName].lowercaseString == appName.lowercased()) // Apply filter by application name and search text + .select(allText[frameId], text, frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) + .limit(limit, offset: offset) + + var results: [(Int64, String, String?, Date, String, Int64)] = [] + do { + for row in try db.prepare(query) { + let frameId = row[allText[frameId]] + let matchedText = row[text] + let applicationName = row[frames[activeApplicationName]] + let timestamp = row[frames[timestamp]] + let filePath = row[videoChunks[filePath]] + let offsetIndex = row[frames[offsetIndex]] + results.append((frameId, matchedText, applicationName, timestamp, filePath, offsetIndex)) + } + } catch { + print("Search error: \(error)") + } + return results + } + + func getRecentResults(limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String?, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { let query = frames diff --git a/rem/Search.swift b/rem/Search.swift index 47204a3..613580f 100644 --- a/rem/Search.swift +++ b/rem/Search.swift @@ -358,24 +358,23 @@ struct ResultsView: View { private func getSearchResults() -> [SearchResult] { var results: [(frameId: Int64, fullText: String?, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] = [] - if searchText.isEmpty { - results = DatabaseManager.shared.getRecentResults(limit: limit, offset: offset) - } else { - results = DatabaseManager.shared.search(searchText: searchText, limit: limit, offset: offset) - } - if selectedFilterAppIndex == 0 { - return mapResultsToSearchResult(results) + if searchText.isEmpty { + results = DatabaseManager.shared.getRecentResults(limit: limit, offset: offset) + } else { + results = DatabaseManager.shared.search(searchText: searchText, limit: limit, offset: offset) + } } else { - let filteredResults = results.filter { result in - if let appName = result.applicationName { - return appName.lowercased() == selectedFilterApp.lowercased() - } - return false + if searchText.isEmpty { + results = DatabaseManager.shared.searchFilteredByAppName(appName: selectedFilterApp, limit: limit, offset: offset) + } else { + results = DatabaseManager.shared.searchFilteredByAppNameAndText(appName: selectedFilterApp, searchText: searchText, limit: limit, offset: offset) } - return mapResultsToSearchResult(filteredResults) } + + return mapResultsToSearchResult(results) } + private func mapResultsToSearchResult(_ data: [(frameId: Int64, fullText: String?, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)]) -> [SearchResult] { let searchResults = data.map { item in From 800a6194f3fb2a218400e74d57cbe1027b2713d3 Mon Sep 17 00:00:00 2001 From: drull Date: Thu, 4 Jan 2024 11:55:27 -0300 Subject: [PATCH 5/9] Using the new table in the queries --- rem/DB.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rem/DB.swift b/rem/DB.swift index 78e5467..0f3259f 100644 --- a/rem/DB.swift +++ b/rem/DB.swift @@ -303,10 +303,12 @@ class DatabaseManager { } return results } + func searchFilteredByAppName(appName: String, limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { let query = frames .join(videoChunks, on: frames[chunkId] == videoChunks[id]) - .filter(frames[activeApplicationName].lowercaseString == appName.lowercased()) // Apply filter by application name + .join(uniqueAppNames, on: uniqueAppNames[activeApplicationName] == frames[activeApplicationName]) + .filter(uniqueAppNames[activeApplicationName].lowercaseString == appName.lowercased()) .select(frames[id], frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) .limit(limit, offset: offset) @@ -330,7 +332,8 @@ class DatabaseManager { let query = allText .join(frames, on: frames[id] == allText[frameId]) .join(videoChunks, on: frames[chunkId] == videoChunks[id]) - .filter(text.match("*\(searchText)*") && frames[activeApplicationName].lowercaseString == appName.lowercased()) // Apply filter by application name and search text + .join(uniqueAppNames, on: uniqueAppNames[activeApplicationName] == frames[activeApplicationName]) + .filter(text.match("*\(searchText)*") && uniqueAppNames[activeApplicationName].lowercaseString == appName.lowercased()) .select(allText[frameId], text, frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) .limit(limit, offset: offset) @@ -351,7 +354,6 @@ class DatabaseManager { return results } - func getRecentResults(limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String?, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { let query = frames From f85445c5ef6d15b7f1a2dd22ea72425800169b57 Mon Sep 17 00:00:00 2001 From: drull Date: Thu, 4 Jan 2024 21:08:14 -0300 Subject: [PATCH 6/9] Merging search functions --- rem/DB.swift | 70 +++++++++++------------------------------------- rem/Search.swift | 5 ++-- 2 files changed, 18 insertions(+), 57 deletions(-) diff --git a/rem/DB.swift b/rem/DB.swift index 0f3259f..a9e57a6 100644 --- a/rem/DB.swift +++ b/rem/DB.swift @@ -164,7 +164,6 @@ class DatabaseManager { do { let count = try db.scalar(query.count) if count == 0 { - print("insert") insertUniqueApplicationNames(appName) } } catch { @@ -279,63 +278,27 @@ class DatabaseManager { return 0 } - func search(searchText: String, limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { - let query = allText + func search(appName: String = "", searchText: String, limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { + var partialQuery = allText .join(frames, on: frames[id] == allText[frameId]) .join(videoChunks, on: frames[chunkId] == videoChunks[id]) - .filter(text.match("*\(searchText)*")) - .select(allText[frameId], text, frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) - .limit(limit, offset: offset) - - var results: [(Int64, String, String?, Date, String, Int64)] = [] - do { - for row in try db.prepare(query) { - let frameId = row[allText[frameId]] - let matchedText = row[text] - let applicationName = row[frames[activeApplicationName]] - let timestamp = row[frames[timestamp]] - let filePath = row[videoChunks[filePath]] - let offsetIndex = row[frames[offsetIndex]] - results.append((frameId, matchedText, applicationName, timestamp, filePath, offsetIndex)) - } - } catch { - print("Search error: \(error)") + + if !appName.isEmpty { + partialQuery = partialQuery.join(uniqueAppNames, on: uniqueAppNames[activeApplicationName] == frames[activeApplicationName]) } - return results - } - - func searchFilteredByAppName(appName: String, limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { - let query = frames - .join(videoChunks, on: frames[chunkId] == videoChunks[id]) - .join(uniqueAppNames, on: uniqueAppNames[activeApplicationName] == frames[activeApplicationName]) - .filter(uniqueAppNames[activeApplicationName].lowercaseString == appName.lowercased()) - .select(frames[id], frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) - .limit(limit, offset: offset) - - var results: [(Int64, String, String?, Date, String, Int64)] = [] - do { - for row in try db.prepare(query) { - let frameId = row[frames[id]] - let applicationName = row[frames[activeApplicationName]] - let timestamp = row[frames[timestamp]] - let filePath = row[videoChunks[filePath]] - let offsetIndex = row[frames[offsetIndex]] - results.append((frameId, "", applicationName, timestamp, filePath, offsetIndex)) - } - } catch { - print("Search error: \(error)") + + var query = partialQuery + .filter(text.match("*\(searchText)*")) + + if !appName.isEmpty && searchText.isEmpty { + query = partialQuery + .filter(uniqueAppNames[activeApplicationName].lowercaseString == appName.lowercased()) + } else if !appName.isEmpty && !searchText.isEmpty { + query = query.filter(uniqueAppNames[activeApplicationName].lowercaseString == appName.lowercased()) } - return results - } - func searchFilteredByAppNameAndText(appName: String, searchText: String, limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { - let query = allText - .join(frames, on: frames[id] == allText[frameId]) - .join(videoChunks, on: frames[chunkId] == videoChunks[id]) - .join(uniqueAppNames, on: uniqueAppNames[activeApplicationName] == frames[activeApplicationName]) - .filter(text.match("*\(searchText)*") && uniqueAppNames[activeApplicationName].lowercaseString == appName.lowercased()) - .select(allText[frameId], text, frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) - .limit(limit, offset: offset) + query = query.select(allText[frameId], text, frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) + .limit(limit, offset: offset) var results: [(Int64, String, String?, Date, String, Int64)] = [] do { @@ -353,7 +316,6 @@ class DatabaseManager { } return results } - func getRecentResults(limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String?, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { let query = frames diff --git a/rem/Search.swift b/rem/Search.swift index 613580f..1416688 100644 --- a/rem/Search.swift +++ b/rem/Search.swift @@ -183,7 +183,6 @@ class SearchResult: ObservableObject, Identifiable { // .replacingOccurrences(of: "\\s+", with: "\\s*", options: .regularExpression) .replacingOccurrences(of: "(", with: "\\(") .replacingOccurrences(of: ")", with: "\\)") - .replacingOccurrences(of: #"!([^ ]*) "#, with: "", options: .regularExpression) if let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive), let match = regex.firstMatch(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count)) { @@ -366,9 +365,9 @@ struct ResultsView: View { } } else { if searchText.isEmpty { - results = DatabaseManager.shared.searchFilteredByAppName(appName: selectedFilterApp, limit: limit, offset: offset) + results = DatabaseManager.shared.search(appName: selectedFilterApp, searchText: "", limit: limit, offset: offset) } else { - results = DatabaseManager.shared.searchFilteredByAppNameAndText(appName: selectedFilterApp, searchText: searchText, limit: limit, offset: offset) + results = DatabaseManager.shared.search(appName: selectedFilterApp, searchText: searchText, limit: limit, offset: offset) } } From 58208df9970c8641c9e62cbc0859769439de20d0 Mon Sep 17 00:00:00 2001 From: drull Date: Thu, 4 Jan 2024 21:45:46 -0300 Subject: [PATCH 7/9] Modifying getRecentResults function --- rem/DB.swift | 10 ++++++++-- rem/Search.swift | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/rem/DB.swift b/rem/DB.swift index a9e57a6..edea328 100644 --- a/rem/DB.swift +++ b/rem/DB.swift @@ -317,12 +317,18 @@ class DatabaseManager { return results } - func getRecentResults(limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String?, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { - let query = frames + func getRecentResults(selectedFilterApp: String = "", limit: Int = 9, offset: Int = 0) -> [(frameId: Int64, fullText: String?, applicationName: String?, timestamp: Date, filePath: String, offsetIndex: Int64)] { + var query = frames .join(videoChunks, on: frames[chunkId] == videoChunks[id]) .select(frames[id], frames[activeApplicationName], frames[timestamp], videoChunks[filePath], frames[offsetIndex]) .order(frames[timestamp].desc) .limit(limit, offset: offset) + + if !selectedFilterApp.isEmpty { + query = query + .join(uniqueAppNames, on: uniqueAppNames[activeApplicationName] == frames[activeApplicationName]) + .filter(uniqueAppNames[activeApplicationName].lowercaseString == selectedFilterApp.lowercased()) + } var results: [(Int64, String?, String?, Date, String, Int64)] = [] do { diff --git a/rem/Search.swift b/rem/Search.swift index 1416688..b4addef 100644 --- a/rem/Search.swift +++ b/rem/Search.swift @@ -365,7 +365,7 @@ struct ResultsView: View { } } else { if searchText.isEmpty { - results = DatabaseManager.shared.search(appName: selectedFilterApp, searchText: "", limit: limit, offset: offset) + results = DatabaseManager.shared.getRecentResults(selectedFilterApp: selectedFilterApp, limit: limit, offset: offset) } else { results = DatabaseManager.shared.search(appName: selectedFilterApp, searchText: searchText, limit: limit, offset: offset) } From 5095d9c453eefbe1e0032dd27544532472d44922 Mon Sep 17 00:00:00 2001 From: Pedro Caetano Date: Fri, 5 Jan 2024 09:55:57 -0300 Subject: [PATCH 8/9] Seed the uniqueAppNames table if empty Co-authored-by: Jason McGhee --- rem/DB.swift | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/rem/DB.swift b/rem/DB.swift index edea328..07a237a 100644 --- a/rem/DB.swift +++ b/rem/DB.swift @@ -90,7 +90,24 @@ class DatabaseManager { t.column(id, primaryKey: .autoincrement) t.column(activeApplicationName, unique: true) }) - + // Seed the `uniqueAppNames` table if empty + do { + if try db.scalar(uniqueAppNames.count) == 0 { + let query = frames.select(distinct: activeApplicationName) + var appNames: [String] = [] + for row in try db.prepare(query) { + if let appName = row[activeApplicationName] { + appNames.append(appName) + } + } + let insert = uniqueAppNames.insertMany( + appNames.map { name in [activeApplicationName <- name] } + ) + try db.run(insert) + } + } catch { + print("Error seeding database with app names: \(error)") + } let config = FTS4Config() .column(frameId, [.unindexed]) .column(text) From 75e0f13ee1ab76afd13aa24fd0883d77d4704411 Mon Sep 17 00:00:00 2001 From: drull Date: Fri, 5 Jan 2024 10:07:04 -0300 Subject: [PATCH 9/9] Update when hovering and appearing --- rem/Search.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rem/Search.swift b/rem/Search.swift index fcf3ed5..6430396 100644 --- a/rem/Search.swift +++ b/rem/Search.swift @@ -104,6 +104,9 @@ struct FilterPicker: View { .onHover(perform: { hovering in updateAppFilterData() }) + .onAppear{ + updateAppFilterData() + } .pickerStyle(.menu) .onChange(of: selectedFilterAppIndex) { newIndex in guard newIndex >= 0 && newIndex < applicationFilterArray.count else {