Making some changes to the view model. braking but we will survive

This commit is contained in:
Sam DuBois
2022-12-18 16:37:53 -07:00
parent 1ef85b5c85
commit fbde055fc6
6 changed files with 255 additions and 158 deletions

View File

@@ -9,65 +9,9 @@ import SwiftUI
import Starscream
import Kingfisher
var BOOTSTRAP_RELAYS = [
"wss://relay.damus.io",
"wss://nostr-relay.wlvs.space",
"wss://nostr.oxtr.dev",
]
struct TimestampedProfile {
let profile: Profile
let timestamp: Int64
}
enum Sheets: Identifiable {
case post
case reply(NostrEvent)
var id: String {
switch self {
case .post: return "post"
case .reply(let ev): return "reply-" + ev.id
}
}
}
enum ThreadState {
case event_details
case chatroom
}
enum FilterState : Int {
case posts_and_replies = 1
case posts = 0
}
struct ContentView: View {
let keypair: Keypair
var pubkey: String {
return keypair.pubkey
}
var privkey: String? {
return keypair.privkey
}
@State var status: String = "Not connected"
@State var active_sheet: Sheets? = nil
@State var damus_state: DamusState? = nil
@State var selected_timeline: Timeline? = .home
@State var is_thread_open: Bool = false
@State var is_profile_open: Bool = false
@State var event: NostrEvent? = nil
@State var active_profile: String? = nil
@State var active_search: NostrFilter? = nil
@State var active_event_id: String? = nil
@State var profile_open: Bool = false
@State var thread_open: Bool = false
@State var search_open: Bool = false
@State var filter_state : FilterState = .posts_and_replies
@StateObject var home: HomeModel = HomeModel()
@EnvironmentObject var viewModel: DamusViewModel
// connect retry timer
let timer = Timer.publish(every: 4, on: .main, in: .common).autoconnect()
@@ -80,9 +24,9 @@ struct ContentView: View {
VStack{
ZStack {
if let damus = self.damus_state {
TimelineView(events: $home.events, loading: $home.loading, damus: damus, show_friend_icon: false, filter: filter_event)
TimelineView(events: viewModel.$home.events, loading: viewModel.$home.loading, damus: damus, show_friend_icon: false, filter: filter_event)
}
if privkey != nil {
if viewModel.privkey != nil {
PostButtonContainer {
self.active_sheet = .post
}
@@ -103,7 +47,7 @@ struct ContentView: View {
var FiltersView: some View {
VStack{
Picker("Filter State", selection: $filter_state) {
Picker("Filter State", selection: $viewModel.filter_state) {
Text("Posts").tag(FilterState.posts)
Text("Posts & Replies").tag(FilterState.posts_and_replies)
}
@@ -112,7 +56,7 @@ struct ContentView: View {
}
func filter_event(_ ev: NostrEvent) -> Bool {
if self.filter_state == .posts {
if viewModel.filter_state == .posts {
return !ev.is_reply(nil)
}
@@ -121,18 +65,18 @@ struct ContentView: View {
func MainContent(damus: DamusState) -> some View {
VStack {
NavigationLink(destination: MaybeProfileView, isActive: $profile_open) {
NavigationLink(destination: MaybeProfileView, isActive: $viewModel.profile_open) {
EmptyView()
}
NavigationLink(destination: MaybeThreadView, isActive: $thread_open) {
NavigationLink(destination: MaybeThreadView, isActive: $viewModel.thread_open) {
EmptyView()
}
NavigationLink(destination: MaybeSearchView, isActive: $search_open) {
NavigationLink(destination: MaybeSearchView, isActive: $viewModel.search_open) {
EmptyView()
}
switch selected_timeline {
case .search:
SearchHomeView(damus_state: damus_state!, model: SearchHomeModel(damus_state: damus_state!))
SearchHomeView(damus_state: viewModel.state!, model: SearchHomeModel(damus_state: damus_state!))
case .home:
PostingTimelineView
@@ -209,18 +153,16 @@ struct ContentView: View {
}
ToolbarItem(placement: .navigationBarTrailing) {
HStack(alignment: .center) {
if home.signal.signal != home.signal.max_signal {
Text("\(home.signal.signal)/\(home.signal.max_signal)")
.font(.callout)
.foregroundColor(.gray)
}
NavigationLink(destination: ConfigView(state: damus_state!)) {
Label("", systemImage: "gear")
if #available(iOS 16.0, *) {
Image(systemName: "chart.bar.fill", variableValue: Double(home.signal.signal) / Double(home.signal.max_signal))
.font(.body.weight(.ultraLight))
.symbolRenderingMode(.hierarchical)
} else {
// Fallback on earlier versions
}
}
.buttonStyle(PlainButtonStyle())
}
}
}
}
@@ -359,54 +301,6 @@ struct ContentView: View {
self.damus_state?.pool.connect_to_disconnected()
}
}
func switch_timeline(_ timeline: Timeline) {
NotificationCenter.default.post(name: .switched_timeline, object: timeline)
if timeline == self.selected_timeline {
NotificationCenter.default.post(name: .scroll_to_top, object: nil)
return
}
self.selected_timeline = timeline
//NotificationCenter.default.post(name: .switched_timeline, object: timeline)
//self.selected_timeline = timeline
}
func add_relay(_ pool: RelayPool, _ relay: String) {
//add_rw_relay(pool, "wss://nostr-pub.wellorder.net")
add_rw_relay(pool, relay)
/*
let profile = Profile(name: relay, about: nil, picture: nil)
let ts = Int64(Date().timeIntervalSince1970)
let tsprofile = TimestampedProfile(profile: profile, timestamp: ts)
damus!.profiles.add(id: relay, profile: tsprofile)
*/
}
func connect() {
let pool = RelayPool()
for relay in BOOTSTRAP_RELAYS {
add_relay(pool, relay)
}
pool.register_handler(sub_id: sub_id, handler: home.handle_event)
self.damus_state = DamusState(pool: pool, keypair: keypair,
likes: EventCounter(our_pubkey: pubkey),
boosts: EventCounter(our_pubkey: pubkey),
contacts: Contacts(),
tips: TipCounter(our_pubkey: pubkey),
profiles: Profiles(),
dms: home.dms
)
home.damus_state = self.damus_state!
pool.connect()
}
}
struct ContentView_Previews: PreviewProvider {
@@ -424,31 +318,6 @@ func get_since_time(last_event: NostrEvent?) -> Int64? {
return nil
}
func ws_nostr_event(relay: String, ev: WebSocketEvent) -> NostrEvent? {
switch ev {
case .binary(let dat):
return NostrEvent(content: "binary data? \(dat.count) bytes", pubkey: relay)
case .cancelled:
return NostrEvent(content: "cancelled", pubkey: relay)
case .connected:
return NostrEvent(content: "connected", pubkey: relay)
case .disconnected:
return NostrEvent(content: "disconnected", pubkey: relay)
case .error(let err):
return NostrEvent(content: "error \(err.debugDescription)", pubkey: relay)
case .text(let txt):
return NostrEvent(content: "text \(txt)", pubkey: relay)
case .pong:
return NostrEvent(content: "pong", pubkey: relay)
case .ping:
return NostrEvent(content: "ping", pubkey: relay)
case .viabilityChanged(let b):
return NostrEvent(content: "viabilityChanged \(b)", pubkey: relay)
case .reconnectSuggested(let b):
return NostrEvent(content: "reconnectSuggested \(b)", pubkey: relay)
}
}
func is_notification(ev: NostrEvent, pubkey: String) -> Bool {
if ev.pubkey == pubkey {
return false
@@ -468,11 +337,6 @@ extension UINavigationController: UIGestureRecognizerDelegate {
}
}
struct LastNotification {
let id: String
let created_at: Int64
}
func get_last_event(_ timeline: Timeline) -> LastNotification? {
let str = timeline.rawValue
let last = UserDefaults.standard.string(forKey: "last_\(str)")

155
damus/DamusViewModel.swift Normal file
View File

@@ -0,0 +1,155 @@
//
// DamusViewModel.swift
// damus
//
// Created by Sam DuBois on 12/18/22.
//
import SwiftUI
import Starscream
import Kingfisher
class DamusViewModel: ObservableObject {
// MARK: Constants and Variables
/// User Keypair object
let keypair: Keypair
var pubkey: String {
return keypair.pubkey
}
var privkey: String? {
return keypair.privkey
}
/// Default relays to be used when setting up the user's account.
var BOOTSTRAP_RELAYS = [
"wss://relay.damus.io",
"wss://nostr-relay.wlvs.space",
"wss://nostr.oxtr.dev",
]
@Published var status: String = "Not connected"
@Published var state: DamusState? = nil
@Published var active_sheet: Sheets? = nil
@Published var selected_timeline: Timeline? = .home
@Published var is_thread_open: Bool = false
@Published var is_profile_open: Bool = false
@Published var event: NostrEvent? = nil
@Published var active_profile: String? = nil
@Published var active_search: String? = nil
@Published var active_event_id: String? = nil
@Published var profile_open: Bool = false
@Published var thread_open: Bool = false
@Published var search_open: Bool = false
@Published var filter_state: FilterState = .posts_and_replies
@Published var home: HomeModel = HomeModel()
// MARK: Functionality
func switch_timeline(_ timeline: Timeline) {
NotificationCenter.default.post(name: .switched_timeline, object: timeline)
if timeline == self.selected_timeline {
NotificationCenter.default.post(name: .scroll_to_top, object: nil)
return
}
self.selected_timeline = timeline
//NotificationCenter.default.post(name: .switched_timeline, object: timeline)
//self.selected_timeline = timeline
}
func add_relay(_ pool: RelayPool, _ relay: String) {
//add_rw_relay(pool, "wss://nostr-pub.wellorder.net")
add_rw_relay(pool, relay)
/*
let profile = Profile(name: relay, about: nil, picture: nil)
let ts = Int64(Date().timeIntervalSince1970)
let tsprofile = TimestampedProfile(profile: profile, timestamp: ts)
damus!.profiles.add(id: relay, profile: tsprofile)
*/
}
func connect() {
let pool = RelayPool()
for relay in BOOTSTRAP_RELAYS {
add_relay(pool, relay)
}
pool.register_handler(sub_id: sub_id, handler: home.handle_event)
self.state = DamusState(pool: pool, keypair: keypair,
likes: EventCounter(our_pubkey: pubkey),
boosts: EventCounter(our_pubkey: pubkey),
contacts: Contacts(),
tips: TipCounter(our_pubkey: pubkey),
profiles: Profiles(),
dms: home.dms
)
home.damus_state = self.state!
pool.connect()
}
}
struct TimestampedProfile {
let profile: Profile
let timestamp: Int64
}
enum Sheets: Identifiable {
case post
case reply(NostrEvent)
var id: String {
switch self {
case .post: return "post"
case .reply(let ev): return "reply-" + ev.id
}
}
}
enum ThreadState {
case event_details
case chatroom
}
enum FilterState : Int {
case posts_and_replies = 1
case posts = 0
}
func ws_nostr_event(relay: String, ev: WebSocketEvent) -> NostrEvent? {
switch ev {
case .binary(let dat):
return NostrEvent(content: "binary data? \(dat.count) bytes", pubkey: relay)
case .cancelled:
return NostrEvent(content: "cancelled", pubkey: relay)
case .connected:
return NostrEvent(content: "connected", pubkey: relay)
case .disconnected:
return NostrEvent(content: "disconnected", pubkey: relay)
case .error(let err):
return NostrEvent(content: "error \(err.debugDescription)", pubkey: relay)
case .text(let txt):
return NostrEvent(content: "text \(txt)", pubkey: relay)
case .pong:
return NostrEvent(content: "pong", pubkey: relay)
case .ping:
return NostrEvent(content: "ping", pubkey: relay)
case .viabilityChanged(let b):
return NostrEvent(content: "viabilityChanged \(b)", pubkey: relay)
case .reconnectSuggested(let b):
return NostrEvent(content: "reconnectSuggested \(b)", pubkey: relay)
}
}
struct LastNotification {
let id: String
let created_at: Int64
}

View File

@@ -0,0 +1,25 @@
//
// Constants.swift
// damus
//
// Created by Sam DuBois on 12/18/22.
//
import Foundation
public class Constants {
static let PUB_KEY = "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"
static let EXAMPLE_DEMOS = DamusState(pool: RelayPool(), keypair: Keypair(pubkey: PUB_KEY, privkey: "privkey"), likes: EventCounter(our_pubkey: PUB_KEY), boosts: EventCounter(our_pubkey: PUB_KEY), contacts: Contacts(), tips: TipCounter(our_pubkey: PUB_KEY), profiles: Profiles(), dms: DirectMessagesModel())
static let EXAMPLE_EVENTS = [
NostrEvent(content: "Icecream", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"),
NostrEvent(content: "This is a test for a really long note that somebody sent because they thought they were super cool or maybe they were just really excited to share something with the world.", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"),
NostrEvent(content: "Bonjour Le Monde", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"),
NostrEvent(content: "Why am I helping on this app? Because it's fun!", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"),
NostrEvent(content: "PIzza", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"),
NostrEvent(content: "Hello World! This is so cool!", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"),
NostrEvent(content: "Nostr - Damus... Haha get it?", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"),
]
}

View File

@@ -6,6 +6,7 @@
//
import SwiftUI
import Shimmer
enum TimelineAction {
case chillin
@@ -33,6 +34,28 @@ struct InnerTimelineView: View {
}
}
.padding(.horizontal)
.refreshable {
<#code#>
}
}
}
struct InnerTimelineRedactedView: View {
let events: [NostrEvent]
let damus: DamusState
let show_friend_icon: Bool
var body: some View {
VStack {
ForEach(events, id: \.id) { event in
EventView(event: event, highlight: .none, has_action_bar: true, damus: damus, show_friend_icon: show_friend_icon)
.buttonStyle(PlainButtonStyle())
}
}
.shimmer()
.redacted(reason: .placeholder)
.padding(.horizontal)
.disabled(true)
}
}
@@ -52,8 +75,7 @@ struct TimelineView: View {
ScrollViewReader { scroller in
ScrollView {
if loading {
ProgressView()
.progressViewStyle(.circular)
InnerTimelineRedactedView(events: Constants.EXAMPLE_EVENTS, damus: damus, show_friend_icon: true)
}
InnerTimelineView(events: $events, damus: damus, show_friend_icon: show_friend_icon, filter: filter)
}
@@ -67,13 +89,11 @@ struct TimelineView: View {
}
}
/*
struct TimelineView_Previews: PreviewProvider {
static var previews: some View {
TimelineView()
TimelineView(events: .constant(Constants.EXAMPLE_EVENTS), loading: .constant(true), damus: Constants.EXAMPLE_DEMOS, show_friend_icon: true, filter: { _ in true })
}
}
*/
struct NavigationLazyView<Content: View>: View {
@@ -85,4 +105,3 @@ struct NavigationLazyView<Content: View>: View {
build()
}
}