Skip to content

Commit

Permalink
Add search on subreddit
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimillian committed May 17, 2021
1 parent 5d172c7 commit 591c30c
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 58 deletions.
3 changes: 3 additions & 0 deletions Packages/Backend/Sources/Backend/Network/Endpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum Endpoint {
case subscribe
case searchSubreddit
case search
case searchPosts(name: String)
case comments(name: String, id: String)
case accessToken
case me, mineSubscriptions, mineMulti
Expand Down Expand Up @@ -65,6 +66,8 @@ public enum Endpoint {
return "api/trending_subreddits"
case .search:
return "search"
case let .searchPosts(name):
return "r/\(name)/search"
}
}
}
12 changes: 0 additions & 12 deletions RedditOs.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
9F19B57A26505DCF00FBEEDA /* SidebarMultiView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F19B57926505DCF00FBEEDA /* SidebarMultiView.swift */; };
9F4537862652DF960026C19B /* SearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F4537852652DF960026C19B /* SearchBarView.swift */; };
9F4537882652ED550026C19B /* QuickSearchPostsResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F4537872652ED550026C19B /* QuickSearchPostsResultView.swift */; };
9F45378B2652F5DC0026C19B /* SubredditSearchState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F45378A2652F5DC0026C19B /* SubredditSearchState.swift */; };
9F4812CC264FC8DB007A719D /* QuickSearchFullResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F4812CB264FC8DB007A719D /* QuickSearchFullResultsView.swift */; };
9F8EE49126510BCF00BDE4AC /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 9F8EE49026510BCF00BDE4AC /* MarkdownUI */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -137,7 +136,6 @@
9F19B57926505DCF00FBEEDA /* SidebarMultiView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarMultiView.swift; sourceTree = "<group>"; };
9F4537852652DF960026C19B /* SearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarView.swift; sourceTree = "<group>"; };
9F4537872652ED550026C19B /* QuickSearchPostsResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSearchPostsResultView.swift; sourceTree = "<group>"; };
9F45378A2652F5DC0026C19B /* SubredditSearchState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubredditSearchState.swift; sourceTree = "<group>"; };
9F4812CB264FC8DB007A719D /* QuickSearchFullResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSearchFullResultsView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -269,7 +267,6 @@
6970A0B724B79AF400B11031 /* Search */ = {
isa = PBXGroup;
children = (
9F4537892652F5CD0026C19B /* Subreddit */,
9F4537842652DDDE0026C19B /* Shared */,
9F4537822652DDCD0026C19B /* Quick */,
693F85D224D06AA700224ADB /* Subreddit Search Popover */,
Expand Down Expand Up @@ -411,14 +408,6 @@
path = Shared;
sourceTree = "<group>";
};
9F4537892652F5CD0026C19B /* Subreddit */ = {
isa = PBXGroup;
children = (
9F45378A2652F5DC0026C19B /* SubredditSearchState.swift */,
);
path = Subreddit;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -522,7 +511,6 @@
6924D53E24CD94B0005487CA /* UserViewModel.swift in Sources */,
69222AA724CD6D6C009F31B4 /* SubmittedPostsListView.swift in Sources */,
9F4812CC264FC8DB007A719D /* QuickSearchFullResultsView.swift in Sources */,
9F45378B2652F5DC0026C19B /* SubredditSearchState.swift in Sources */,
697E324724E3ED620006F00F /* CommentViewModel.swift in Sources */,
692566DA24B8A3830014E0D4 /* PostDetailHeader.swift in Sources */,
69CCB3EA24E2BEAC003FAAD7 /* SubredditAboutPopoverView.swift in Sources */,
Expand Down
13 changes: 0 additions & 13 deletions RedditOs/Features/Search/Subreddit/SubredditSearchState.swift

This file was deleted.

3 changes: 3 additions & 0 deletions RedditOs/Features/Subreddit/SubredditPostRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ struct SubredditPostRow: View, Equatable {
let url = URL(string: urlString) {
Link(destination: url) {
Text(url.host ?? url.absoluteString)
.lineLimit(1)
.truncationMode(.tail)
.frame(maxWidth: 250)
}
}
}
Expand Down
37 changes: 26 additions & 11 deletions RedditOs/Features/Subreddit/SubredditPostsListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ struct SubredditPostsListView: View, Equatable {
@EnvironmentObject private var localData: LocalDataStore

@StateObject private var viewModel: SubredditViewModel
@StateObject private var searchState = SubredditSearchState()
@AppStorage(SettingsKey.subreddit_display_mode) private var displayMode = SubredditPostRow.DisplayMode.large

@State private var subredditAboutPopoverShown = false
Expand All @@ -48,6 +47,15 @@ struct SubredditPostsListView: View, Equatable {
return ""
}

var posts: [SubredditPost]? {
if viewModel.isSearchLoading {
return nil
} else if !viewModel.searchText.isEmpty && viewModel.searchResults != nil {
return viewModel.searchResults
}
return viewModel.listings
}

private var placeholderIcon: some View {
Image(systemName: "globe")
.resizable()
Expand All @@ -56,19 +64,26 @@ struct SubredditPostsListView: View, Equatable {

var body: some View {
PostsListView(header: {
SearchBarView(placeholder: "Search",
searchText: $searchState.searchText) { editing in

} onCommit: {

} onCancel: {

if !isDefaultChannel {
SearchBarView(placeholder: "Search",
searchText: $viewModel.searchText) { editing in

} onCommit: {

} onCancel: {

}
.keyboardShortcut("f", modifiers: .command)
.padding(.bottom, 8)
}
.keyboardShortcut("f", modifiers: .command)
},
posts: viewModel.listings,
posts: posts,
displayMode: .constant(displayMode)) {
viewModel.fetchListings()
if !viewModel.searchText.isEmpty && viewModel.searchResults != nil {
viewModel.fetchSearch(text: viewModel.searchText, after: viewModel.searchResults?.last?.id)
} else {
viewModel.fetchListings()
}
}
.equatable()
.toolbar {
Expand Down
91 changes: 69 additions & 22 deletions RedditOs/Features/Subreddit/SubredditViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ class SubredditViewModel: ObservableObject {
}

let name: String

private var subredditCancellable: AnyCancellable?
private var listingCancellable: AnyCancellable?
private var subscribeCancellable: AnyCancellable?


@Published var subreddit: Subreddit?
@Published var listings: [SubredditPost]?
@Published var searchResults: [SubredditPost]?

@Published var searchText = ""
@Published var isSearchLoading = false

@AppStorage(SettingsKey.subreddit_defaut_sort_order) var sortOrder = SortOrder.hot {
didSet {
listings = nil
Expand All @@ -31,23 +32,43 @@ class SubredditViewModel: ObservableObject {
}
@Published var errorLoadingAbout = false

private var postsSearchPublisher: AnyPublisher<ListingResponse<SubredditPost>, Never>?
private var cancellableSet: Set<AnyCancellable> = Set()

init(name: String) {
self.name = name

$searchText
.subscribe(on: DispatchQueue.global())
.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink(receiveValue: { [weak self] text in
if text.isEmpty {
self?.isSearchLoading = false
self?.searchResults = nil
} else {
self?.isSearchLoading = true
self?.fetchSearch(text: text, after: nil)
}
})
.store(in: &cancellableSet)
}

func fetchAbout() {
subredditCancellable = Subreddit.fetchAbout(name: name)
.receive(on: DispatchQueue.main)
.sink { [weak self] holder in
self?.errorLoadingAbout = holder == nil
self?.subreddit = holder?.data
}
Subreddit.fetchAbout(name: name)
.receive(on: DispatchQueue.main)
.sink { [weak self] holder in
self?.errorLoadingAbout = holder == nil
self?.subreddit = holder?.data
}
.store(in: &cancellableSet)
}

func fetchListings() {
listingCancellable = SubredditPost.fetch(subreddit: name,
sort: sortOrder.rawValue,
after: listings?.last)
SubredditPost.fetch(subreddit: name,
sort: sortOrder.rawValue,
after: listings?.last)
.receive(on: DispatchQueue.main)
.map{ $0.data?.children.map{ $0.data }}
.sink{ [weak self] listings in
Expand All @@ -57,25 +78,51 @@ class SubredditViewModel: ObservableObject {
self?.listings = listings
}
}
.store(in: &cancellableSet)
}

func fetchSearch(text: String, after: String?) {
var params = ["q": text, "restrict_sr": "1"]
if let after = after {
params["after"] = after
}
postsSearchPublisher = API.shared.request(endpoint: .searchPosts(name: name), params: params)
.subscribe(on: DispatchQueue.global())
.replaceError(with: ListingResponse(error: "error"))
.eraseToAnyPublisher()

postsSearchPublisher?.receive(on: DispatchQueue.main)
.map{ $0.data?.children.map{ $0.data }}
.sink(receiveValue: { [weak self] results in
self?.isSearchLoading = false
if self?.searchResults?.last != nil, let results = results {
self?.searchResults?.append(contentsOf: results)
} else {
self?.searchResults = results
}
})
.store(in: &cancellableSet)
}

func toggleSubscribe() {
if subreddit?.userIsSubscriber == true {
subscribeCancellable = subreddit?.unSubscribe()
.receive(on: DispatchQueue.main)
.sink { [weak self] response in
if response.error != nil {
self?.subreddit?.userIsSubscriber = true
}
}
subreddit?.unSubscribe()
.receive(on: DispatchQueue.main)
.sink { [weak self] response in
if response.error != nil {
self?.subreddit?.userIsSubscriber = true
}
}
.store(in: &cancellableSet)
} else {
subscribeCancellable = subreddit?.subscribe()
subreddit?.subscribe()
.receive(on: DispatchQueue.main)
.sink { [weak self] response in
if response.error != nil {
self?.subreddit?.userIsSubscriber = false
}
}
.store(in: &cancellableSet)
}
}
}

0 comments on commit 591c30c

Please sign in to comment.