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>
This commit is contained in:
@@ -9,12 +9,12 @@ import SwiftUI
|
|||||||
|
|
||||||
struct SupporterBadge: View {
|
struct SupporterBadge: View {
|
||||||
let percent: Int?
|
let percent: Int?
|
||||||
let purple_badge_info: DamusPurple.UserBadgeInfo?
|
let purple_account: DamusPurple.Account?
|
||||||
let style: Style
|
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.percent = percent
|
||||||
self.purple_badge_info = purple_badge_info
|
self.purple_account = purple_account
|
||||||
self.style = style
|
self.style = style
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,15 +22,15 @@ struct SupporterBadge: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
if let purple_badge_info, purple_badge_info.active == true {
|
if let purple_account, purple_account.active == true {
|
||||||
HStack(spacing: 1) {
|
HStack(spacing: 1) {
|
||||||
Image("star.fill")
|
Image("star.fill")
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width:size, height:size)
|
.frame(width:size, height:size)
|
||||||
.foregroundStyle(GoldGradient)
|
.foregroundStyle(GoldGradient)
|
||||||
if self.style == .full,
|
if self.style == .full,
|
||||||
let ordinal_number = self.purple_badge_info?.subscriber_number,
|
let ordinal_number = self.purple_account?.subscriber_number,
|
||||||
let ordinal = self.purple_badge_info?.ordinal() {
|
let ordinal = self.purple_account?.ordinal() {
|
||||||
Text(ordinal)
|
Text(ordinal)
|
||||||
.foregroundStyle(DamusColors.gold)
|
.foregroundStyle(DamusColors.gold)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
@@ -85,7 +85,7 @@ struct SupporterBadge_Previews: PreviewProvider {
|
|||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
SupporterBadge(
|
SupporterBadge(
|
||||||
percent: nil,
|
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
|
style: .full
|
||||||
)
|
)
|
||||||
.frame(width: 100)
|
.frame(width: 100)
|
||||||
|
|||||||
@@ -10,17 +10,17 @@ import Foundation
|
|||||||
class DamusPurple: StoreObserverDelegate {
|
class DamusPurple: StoreObserverDelegate {
|
||||||
let settings: UserSettingsStore
|
let settings: UserSettingsStore
|
||||||
let keypair: Keypair
|
let keypair: Keypair
|
||||||
var starred_profiles_cache: [Pubkey: UserBadgeInfo]
|
var account_cache: [Pubkey: Account]
|
||||||
|
|
||||||
init(settings: UserSettingsStore, keypair: Keypair) {
|
init(settings: UserSettingsStore, keypair: Keypair) {
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
self.keypair = keypair
|
self.keypair = keypair
|
||||||
self.starred_profiles_cache = [:]
|
self.account_cache = [:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Functions
|
// MARK: Functions
|
||||||
func is_profile_subscribed_to_purple(pubkey: Pubkey) async -> Bool? {
|
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 {
|
var environment: DamusPurpleEnvironment {
|
||||||
@@ -38,25 +38,6 @@ class DamusPurple: StoreObserverDelegate {
|
|||||||
return self.settings.enable_experimental_purple_iap_support
|
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? {
|
func account_exists(pubkey: Pubkey) async -> Bool? {
|
||||||
guard let account_data = try? await self.get_account_data(pubkey: pubkey) else { return nil }
|
guard let account_data = try? await self.get_account_data(pubkey: pubkey) else { return nil }
|
||||||
|
|
||||||
@@ -67,9 +48,20 @@ class DamusPurple: StoreObserverDelegate {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func get_account(pubkey: Pubkey) async throws -> Account? {
|
func get_maybe_cached_account(pubkey: Pubkey) async throws -> Account? {
|
||||||
guard let data = try await self.get_account_data(pubkey: pubkey) else { return nil }
|
if let account = self.account_cache[pubkey] {
|
||||||
return Account.from(json_data: data)
|
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? {
|
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 {
|
struct Account {
|
||||||
let pubkey: Pubkey
|
let pubkey: Pubkey
|
||||||
let created_at: Date
|
let created_at: Date
|
||||||
let expiry: Date
|
let expiry: Date
|
||||||
let subscriber_number: UInt
|
let subscriber_number: Int
|
||||||
let active: Bool
|
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? {
|
static func from(json_data: Data) -> Self? {
|
||||||
guard let payload = try? JSONDecoder().decode(Payload.self, from: json_data) else { return nil }
|
guard let payload = try? JSONDecoder().decode(Payload.self, from: json_data) else { return nil }
|
||||||
return Self.from(payload: payload)
|
return Self.from(payload: payload)
|
||||||
@@ -251,7 +234,7 @@ class DamusPurple: StoreObserverDelegate {
|
|||||||
pubkey: pubkey,
|
pubkey: pubkey,
|
||||||
created_at: Date.init(timeIntervalSince1970: TimeInterval(payload.created_at)),
|
created_at: Date.init(timeIntervalSince1970: TimeInterval(payload.created_at)),
|
||||||
expiry: Date.init(timeIntervalSince1970: TimeInterval(payload.expiry)),
|
expiry: Date.init(timeIntervalSince1970: TimeInterval(payload.expiry)),
|
||||||
subscriber_number: payload.subscriber_number,
|
subscriber_number: Int(payload.subscriber_number),
|
||||||
active: payload.active
|
active: payload.active
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ struct EventProfileName: View {
|
|||||||
@State var display_name: DisplayName?
|
@State var display_name: DisplayName?
|
||||||
@State var nip05: NIP05?
|
@State var nip05: NIP05?
|
||||||
@State var donation: Int?
|
@State var donation: Int?
|
||||||
@State var purple_badge: DamusPurple.UserBadgeInfo?
|
@State var purple_account: DamusPurple.Account?
|
||||||
|
|
||||||
let size: EventViewKind
|
let size: EventViewKind
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ struct EventProfileName: View {
|
|||||||
self.size = size
|
self.size = size
|
||||||
let donation = damus.ndb.lookup_profile(pubkey)?.map({ p in p?.profile?.damus_donation }).value
|
let donation = damus.ndb.lookup_profile(pubkey)?.map({ p in p?.profile?.damus_donation }).value
|
||||||
self._donation = State(wrappedValue: donation)
|
self._donation = State(wrappedValue: donation)
|
||||||
self.purple_badge = nil
|
self.purple_account = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var friend_type: FriendType? {
|
var friend_type: FriendType? {
|
||||||
@@ -94,7 +94,7 @@ struct EventProfileName: View {
|
|||||||
.frame(width: 14, height: 14)
|
.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
|
.onReceive(handle_notify(.profile_updated)) { update in
|
||||||
if update.pubkey != pubkey {
|
if update.pubkey != pubkey {
|
||||||
@@ -119,13 +119,11 @@ struct EventProfileName: View {
|
|||||||
donation = profile.damus_donation
|
donation = profile.damus_donation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear(perform: {
|
.task {
|
||||||
Task {
|
if damus_state.purple.enable_purple {
|
||||||
if damus_state.purple.enable_purple {
|
self.purple_account = try? await damus_state.purple.get_maybe_cached_account(pubkey: pubkey)
|
||||||
self.purple_badge = await damus_state.purple.profile_purple_badge_info(pubkey: pubkey)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ struct ProfileName: View {
|
|||||||
@State var display_name: DisplayName?
|
@State var display_name: DisplayName?
|
||||||
@State var nip05: NIP05?
|
@State var nip05: NIP05?
|
||||||
@State var donation: Int?
|
@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) {
|
init(pubkey: Pubkey, prefix: String = "", damus: DamusState, show_nip5_domain: Bool = true) {
|
||||||
self.pubkey = pubkey
|
self.pubkey = pubkey
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
self.damus_state = damus
|
self.damus_state = damus
|
||||||
self.show_nip5_domain = show_nip5_domain
|
self.show_nip5_domain = show_nip5_domain
|
||||||
self.purple_badge = nil
|
self.purple_account = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var friend_type: FriendType? {
|
var friend_type: FriendType? {
|
||||||
@@ -109,15 +109,15 @@ struct ProfileName: View {
|
|||||||
.frame(width: 14, height: 14)
|
.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 {
|
||||||
Task {
|
if damus_state.purple.enable_purple {
|
||||||
if damus_state.purple.enable_purple {
|
self.purple_account = try? await damus_state.purple.get_maybe_cached_account(pubkey: pubkey)
|
||||||
self.purple_badge = await damus_state.purple.profile_purple_badge_info(pubkey: pubkey)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.onReceive(handle_notify(.profile_updated)) { update in
|
.onReceive(handle_notify(.profile_updated)) { update in
|
||||||
if update.pubkey != pubkey {
|
if update.pubkey != pubkey {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ struct DamusPurpleAccountView: View {
|
|||||||
|
|
||||||
SupporterBadge(
|
SupporterBadge(
|
||||||
percent: nil,
|
percent: nil,
|
||||||
purple_badge_info: DamusPurple.UserBadgeInfo.from(account: account),
|
purple_account: account,
|
||||||
style: .full
|
style: .full
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ struct DamusPurpleNewUserOnboardingView: View {
|
|||||||
.ignoresSafeArea() // Necessary to avoid weird white edges
|
.ignoresSafeArea() // Necessary to avoid weird white edges
|
||||||
}
|
}
|
||||||
.task {
|
.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
|
return
|
||||||
}
|
}
|
||||||
// Let's notify other views across SwiftUI to update our user's Purple status.
|
// Let's notify other views across SwiftUI to update our user's Purple status.
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ struct DamusPurpleView: View {
|
|||||||
|
|
||||||
func load_account() async {
|
func load_account() async {
|
||||||
do {
|
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)
|
self.my_account_info_state = .loaded(account: account)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -232,7 +232,8 @@ struct DamusPurpleView: View {
|
|||||||
|
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
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 {
|
Task {
|
||||||
await self.damus_state.purple.send_receipt()
|
await self.damus_state.purple.send_receipt()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user