@@ -49,6 +49,8 @@
|
|||||||
4C3BEFDC281DCE6100B3DE84 /* Liked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDB281DCE6100B3DE84 /* Liked.swift */; };
|
4C3BEFDC281DCE6100B3DE84 /* Liked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDB281DCE6100B3DE84 /* Liked.swift */; };
|
||||||
4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */; };
|
4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */; };
|
||||||
4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C477C9D282C3A4800033AA3 /* TipCounter.swift */; };
|
4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C477C9D282C3A4800033AA3 /* TipCounter.swift */; };
|
||||||
|
4C5C7E68284ED36500A22DF5 /* SearchHomeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5C7E67284ED36500A22DF5 /* SearchHomeModel.swift */; };
|
||||||
|
4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5C7E69284EDE2E00A22DF5 /* SearchResultsView.swift */; };
|
||||||
4C5F9114283D694D0052CD1C /* FollowTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5F9113283D694D0052CD1C /* FollowTarget.swift */; };
|
4C5F9114283D694D0052CD1C /* FollowTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5F9113283D694D0052CD1C /* FollowTarget.swift */; };
|
||||||
4C5F9116283D855D0052CD1C /* EventsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5F9115283D855D0052CD1C /* EventsModel.swift */; };
|
4C5F9116283D855D0052CD1C /* EventsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5F9115283D855D0052CD1C /* EventsModel.swift */; };
|
||||||
4C5F9118283D88E40052CD1C /* FollowingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5F9117283D88E40052CD1C /* FollowingModel.swift */; };
|
4C5F9118283D88E40052CD1C /* FollowingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5F9117283D88E40052CD1C /* FollowingModel.swift */; };
|
||||||
@@ -154,6 +156,8 @@
|
|||||||
4C3BEFDB281DCE6100B3DE84 /* Liked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Liked.swift; sourceTree = "<group>"; };
|
4C3BEFDB281DCE6100B3DE84 /* Liked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Liked.swift; sourceTree = "<group>"; };
|
||||||
4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusState.swift; sourceTree = "<group>"; };
|
4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusState.swift; sourceTree = "<group>"; };
|
||||||
4C477C9D282C3A4800033AA3 /* TipCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TipCounter.swift; sourceTree = "<group>"; };
|
4C477C9D282C3A4800033AA3 /* TipCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TipCounter.swift; sourceTree = "<group>"; };
|
||||||
|
4C5C7E67284ED36500A22DF5 /* SearchHomeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHomeModel.swift; sourceTree = "<group>"; };
|
||||||
|
4C5C7E69284EDE2E00A22DF5 /* SearchResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsView.swift; sourceTree = "<group>"; };
|
||||||
4C5F9113283D694D0052CD1C /* FollowTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowTarget.swift; sourceTree = "<group>"; };
|
4C5F9113283D694D0052CD1C /* FollowTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowTarget.swift; sourceTree = "<group>"; };
|
||||||
4C5F9115283D855D0052CD1C /* EventsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsModel.swift; sourceTree = "<group>"; };
|
4C5F9115283D855D0052CD1C /* EventsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsModel.swift; sourceTree = "<group>"; };
|
||||||
4C5F9117283D88E40052CD1C /* FollowingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingModel.swift; sourceTree = "<group>"; };
|
4C5F9117283D88E40052CD1C /* FollowingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingModel.swift; sourceTree = "<group>"; };
|
||||||
@@ -254,6 +258,7 @@
|
|||||||
4C5F9115283D855D0052CD1C /* EventsModel.swift */,
|
4C5F9115283D855D0052CD1C /* EventsModel.swift */,
|
||||||
4C5F9117283D88E40052CD1C /* FollowingModel.swift */,
|
4C5F9117283D88E40052CD1C /* FollowingModel.swift */,
|
||||||
4C987B56283FD07F0042CE38 /* FollowersModel.swift */,
|
4C987B56283FD07F0042CE38 /* FollowersModel.swift */,
|
||||||
|
4C5C7E67284ED36500A22DF5 /* SearchHomeModel.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -291,6 +296,7 @@
|
|||||||
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */,
|
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */,
|
||||||
4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */,
|
4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */,
|
||||||
4C90BD17283A9EE5008EE7EF /* LoginView.swift */,
|
4C90BD17283A9EE5008EE7EF /* LoginView.swift */,
|
||||||
|
4C5C7E69284EDE2E00A22DF5 /* SearchResultsView.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -549,6 +555,7 @@
|
|||||||
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */,
|
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */,
|
||||||
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
|
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
|
||||||
4C363A8628234FDE006E126D /* ImageCache.swift in Sources */,
|
4C363A8628234FDE006E126D /* ImageCache.swift in Sources */,
|
||||||
|
4C5C7E68284ED36500A22DF5 /* SearchHomeModel.swift in Sources */,
|
||||||
4C75EFB728049D990006080F /* RelayPool.swift in Sources */,
|
4C75EFB728049D990006080F /* RelayPool.swift in Sources */,
|
||||||
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */,
|
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */,
|
||||||
4CEE2AF5280B29E600AB5EEF /* TimeAgo.swift in Sources */,
|
4CEE2AF5280B29E600AB5EEF /* TimeAgo.swift in Sources */,
|
||||||
@@ -591,6 +598,7 @@
|
|||||||
4C363A9C282838B9006E126D /* EventRef.swift in Sources */,
|
4C363A9C282838B9006E126D /* EventRef.swift in Sources */,
|
||||||
4C8682872814DE470026224F /* ProfileView.swift in Sources */,
|
4C8682872814DE470026224F /* ProfileView.swift in Sources */,
|
||||||
4C5F9114283D694D0052CD1C /* FollowTarget.swift in Sources */,
|
4C5F9114283D694D0052CD1C /* FollowTarget.swift in Sources */,
|
||||||
|
4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */,
|
||||||
4CE6DF1627F8DEBF00C66700 /* RelayConnection.swift in Sources */,
|
4CE6DF1627F8DEBF00C66700 /* RelayConnection.swift in Sources */,
|
||||||
4C3BEFD6281D995700B3DE84 /* ActionBarModel.swift in Sources */,
|
4C3BEFD6281D995700B3DE84 /* ActionBarModel.swift in Sources */,
|
||||||
4C363AA428296DEE006E126D /* SearchModel.swift in Sources */,
|
4C363AA428296DEE006E126D /* SearchModel.swift in Sources */,
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
switch selected_timeline {
|
switch selected_timeline {
|
||||||
case .search:
|
case .search:
|
||||||
SearchHomeView()
|
SearchHomeView(damus_state: damus_state!, model: SearchHomeModel(pool: damus_state!.pool) )
|
||||||
|
|
||||||
case .home:
|
case .home:
|
||||||
PostingTimelineView
|
PostingTimelineView
|
||||||
|
|||||||
60
damus/Models/SearchHomeModel.swift
Normal file
60
damus/Models/SearchHomeModel.swift
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// SearchHomeModel.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by William Casarin on 2022-06-06.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
/// The data model for the SearchHome view, typically something global-like
|
||||||
|
class SearchHomeModel: ObservableObject {
|
||||||
|
@Published var events: [NostrEvent] = []
|
||||||
|
let pool: RelayPool
|
||||||
|
let sub_id = UUID().description
|
||||||
|
let limit: UInt32 = 1000
|
||||||
|
|
||||||
|
init(pool: RelayPool) {
|
||||||
|
self.pool = pool
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_base_filter() -> NostrFilter {
|
||||||
|
var filter = NostrFilter.filter_text
|
||||||
|
filter.limit = self.limit
|
||||||
|
filter.until = Int64(Date.now.timeIntervalSince1970)
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
|
||||||
|
func subscribe() {
|
||||||
|
pool.subscribe(sub_id: sub_id, filters: [get_base_filter()], handler: handle_event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsubscribe() {
|
||||||
|
pool.unsubscribe(sub_id: sub_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handle_event(relay_id: String, conn_ev: NostrConnectionEvent) {
|
||||||
|
switch conn_ev {
|
||||||
|
case .ws_event:
|
||||||
|
break
|
||||||
|
case .nostr_event(let event):
|
||||||
|
switch event {
|
||||||
|
case .event(let sub_id, let ev):
|
||||||
|
guard sub_id == self.sub_id else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard self.events.count <= limit else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ev.kind == NostrKind.text.rawValue {
|
||||||
|
let _ = insert_uniq_sorted_event(events: &events, new_ev: ev) {
|
||||||
|
$0.created_at > $1.created_at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .notice(let msg):
|
||||||
|
print("search home notice: \(msg)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,15 +6,68 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import CryptoKit
|
||||||
|
|
||||||
struct SearchHomeView: View {
|
struct SearchHomeView: View {
|
||||||
|
let damus_state: DamusState
|
||||||
|
@StateObject var model: SearchHomeModel
|
||||||
|
@State var search: String = ""
|
||||||
|
|
||||||
|
var SearchInput: some View {
|
||||||
|
ZStack(alignment: .leading) {
|
||||||
|
TextField("", text: $search)
|
||||||
|
.padding(5)
|
||||||
|
.padding(.leading, 35)
|
||||||
|
.textInputAutocapitalization(.never)
|
||||||
|
Label("", systemImage: "magnifyingglass")
|
||||||
|
.padding(.leading, 10)
|
||||||
|
}
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 20)
|
||||||
|
.foregroundColor(.gray.opacity(0.2))
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
var GlobalContent: some View {
|
||||||
|
TimelineView(events: $model.events, damus: damus_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SearchContent: some View {
|
||||||
|
SearchResultsView(damus_state: damus_state, search: $search)
|
||||||
|
}
|
||||||
|
|
||||||
|
var MainContent: some View {
|
||||||
|
Group {
|
||||||
|
if search.isEmpty {
|
||||||
|
GlobalContent
|
||||||
|
} else {
|
||||||
|
SearchContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text("Search Home")
|
VStack {
|
||||||
|
SearchInput
|
||||||
|
|
||||||
|
MainContent
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
model.subscribe()
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
model.unsubscribe()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SearchHomeView_Previews: PreviewProvider {
|
struct SearchHomeView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
SearchHomeView()
|
let state = test_damus_state()
|
||||||
|
SearchHomeView(
|
||||||
|
damus_state: state,
|
||||||
|
model: SearchHomeModel(pool: state.pool)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
57
damus/Views/SearchResultsView.swift
Normal file
57
damus/Views/SearchResultsView.swift
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// SearchResultsView.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by William Casarin on 2022-06-06.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct SearchResultsView: View {
|
||||||
|
let damus_state: DamusState
|
||||||
|
@Binding var search: String
|
||||||
|
@State var results: [(String, Profile)] = []
|
||||||
|
|
||||||
|
func ProfileSearchResult(pk: String, res: Profile) -> some View {
|
||||||
|
FollowUserView(target: .pubkey(pk), damus_state: damus_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
var MainContent: some View {
|
||||||
|
VStack {
|
||||||
|
ForEach(results, id: \.0) { prof in
|
||||||
|
ProfileSearchResult(pk: prof.0, res: prof.1)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func search_changed(_ new: String) {
|
||||||
|
let profs = damus_state.profiles.profiles.enumerated()
|
||||||
|
self.results = profs.reduce(into: []) { acc, els in
|
||||||
|
let pk = els.element.key
|
||||||
|
let prof = els.element.value.profile
|
||||||
|
let lowname = prof.name.map { $0.lowercased() }
|
||||||
|
let lowdisp = prof.display_name.map { $0.lowercased() }
|
||||||
|
let ok = new == pk || String(new.dropFirst()) == pk
|
||||||
|
|| lowname?.contains(new) ?? false
|
||||||
|
|| lowdisp?.contains(new) ?? false
|
||||||
|
if ok {
|
||||||
|
acc.append((pk, prof))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
MainContent
|
||||||
|
.frame(maxHeight: .infinity)
|
||||||
|
.onChange(of: search) { new in search_changed(new) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SearchResultsView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
let search = Binding<String>.init(get: { "jb55" }, set: { _ in })
|
||||||
|
SearchResultsView(damus_state: test_damus_state(), search: search)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,10 +37,13 @@ func describe_search(_ filter: NostrFilter) -> String {
|
|||||||
return "Search"
|
return "Search"
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
struct SearchView_Previews: PreviewProvider {
|
struct SearchView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
SearchView()
|
let test_state = test_damus_state()
|
||||||
|
let filter = NostrFilter.filter_hashtag(["bitcoin"])
|
||||||
|
let pool = test_state.pool
|
||||||
|
let model = SearchModel(pool: pool, search: filter)
|
||||||
|
|
||||||
|
SearchView(appstate: test_state, search: model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
Reference in New Issue
Block a user