damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit f06b88213985faf3b8e1448aa50bdcd88ac0870e
parent fe177bdb9e4aeedf16d79420d345f8e7d07d6bc0
Author: William Casarin <jb55@jb55.com>
Date:   Tue, 30 Jan 2024 17:30:12 -0800

purple: consolidate UserBadgeInfo with Account

Rename get_account to fetch_account to make it clear that it is always a
call to the server.

Add get_maybe_cached_account method that checks cached before calling
fetch_account.

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdamus/Components/SupporterBadge.swift | 14+++++++-------
Mdamus/Models/Purple/DamusPurple.swift | 75+++++++++++++++++++++++++++++----------------------------------------------
Mdamus/Views/Profile/EventProfileName.swift | 18++++++++----------
Mdamus/Views/Profile/ProfileName.swift | 20++++++++++----------
Mdamus/Views/Purple/DamusPurpleAccountView.swift | 2+-
Mdamus/Views/Purple/DamusPurpleNewUserOnboardingView.swift | 2+-
Mdamus/Views/Purple/DamusPurpleView.swift | 5+++--
7 files changed, 59 insertions(+), 77 deletions(-)

diff --git a/damus/Components/SupporterBadge.swift b/damus/Components/SupporterBadge.swift @@ -9,12 +9,12 @@ import SwiftUI struct SupporterBadge: View { let percent: Int? - let purple_badge_info: DamusPurple.UserBadgeInfo? + let purple_account: DamusPurple.Account? let style: Style - init(percent: Int?, purple_badge_info: DamusPurple.UserBadgeInfo? = nil, style: Style) { + init(percent: Int?, purple_account: DamusPurple.Account? = nil, style: Style) { self.percent = percent - self.purple_badge_info = purple_badge_info + self.purple_account = purple_account self.style = style } @@ -22,15 +22,15 @@ struct SupporterBadge: View { var body: some View { HStack { - if let purple_badge_info, purple_badge_info.active == true { + if let purple_account, purple_account.active == true { HStack(spacing: 1) { Image("star.fill") .resizable() .frame(width:size, height:size) .foregroundStyle(GoldGradient) if self.style == .full, - let ordinal_number = self.purple_badge_info?.subscriber_number, - let ordinal = self.purple_badge_info?.ordinal() { + let ordinal_number = self.purple_account?.subscriber_number, + let ordinal = self.purple_account?.ordinal() { Text(ordinal) .foregroundStyle(DamusColors.gold) .font(.caption) @@ -85,7 +85,7 @@ struct SupporterBadge_Previews: PreviewProvider { HStack(alignment: .center) { SupporterBadge( percent: nil, - purple_badge_info: DamusPurple.UserBadgeInfo(active: true, subscriber_number: subscriber_number), + purple_account: DamusPurple.Account(pubkey: test_pubkey, created_at: .now, expiry: .now.addingTimeInterval(10000), subscriber_number: subscriber_number, active: true), style: .full ) .frame(width: 100) diff --git a/damus/Models/Purple/DamusPurple.swift b/damus/Models/Purple/DamusPurple.swift @@ -10,17 +10,17 @@ import Foundation class DamusPurple: StoreObserverDelegate { let settings: UserSettingsStore let keypair: Keypair - var starred_profiles_cache: [Pubkey: UserBadgeInfo] - + var account_cache: [Pubkey: Account] + init(settings: UserSettingsStore, keypair: Keypair) { self.settings = settings self.keypair = keypair - self.starred_profiles_cache = [:] + self.account_cache = [:] } // MARK: Functions func is_profile_subscribed_to_purple(pubkey: Pubkey) async -> Bool? { - return await self.profile_purple_badge_info(pubkey: pubkey)?.active + return try? await self.get_maybe_cached_account(pubkey: pubkey)?.active } var environment: DamusPurpleEnvironment { @@ -38,25 +38,6 @@ class DamusPurple: StoreObserverDelegate { return self.settings.enable_experimental_purple_iap_support } - func profile_purple_badge_info(pubkey: Pubkey) async -> UserBadgeInfo? { - if let cached_result = self.starred_profiles_cache[pubkey] { - return cached_result - } - - guard let data = try? await self.get_account_data(pubkey: pubkey) else { return nil } - - guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { return nil } - - if let active = json["active"] as? Bool { - let subscriber_number: Int? = json["subscriber_number"] as? Int - let badge_info = UserBadgeInfo(active: active, subscriber_number: subscriber_number) - self.starred_profiles_cache[pubkey] = badge_info - return badge_info - } - - return nil - } - func account_exists(pubkey: Pubkey) async -> Bool? { guard let account_data = try? await self.get_account_data(pubkey: pubkey) else { return nil } @@ -66,10 +47,21 @@ class DamusPurple: StoreObserverDelegate { return false } - - func get_account(pubkey: Pubkey) async throws -> Account? { - guard let data = try await self.get_account_data(pubkey: pubkey) else { return nil } - return Account.from(json_data: data) + + func get_maybe_cached_account(pubkey: Pubkey) async throws -> Account? { + if let account = self.account_cache[pubkey] { + return account + } + return try await fetch_account(pubkey: pubkey) + } + + func fetch_account(pubkey: Pubkey) async throws -> Account? { + guard let data = try await self.get_account_data(pubkey: pubkey) , + let account = Account.from(json_data: data) else { + return nil + } + self.account_cache[pubkey] = account + return account } func get_account_data(pubkey: Pubkey) async throws -> Data? { @@ -217,29 +209,20 @@ class DamusPurple: StoreObserverDelegate { } - struct UserBadgeInfo { - var active: Bool - var subscriber_number: Int? - - func ordinal() -> String? { - guard let number = self.subscriber_number else { return nil } - let formatter = NumberFormatter() - formatter.numberStyle = .ordinal - return formatter.string(from: NSNumber(integerLiteral: number)) - } - - static func from(account: Account) -> Self { - return UserBadgeInfo(active: account.active, subscriber_number: Int(account.subscriber_number)) - } - } - struct Account { let pubkey: Pubkey let created_at: Date let expiry: Date - let subscriber_number: UInt + let subscriber_number: Int let active: Bool - + + func ordinal() -> String? { + let number = Int(self.subscriber_number) + let formatter = NumberFormatter() + formatter.numberStyle = .ordinal + return formatter.string(from: NSNumber(integerLiteral: number)) + } + static func from(json_data: Data) -> Self? { guard let payload = try? JSONDecoder().decode(Payload.self, from: json_data) else { return nil } return Self.from(payload: payload) @@ -251,7 +234,7 @@ class DamusPurple: StoreObserverDelegate { pubkey: pubkey, created_at: Date.init(timeIntervalSince1970: TimeInterval(payload.created_at)), expiry: Date.init(timeIntervalSince1970: TimeInterval(payload.expiry)), - subscriber_number: payload.subscriber_number, + subscriber_number: Int(payload.subscriber_number), active: payload.active ) } diff --git a/damus/Views/Profile/EventProfileName.swift b/damus/Views/Profile/EventProfileName.swift @@ -16,8 +16,8 @@ struct EventProfileName: View { @State var display_name: DisplayName? @State var nip05: NIP05? @State var donation: Int? - @State var purple_badge: DamusPurple.UserBadgeInfo? - + @State var purple_account: DamusPurple.Account? + let size: EventViewKind init(pubkey: Pubkey, damus: DamusState, size: EventViewKind = .normal) { @@ -26,7 +26,7 @@ struct EventProfileName: View { self.size = size let donation = damus.ndb.lookup_profile(pubkey)?.map({ p in p?.profile?.damus_donation }).value self._donation = State(wrappedValue: donation) - self.purple_badge = nil + self.purple_account = nil } var friend_type: FriendType? { @@ -94,7 +94,7 @@ struct EventProfileName: View { .frame(width: 14, height: 14) } - SupporterBadge(percent: self.supporter_percentage(), purple_badge_info: self.purple_badge, style: .compact) + SupporterBadge(percent: self.supporter_percentage(), purple_account: self.purple_account, style: .compact) } .onReceive(handle_notify(.profile_updated)) { update in if update.pubkey != pubkey { @@ -119,13 +119,11 @@ struct EventProfileName: View { donation = profile.damus_donation } } - .onAppear(perform: { - Task { - if damus_state.purple.enable_purple { - self.purple_badge = await damus_state.purple.profile_purple_badge_info(pubkey: pubkey) - } + .task { + if damus_state.purple.enable_purple { + self.purple_account = try? await damus_state.purple.get_maybe_cached_account(pubkey: pubkey) } - }) + } } } diff --git a/damus/Views/Profile/ProfileName.swift b/damus/Views/Profile/ProfileName.swift @@ -41,14 +41,14 @@ struct ProfileName: View { @State var display_name: DisplayName? @State var nip05: NIP05? @State var donation: Int? - @State var purple_badge: DamusPurple.UserBadgeInfo? - + @State var purple_account: DamusPurple.Account? + init(pubkey: Pubkey, prefix: String = "", damus: DamusState, show_nip5_domain: Bool = true) { self.pubkey = pubkey self.prefix = prefix self.damus_state = damus self.show_nip5_domain = show_nip5_domain - self.purple_badge = nil + self.purple_account = nil } var friend_type: FriendType? { @@ -109,15 +109,15 @@ struct ProfileName: View { .frame(width: 14, height: 14) } - SupporterBadge(percent: supporter(profile: profile), purple_badge_info: self.purple_badge, style: .full) + SupporterBadge(percent: supporter(profile: profile), purple_account: self.purple_account, style: .compact) + + } - .onAppear(perform: { - Task { - if damus_state.purple.enable_purple { - self.purple_badge = await damus_state.purple.profile_purple_badge_info(pubkey: pubkey) - } + .task { + if damus_state.purple.enable_purple { + self.purple_account = try? await damus_state.purple.get_maybe_cached_account(pubkey: pubkey) } - }) + } .onReceive(handle_notify(.profile_updated)) { update in if update.pubkey != pubkey { return diff --git a/damus/Views/Purple/DamusPurpleAccountView.swift b/damus/Views/Purple/DamusPurpleAccountView.swift @@ -83,7 +83,7 @@ struct DamusPurpleAccountView: View { SupporterBadge( percent: nil, - purple_badge_info: DamusPurple.UserBadgeInfo.from(account: account), + purple_account: account, style: .full ) } diff --git a/damus/Views/Purple/DamusPurpleNewUserOnboardingView.swift b/damus/Views/Purple/DamusPurpleNewUserOnboardingView.swift @@ -32,7 +32,7 @@ struct DamusPurpleNewUserOnboardingView: View { .ignoresSafeArea() // Necessary to avoid weird white edges } .task { - guard let account = try? await damus_state.purple.get_account(pubkey: damus_state.pubkey), account.active else { + guard let account = try? await damus_state.purple.fetch_account(pubkey: damus_state.pubkey), account.active else { return } // Let's notify other views across SwiftUI to update our user's Purple status. diff --git a/damus/Views/Purple/DamusPurpleView.swift b/damus/Views/Purple/DamusPurpleView.swift @@ -117,7 +117,7 @@ struct DamusPurpleView: View { func load_account() async { do { - if let account = try await damus_state.purple.get_account(pubkey: damus_state.keypair.pubkey) { + if let account = try await damus_state.purple.fetch_account(pubkey: damus_state.keypair.pubkey) { self.my_account_info_state = .loaded(account: account) return } @@ -232,7 +232,8 @@ struct DamusPurpleView: View { switch result { case .success: - self.damus_state.purple.starred_profiles_cache[keypair.pubkey] = nil + // TODO (will): why do this here? + //self.damus_state.purple.starred_profiles_cache[keypair.pubkey] = nil Task { await self.damus_state.purple.send_receipt() }