Skip to content

Commit d9c3e67

Browse files
committed
Added "Search thread" option to hamburger menu, leveraging Forums Search feature
1 parent eca864e commit d9c3e67

3 files changed

Lines changed: 96 additions & 60 deletions

File tree

App/Resources/Localizable.xcstrings

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -56,86 +56,86 @@
5656
"Back" : {
5757

5858
},
59-
"bookmarks.title" : {
60-
"comment" : "Title of the bookmarks screen, shown in the navbar and the tab bar.",
61-
"extractionState" : "migrated",
59+
"bookmarks.filter.all" : {
60+
"comment" : "Segmented control label for showing all bookmarks.",
61+
"extractionState" : "manual",
6262
"localizations" : {
6363
"en" : {
6464
"stringUnit" : {
6565
"state" : "translated",
66-
"value" : "Bookmarks"
66+
"value" : "All"
6767
}
6868
}
6969
}
7070
},
71-
"bookmarks.filter.all" : {
72-
"comment" : "Segmented control label for showing all bookmarks.",
71+
"bookmarks.filter.button.accessibility-label" : {
72+
"comment" : "Accessibility label for the filter button in the bookmarks navigation bar.",
7373
"extractionState" : "manual",
7474
"localizations" : {
7575
"en" : {
7676
"stringUnit" : {
7777
"state" : "translated",
78-
"value" : "All"
78+
"value" : "Filter bookmarks"
7979
}
8080
}
8181
}
8282
},
83-
"bookmarks.filter.unread" : {
84-
"comment" : "Segmented control label for showing only unread bookmarks.",
83+
"bookmarks.filter.menu.accessibility-hint" : {
84+
"comment" : "Accessibility hint for the filter menu popover.",
8585
"extractionState" : "manual",
8686
"localizations" : {
8787
"en" : {
8888
"stringUnit" : {
8989
"state" : "translated",
90-
"value" : "Unread"
90+
"value" : "Filter bookmarks by read status or star color"
9191
}
9292
}
9393
}
9494
},
95-
"bookmarks.filter.read" : {
96-
"comment" : "Segmented control label for showing only read bookmarks.",
95+
"bookmarks.filter.menu.accessibility-label" : {
96+
"comment" : "Accessibility label for the filter menu popover.",
9797
"extractionState" : "manual",
9898
"localizations" : {
9999
"en" : {
100100
"stringUnit" : {
101101
"state" : "translated",
102-
"value" : "Read"
102+
"value" : "Filter Menu"
103103
}
104104
}
105105
}
106106
},
107-
"bookmarks.filter.button.accessibility-label" : {
108-
"comment" : "Accessibility label for the filter button in the bookmarks navigation bar.",
107+
"bookmarks.filter.read" : {
108+
"comment" : "Segmented control label for showing only read bookmarks.",
109109
"extractionState" : "manual",
110110
"localizations" : {
111111
"en" : {
112112
"stringUnit" : {
113113
"state" : "translated",
114-
"value" : "Filter bookmarks"
114+
"value" : "Read"
115115
}
116116
}
117117
}
118118
},
119-
"bookmarks.filter.menu.accessibility-label" : {
120-
"comment" : "Accessibility label for the filter menu popover.",
119+
"bookmarks.filter.star.accessibility-hint.selected" : {
120+
"comment" : "Accessibility hint for a currently selected star color filter button.",
121121
"extractionState" : "manual",
122122
"localizations" : {
123123
"en" : {
124124
"stringUnit" : {
125125
"state" : "translated",
126-
"value" : "Filter Menu"
126+
"value" : "Currently selected. Double-tap to deselect."
127127
}
128128
}
129129
}
130130
},
131-
"bookmarks.filter.menu.accessibility-hint" : {
132-
"comment" : "Accessibility hint for the filter menu popover.",
131+
"bookmarks.filter.star.accessibility-hint.unselected" : {
132+
"comment" : "Accessibility hint for an unselected star color filter button.",
133133
"extractionState" : "manual",
134134
"localizations" : {
135135
"en" : {
136136
"stringUnit" : {
137137
"state" : "translated",
138-
"value" : "Filter bookmarks by read status or star color"
138+
"value" : "Double-tap to filter by this star color."
139139
}
140140
}
141141
}
@@ -152,50 +152,50 @@
152152
}
153153
}
154154
},
155-
"bookmarks.filter.star.accessibility-hint.selected" : {
156-
"comment" : "Accessibility hint for a currently selected star color filter button.",
155+
"bookmarks.filter.unread" : {
156+
"comment" : "Segmented control label for showing only unread bookmarks.",
157157
"extractionState" : "manual",
158158
"localizations" : {
159159
"en" : {
160160
"stringUnit" : {
161161
"state" : "translated",
162-
"value" : "Currently selected. Double-tap to deselect."
162+
"value" : "Unread"
163163
}
164164
}
165165
}
166166
},
167-
"bookmarks.filter.star.accessibility-hint.unselected" : {
168-
"comment" : "Accessibility hint for an unselected star color filter button.",
167+
"bookmarks.search.button.accessibility-label" : {
168+
"comment" : "Accessibility label for the search button in the bookmarks navigation bar.",
169169
"extractionState" : "manual",
170170
"localizations" : {
171171
"en" : {
172172
"stringUnit" : {
173173
"state" : "translated",
174-
"value" : "Double-tap to filter by this star color."
174+
"value" : "Search bookmarks"
175175
}
176176
}
177177
}
178178
},
179-
"bookmarks.search.button.accessibility-label" : {
180-
"comment" : "Accessibility label for the search button in the bookmarks navigation bar.",
179+
"bookmarks.search.placeholder" : {
180+
"comment" : "Placeholder text for the bookmarks search bar.",
181181
"extractionState" : "manual",
182182
"localizations" : {
183183
"en" : {
184184
"stringUnit" : {
185185
"state" : "translated",
186-
"value" : "Search bookmarks"
186+
"value" : "Search by title or author…"
187187
}
188188
}
189189
}
190190
},
191-
"bookmarks.search.placeholder" : {
192-
"comment" : "Placeholder text for the bookmarks search bar.",
193-
"extractionState" : "manual",
191+
"bookmarks.title" : {
192+
"comment" : "Title of the bookmarks screen, shown in the navbar and the tab bar.",
193+
"extractionState" : "migrated",
194194
"localizations" : {
195195
"en" : {
196196
"stringUnit" : {
197197
"state" : "translated",
198-
"value" : "Search by title or author\u2026"
198+
"value" : "Bookmarks"
199199
}
200200
}
201201
}
@@ -1148,46 +1148,46 @@
11481148
}
11491149
}
11501150
},
1151-
"private-message-folder.delete-error-title" : {
1152-
"comment" : "Error title when folder deletion fails",
1151+
"private-message-folder.delete-button" : {
1152+
"comment" : "Button to confirm folder deletion",
11531153
"localizations" : {
11541154
"en" : {
11551155
"stringUnit" : {
11561156
"state" : "translated",
1157-
"value" : "Could not delete folder"
1157+
"value" : "Delete"
11581158
}
11591159
}
11601160
}
11611161
},
1162-
"private-message-folder.delete-confirm-title" : {
1163-
"comment" : "Title of confirmation dialog when deleting a folder",
1162+
"private-message-folder.delete-confirm-message" : {
1163+
"comment" : "Message shown when deleting a folder explaining that messages will be moved",
11641164
"localizations" : {
11651165
"en" : {
11661166
"stringUnit" : {
11671167
"state" : "translated",
1168-
"value" : "Delete Folder?"
1168+
"value" : "Messages in this folder will be moved to Inbox or Sent."
11691169
}
11701170
}
11711171
}
11721172
},
1173-
"private-message-folder.delete-confirm-message" : {
1174-
"comment" : "Message shown when deleting a folder explaining that messages will be moved",
1173+
"private-message-folder.delete-confirm-title" : {
1174+
"comment" : "Title of confirmation dialog when deleting a folder",
11751175
"localizations" : {
11761176
"en" : {
11771177
"stringUnit" : {
11781178
"state" : "translated",
1179-
"value" : "Messages in this folder will be moved to Inbox or Sent."
1179+
"value" : "Delete Folder?"
11801180
}
11811181
}
11821182
}
11831183
},
1184-
"private-message-folder.delete-button" : {
1185-
"comment" : "Button to confirm folder deletion",
1184+
"private-message-folder.delete-error-title" : {
1185+
"comment" : "Error title when folder deletion fails",
11861186
"localizations" : {
11871187
"en" : {
11881188
"stringUnit" : {
11891189
"state" : "translated",
1190-
"value" : "Delete"
1190+
"value" : "Could not delete folder"
11911191
}
11921192
}
11931193
}
@@ -1615,6 +1615,12 @@
16151615
},
16161616
"Search smilies…" : {
16171617

1618+
},
1619+
"Search Thread" : {
1620+
1621+
},
1622+
"Search thread..." : {
1623+
16181624
},
16191625
"Select Forums" : {
16201626

@@ -1797,4 +1803,4 @@
17971803
}
17981804
},
17991805
"version" : "1.0"
1800-
}
1806+
}

App/View Controllers/Posts/PostsPageViewController.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ final class PostsPageViewController: ViewController {
113113
identifier: .init("yourPosts"),
114114
handler: { [unowned self] in yourPosts(action: $0) }
115115
),
116+
// Search thread
117+
UIAction(
118+
title: "Search thread",
119+
image: UIImage(named: "view-in-thread")!.withRenderingMode(.alwaysTemplate),
120+
identifier: .init("searchThread"),
121+
handler: { [unowned self] in searchThread(action: $0) }
122+
),
116123
])
117124
}
118125

@@ -1193,6 +1200,17 @@ final class PostsPageViewController: ViewController {
11931200
}
11941201
}
11951202

1203+
private func searchThread(action: UIAction) {
1204+
if enableHaptics {
1205+
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
1206+
}
1207+
self.dismiss(animated: false) { [self] in
1208+
let searchVC = SearchHostingController(threadID: thread.threadID)
1209+
searchVC.modalPresentationStyle = (traitCollection.userInterfaceIdiom == .pad) ? .pageSheet : .fullScreen
1210+
present(searchVC, animated: true)
1211+
}
1212+
}
1213+
11961214
private func bookmark(action: UIAction) {
11971215
if enableHaptics {
11981216
UIImpactFeedbackGenerator(style: .medium).impactOccurred()

App/Views/SearchView.swift

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,12 @@ struct SearchView: View {
275275
.padding()
276276
.background(theme[color: "sheetBackgroundColor"])
277277

278-
forumSelectionList
279-
.padding(.horizontal)
278+
if model.threadID == nil {
279+
forumSelectionList
280+
.padding(.horizontal)
281+
} else {
282+
Spacer()
283+
}
280284
}
281285
.background(theme[color: "backgroundColor"]!.ignoresSafeArea(.all))
282286
.contentShape(Rectangle())
@@ -286,7 +290,7 @@ struct SearchView: View {
286290
.navigationBarTitleDisplayMode(.inline)
287291
.toolbar {
288292
ToolbarItem(placement: .principal) {
289-
Text("Search Forums")
293+
Text(model.threadID == nil ? "Search Forums" : "Search Thread")
290294
.font(.headline)
291295
.foregroundColor(theme[color: "navigationBarTextColor"])
292296
}
@@ -341,7 +345,7 @@ struct SearchView: View {
341345

342346
ZStack(alignment: .leading) {
343347
if model.searchState.query.isEmpty {
344-
Text("Search forums...")
348+
Text(model.threadID == nil ? "Search forums..." : "Search thread...")
345349
.foregroundColor(theme[color: "listSecondaryTextColor"])
346350
}
347351

@@ -617,20 +621,23 @@ final class SearchPageViewModel: ObservableObject {
617621
private let isPreview: Bool
618622
private var searchQueryID: String?
619623
private let previewHTML: String?
620-
624+
let threadID: String?
625+
621626
init(
622627
forumSelectOptions: [ForumSelectOption] = [],
623628
searchHelpHints: [SearchHelpHint] = [],
624629
searchResults: [SearchResult] = [],
625630
isPreview: Bool = false,
626-
previewHTML: String? = nil
631+
previewHTML: String? = nil,
632+
threadID: String? = nil
627633
) {
628634
self.forumSelectOptions = forumSelectOptions
629635
self.searchHelpHints = searchHelpHints
630636
self.searchResults = searchResults
631637
self.isPreview = isPreview
632638
self.previewHTML = previewHTML
633-
639+
self.threadID = threadID
640+
634641
// Move the Task creation to after initialization
635642
Task { [weak self] in
636643
await self?.loadInitialData()
@@ -831,14 +838,19 @@ final class SearchPageViewModel: ObservableObject {
831838

832839
func performSearch() async {
833840
searchState.message = ""
834-
841+
835842
let forumIDs = forumSelectOptions
836843
.filter(\.isSelected)
837844
.map(\.value)
838-
845+
846+
let outgoingQuery: String = {
847+
guard let threadID, !threadID.isEmpty else { return searchState.query }
848+
return "threadid:\(threadID) \(searchState.query)"
849+
}()
850+
839851
do {
840852
let document = try await ForumsClient.shared.searchForums(
841-
query: searchState.query,
853+
query: outgoingQuery,
842854
forumIDs: forumIDs
843855
)
844856

@@ -935,8 +947,8 @@ extension Int {
935947
final class SearchHostingController: UIHostingController<AnyView> {
936948
private let searchModel: SearchPageViewModel
937949

938-
init() {
939-
self.searchModel = SearchPageViewModel()
950+
init(threadID: String? = nil) {
951+
self.searchModel = SearchPageViewModel(threadID: threadID)
940952
super.init(rootView: AnyView(SearchView(model: searchModel).themed()))
941953
}
942954

0 commit comments

Comments
 (0)