Skip to content

Commit

Permalink
update search view. (#59)
Browse files Browse the repository at this point in the history
Co-authored-by: Jiaqi Feng <jiaqi.feng@transcarent.com>
  • Loading branch information
Livinglist and jiaqi-transcarent committed Jun 5, 2023
1 parent 9cf6ef1 commit 3757ba4
Show file tree
Hide file tree
Showing 41 changed files with 487 additions and 222 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,48 @@
public protocol SearchFilter: Equatable {
var query: String { get }
}

public class StoryFilter: SearchFilter {
public let query: String = "story"
import Foundation

public static func == (lhs: StoryFilter, rhs: StoryFilter) -> Bool {
lhs.query == rhs.query
public enum SearchFilter: Equatable, Hashable {
case story
case comment
case dateRange(Date, Date)

var query: String {
switch(self){
case .story:
return "story"
case .comment:
return "comment"
case .dateRange(let startDate, let endDate):
let startTimestamp = Int(startDate.timeIntervalSince1970.rounded())
let endTimestamp = Int(endDate.timeIntervalSince1970.rounded())

if startTimestamp != endTimestamp {
return "created_at_i>=\(startTimestamp),created_at_i<=\(endTimestamp)"
} else {
let updatedStartDate = Calendar.current.date(
byAdding: .hour,
value: -24,
to: startDate)
let updatedStartTimestamp = updatedStartDate?.timeIntervalSince1970

if let updatedStartTimestamp = updatedStartTimestamp?.rounded() {
return "created_at_i>=\(Int(updatedStartTimestamp)),created_at_i<=\(endTimestamp)"
}

return .init()
}
}
}

public init() { }
}

public class CommentFilter: SearchFilter {
public let query: String = "comment"

public static func == (lhs: CommentFilter, rhs: CommentFilter) -> Bool {
lhs.query == rhs.query

var isNumericFilter: Bool {
switch(self){
case .story, .comment:
return false
case .dateRange:
return true
}
}

var isTagFilter: Bool {
!isNumericFilter
}

public init() { }
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Foundation

public class SearchParams {
public class SearchParams: Equatable {
public let page: Int
public let query: String
public let sorted: Bool
public let filters: [any SearchFilter]
public let filters: Set<SearchFilter>

public var filteredQuery: String {
var buffer = String()
Expand All @@ -13,33 +13,51 @@ public class SearchParams {
if sorted {
buffer.append("search_by_date?query=\(encodedQuery)")
} else {
buffer.append("search?query=?query=\(encodedQuery)")
buffer.append("search?query=\(encodedQuery)")
}

if filters.isEmpty == false {
buffer.append("&tags=")
if !filters.isEmpty {
let numericFilters = filters.filter({ $0.isNumericFilter })
let tagFilters = filters.filter({ $0.isTagFilter })

for filter in filters {
buffer.append(filter.query)
buffer.append(",")
if !numericFilters.isEmpty {
buffer.append("&numericFilters=")
for filter in filters.filter({ $0.isNumericFilter }) {
buffer.append(filter.query)
buffer.append(",")
}
buffer = String(buffer.dropLast(1))
}

buffer = String(buffer.dropLast(1))

if !tagFilters.isEmpty {
buffer.append("&tags=(")
for filter in filters.filter({ $0.isTagFilter }) {
buffer.append(filter.query)
buffer.append(",")
}
buffer = String(buffer.dropLast(1))
buffer.append(")")
}

}

buffer.append("&page=\(page)");

return buffer
}

public init(page: Int, query: String, sorted: Bool, filters: [any SearchFilter]) {
public init(page: Int, query: String, sorted: Bool, filters: Set<SearchFilter>) {
self.page = page
self.query = query
self.sorted = sorted
self.filters = filters
}

public func copyWith(page: Int? = nil, query: String? = nil, sorted: Bool? = nil, filters: [any SearchFilter]? = nil) -> SearchParams {
public func copyWith(page: Int? = nil, query: String? = nil, sorted: Bool? = nil, filters: Set<SearchFilter>? = nil) -> SearchParams {
return SearchParams(page: page ?? self.page, query: query ?? self.query, sorted: sorted ?? self.sorted, filters: filters ?? self.filters)
}

public static func == (lhs: SearchParams, rhs: SearchParams) -> Bool {
return lhs.page == rhs.page && lhs.query == rhs.query && lhs.sorted == rhs.sorted && lhs.filters == rhs.filters
}
}
22 changes: 11 additions & 11 deletions Packages/HackerNewsKit/Sources/HackerNewsKit/Models/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ public struct User: Decodable, Equatable {
public let submitted: [Int]?

public init() {
self.id = String()
self.about = String()
self.created = Int()
self.delay = Int()
self.karma = Int()
self.submitted = [Int]()
self.id = .init()
self.about = .init()
self.created = .init()
self.delay = .init()
self.karma = .init()
self.submitted = .init()
}

/// If a user does not have any activity, the user endpoint will not return anything.
/// in that case, we create a user with only username.
public init(id: String) {
self.id = id
self.about = String()
self.created = Int()
self.delay = Int()
self.karma = Int()
self.submitted = [Int]()
self.about = .init()
self.created = .init()
self.delay = .init()
self.karma = .init()
self.submitted = .init()
}

init(id: String?, about: String?, created: Int?, delay: Int?, karma: Int?, submitted: [Int]?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Alamofire
import Security

public class AuthRepository {
public static let shared = AuthRepository()
public static let shared: AuthRepository = .init()

private let server: String = "news.ycombinator.com"
private let baseUrl: String = "https://news.ycombinator.com"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import Foundation
import Alamofire

public class SearchRepository {
public static let shared = SearchRepository()
public static let shared: SearchRepository = .init()

private init() {}

private let baseUrl = "http://hn.algolia.com/api/v1/"
private let baseUrl = "https://hn.algolia.com/api/v1/"

public func search(params: SearchParams, onItemFetched: @escaping (any Item) -> Void) async -> Void {
let urlStr = "\(baseUrl)\(params.filteredQuery)"
guard let url = URL(string: urlStr) else { return }
guard let urlStr = "\(baseUrl)\(params.filteredQuery)".addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed),
let url = URL(string: urlStr) else { return }
let response = await AF.request(url).serializingString().response

guard let result = try? response.result.get(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import Alamofire

public class StoriesRepository {
public static let shared = StoriesRepository()
public static let shared: StoriesRepository = .init()

private let baseUrl: String = "https://hacker-news.firebaseio.com/v0/"

Expand Down
Binary file modified Resources/Screenshots/iphone-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Resources/zcombinator.xcf
Binary file not shown.
2 changes: 1 addition & 1 deletion ShareExtension/ShareViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ShareViewController: SLComposeServiceViewController {
}
}

override func didSelectPost() { }
override func didSelectPost() {}

override func configurationItems() -> [Any]! {
return []
Expand Down
2 changes: 1 addition & 1 deletion Shared/Models/Action.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ enum Action: Equatable {
case .copy:
return "Copied"
case .none:
return String()
return .init()
}
}
}
8 changes: 4 additions & 4 deletions Shared/Models/AppNotification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ private extension Calendar {
}

class AppNotification {
private let auth = Authentication.shared
private let repo = StoriesRepository.shared
private let auth: Authentication = .shared
private let repo: StoriesRepository = .shared

static let shared = AppNotification()
static let shared: AppNotification = .init()

private init() { }
private init() {}

func scheduleFetching() {
let request = BGAppRefreshTaskRequest(identifier: Constants.AppNotification.backgroundTaskId)
Expand Down
4 changes: 2 additions & 2 deletions Shared/Models/Authentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import HackerNewsKit

public class Authentication: ObservableObject {
@Published var username: String?
@Published var loggedIn = Bool()
@Published var loggedIn: Bool = .init()
@Published var user: User?

static let shared = Authentication()
static let shared: Authentication = .init()

private init() {
Task {
Expand Down
6 changes: 3 additions & 3 deletions Shared/Models/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import SwiftUI
import HackerNewsKit

class Router: ObservableObject {
@Published var path = NavigationPath()
@Published var path: NavigationPath = .init()

static let shared = Router()
static let shared: Router = .init()

private init() { }
private init() {}

func to(_ destination: Destination) {
path.append(destination)
Expand Down
6 changes: 3 additions & 3 deletions Shared/Models/Settings.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Foundation

class Settings: ObservableObject {
@Published var favList = Array<Int>()
@Published var pinList = Array<Int>()
@Published var favList: [Int] = .init()
@Published var pinList: [Int] = .init()

static let shared = Settings()
static let shared: Settings = .init()

private init() {
if let favList = UserDefaults.standard.array(forKey: Constants.UserDefaults.favListKey) as? [Int] {
Expand Down
4 changes: 2 additions & 2 deletions Shared/Models/Stores/FavStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import HackerNewsKit
extension FavView {
@MainActor
class FavStore: ObservableObject {
@Published var items = [any Item]()
@Published var items: [any Item] = .init()
@Published var status: Status = .idle

private let settingsStore = Settings.shared
private let settingsStore: Settings = .shared
private let pageSize: Int = 10
private var currentPage: Int = 0
private var cancellable: AnyCancellable?
Expand Down
2 changes: 1 addition & 1 deletion Shared/Models/Stores/ItemStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import HackerNewsKit
extension ItemView {
@MainActor
class ItemStore : ObservableObject {
@Published var kids = [Comment]()
@Published var kids: [Comment] = .init()
@Published var status: Status = .idle
@Published var item: (any Item)?
@Published var loadingItem: Int?
Expand Down
4 changes: 2 additions & 2 deletions Shared/Models/Stores/PinStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import HackerNewsKit
extension PinView {
@MainActor
class PinStore: ObservableObject {
@Published var pinnedItems = [any Item]()
@Published var pinnedItems: [any Item] = .init()
@Published var status: Status = .idle
private let settings = Settings.shared
private let settings: Settings = .shared
private(set) var pinnedIds: [Int] = [Int]() {
didSet {
Task {
Expand Down
Loading

0 comments on commit 3757ba4

Please sign in to comment.