Implement search — fetch articles matching a search string from the database.
This commit is contained in:
parent
0e98cd56a1
commit
efe8a4ab15
@ -496,6 +496,14 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func debugRunSearch() {
|
||||||
|
#if DEBUG
|
||||||
|
database.fetchArticlesMatching("Brent Simmons") { (articles) in
|
||||||
|
print(articles)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Notifications
|
// MARK: - Notifications
|
||||||
|
|
||||||
@objc func downloadProgressDidChange(_ note: Notification) {
|
@objc func downloadProgressDidChange(_ note: Notification) {
|
||||||
|
@ -25,7 +25,6 @@ public final class ArticlesDatabase {
|
|||||||
private let articlesTable: ArticlesTable
|
private let articlesTable: ArticlesTable
|
||||||
|
|
||||||
public init(databaseFilePath: String, accountID: String) {
|
public init(databaseFilePath: String, accountID: String) {
|
||||||
|
|
||||||
self.accountID = accountID
|
self.accountID = accountID
|
||||||
|
|
||||||
let queue = RSDatabaseQueue(filepath: databaseFilePath, excludeFromBackup: false)
|
let queue = RSDatabaseQueue(filepath: databaseFilePath, excludeFromBackup: false)
|
||||||
@ -43,69 +42,60 @@ public final class ArticlesDatabase {
|
|||||||
// MARK: - Fetching Articles
|
// MARK: - Fetching Articles
|
||||||
|
|
||||||
public func fetchArticles(for feedID: String) -> Set<Article> {
|
public func fetchArticles(for feedID: String) -> Set<Article> {
|
||||||
|
|
||||||
return articlesTable.fetchArticles(feedID)
|
return articlesTable.fetchArticles(feedID)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchArticlesAsync(for feedID: String, _ resultBlock: @escaping ArticleResultBlock) {
|
public func fetchArticlesAsync(for feedID: String, _ resultBlock: @escaping ArticleResultBlock) {
|
||||||
|
|
||||||
articlesTable.fetchArticlesAsync(feedID, withLimits: true, resultBlock)
|
articlesTable.fetchArticlesAsync(feedID, withLimits: true, resultBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchUnreadArticles(for feedIDs: Set<String>) -> Set<Article> {
|
public func fetchUnreadArticles(for feedIDs: Set<String>) -> Set<Article> {
|
||||||
|
|
||||||
return articlesTable.fetchUnreadArticles(for: feedIDs)
|
return articlesTable.fetchUnreadArticles(for: feedIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchTodayArticles(for feedIDs: Set<String>) -> Set<Article> {
|
public func fetchTodayArticles(for feedIDs: Set<String>) -> Set<Article> {
|
||||||
|
|
||||||
return articlesTable.fetchTodayArticles(for: feedIDs)
|
return articlesTable.fetchTodayArticles(for: feedIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchStarredArticles(for feedIDs: Set<String>) -> Set<Article> {
|
public func fetchStarredArticles(for feedIDs: Set<String>) -> Set<Article> {
|
||||||
|
|
||||||
return articlesTable.fetchStarredArticles(for: feedIDs)
|
return articlesTable.fetchStarredArticles(for: feedIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func fetchArticlesMatching(_ searchString: String, _ resultBlock: @escaping ArticleResultBlock) {
|
||||||
|
articlesTable.fetchArticlesMatching(searchString, resultBlock)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Unread Counts
|
// MARK: - Unread Counts
|
||||||
|
|
||||||
public func fetchUnreadCounts(for feedIDs: Set<String>, _ completion: @escaping UnreadCountCompletionBlock) {
|
public func fetchUnreadCounts(for feedIDs: Set<String>, _ completion: @escaping UnreadCountCompletionBlock) {
|
||||||
|
|
||||||
articlesTable.fetchUnreadCounts(feedIDs, completion)
|
articlesTable.fetchUnreadCounts(feedIDs, completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchUnreadCount(for feedIDs: Set<String>, since: Date, callback: @escaping (Int) -> Void) {
|
public func fetchUnreadCount(for feedIDs: Set<String>, since: Date, callback: @escaping (Int) -> Void) {
|
||||||
|
|
||||||
articlesTable.fetchUnreadCount(feedIDs, since, callback)
|
articlesTable.fetchUnreadCount(feedIDs, since, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchStarredAndUnreadCount(for feedIDs: Set<String>, callback: @escaping (Int) -> Void) {
|
public func fetchStarredAndUnreadCount(for feedIDs: Set<String>, callback: @escaping (Int) -> Void) {
|
||||||
|
|
||||||
articlesTable.fetchStarredAndUnreadCount(feedIDs, callback)
|
articlesTable.fetchStarredAndUnreadCount(feedIDs, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchAllNonZeroUnreadCounts(_ completion: @escaping UnreadCountCompletionBlock) {
|
public func fetchAllNonZeroUnreadCounts(_ completion: @escaping UnreadCountCompletionBlock) {
|
||||||
|
|
||||||
articlesTable.fetchAllUnreadCounts(completion)
|
articlesTable.fetchAllUnreadCounts(completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Saving and Updating Articles
|
// MARK: - Saving and Updating Articles
|
||||||
|
|
||||||
public func update(feedID: String, parsedFeed: ParsedFeed, completion: @escaping UpdateArticlesWithFeedCompletionBlock) {
|
public func update(feedID: String, parsedFeed: ParsedFeed, completion: @escaping UpdateArticlesWithFeedCompletionBlock) {
|
||||||
|
|
||||||
return articlesTable.update(feedID, parsedFeed, completion)
|
return articlesTable.update(feedID, parsedFeed, completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Status
|
// MARK: - Status
|
||||||
|
|
||||||
public func mark(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<ArticleStatus>? {
|
public func mark(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<ArticleStatus>? {
|
||||||
|
|
||||||
return articlesTable.mark(articles, statusKey, flag)
|
return articlesTable.mark(articles, statusKey, flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func markEverywhereAsRead() {
|
public func markEverywhereAsRead() {
|
||||||
|
|
||||||
articlesTable.markEverywhereAsRead()
|
articlesTable.markEverywhereAsRead()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,15 @@ final class ArticlesTable: DatabaseTable {
|
|||||||
return fetchStarredArticles(feedIDs)
|
return fetchStarredArticles(feedIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchArticlesMatching(_ searchString: String, _ resultBlock: @escaping ArticleResultBlock) {
|
||||||
|
queue.fetch { (database) in
|
||||||
|
let articles = self.fetchArticlesMatching(searchString, database)
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
resultBlock(articles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Updating
|
// MARK: Updating
|
||||||
|
|
||||||
func update(_ feedID: String, _ parsedFeed: ParsedFeed, _ completion: @escaping UpdateArticlesWithFeedCompletionBlock) {
|
func update(_ feedID: String, _ parsedFeed: ParsedFeed, _ completion: @escaping UpdateArticlesWithFeedCompletionBlock) {
|
||||||
@ -425,6 +434,11 @@ private extension ArticlesTable {
|
|||||||
return articles
|
return articles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchArticlesMatching(_ searchString: String, _ database: FMDatabase) -> Set<Article> {
|
||||||
|
let whereClause = "(starred=1 or dateArrived>?) and userDeleted=0 and (textMatchesSearchString(title,?) or textMatchesSearchString(contentHTML,?) or textMatchesSearchString(contentText,?) or textMatchesSearchString(summary,?))"
|
||||||
|
let parameters: [AnyObject] = [articleCutoffDate as AnyObject, searchString as AnyObject, searchString as AnyObject, searchString as AnyObject, searchString as AnyObject]
|
||||||
|
return self.fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters, withLimits: false)
|
||||||
|
}
|
||||||
|
|
||||||
func articlesWithSQL(_ sql: String, _ parameters: [AnyObject], _ database: FMDatabase) -> Set<Article> {
|
func articlesWithSQL(_ sql: String, _ parameters: [AnyObject], _ database: FMDatabase) -> Set<Article> {
|
||||||
|
|
||||||
|
@ -558,6 +558,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Debug Menu
|
||||||
|
extension AppDelegate {
|
||||||
|
|
||||||
|
@IBAction func debugSearch(_ sender: Any?) {
|
||||||
|
AccountManager.shared.localAccount.debugRunSearch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private extension AppDelegate {
|
private extension AppDelegate {
|
||||||
|
|
||||||
func createReaderWindow() -> MainWindowController {
|
func createReaderWindow() -> MainWindowController {
|
||||||
|
@ -461,6 +461,12 @@
|
|||||||
<action selector="debugTestCrashReportSending:" target="Ady-hI-5gd" id="olQ-kb-kkm"/>
|
<action selector="debugTestCrashReportSending:" target="Ady-hI-5gd" id="olQ-kb-kkm"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
<menuItem title="Debug Search" id="9Ot-wC-s5U">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="debugSearch:" target="Ady-hI-5gd" id="HvM-F7-u7s"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
</items>
|
</items>
|
||||||
</menu>
|
</menu>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user