mirror of
git://jb55.com/damus
synced 2024-09-30 00:40:45 +00:00
purple: adapt to integrate better with the LN flow
Signed-off-by: Daniel D’Aquino <daniel@daquino.me> Reviewed-by: William Casarin <jb55@jb55.com> Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
parent
a6b430284f
commit
e649c49981
@ -442,6 +442,7 @@
|
|||||||
D72341192B6864F200E1E135 /* DamusPurpleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72341182B6864F200E1E135 /* DamusPurpleEnvironment.swift */; };
|
D72341192B6864F200E1E135 /* DamusPurpleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72341182B6864F200E1E135 /* DamusPurpleEnvironment.swift */; };
|
||||||
D723411A2B6864F200E1E135 /* DamusPurpleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72341182B6864F200E1E135 /* DamusPurpleEnvironment.swift */; };
|
D723411A2B6864F200E1E135 /* DamusPurpleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72341182B6864F200E1E135 /* DamusPurpleEnvironment.swift */; };
|
||||||
D723C38E2AB8D83400065664 /* ContentFilters.swift in Sources */ = {isa = PBXBuildFile; fileRef = D723C38D2AB8D83400065664 /* ContentFilters.swift */; };
|
D723C38E2AB8D83400065664 /* ContentFilters.swift in Sources */ = {isa = PBXBuildFile; fileRef = D723C38D2AB8D83400065664 /* ContentFilters.swift */; };
|
||||||
|
D724D8272B64B40B00ABE789 /* DamusPurpleAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D724D8262B64B40B00ABE789 /* DamusPurpleAccountView.swift */; };
|
||||||
D72A2D022AD9C136002AFF62 /* EventViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */; };
|
D72A2D022AD9C136002AFF62 /* EventViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */; };
|
||||||
D72A2D052AD9C1B5002AFF62 /* MockDamusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2D042AD9C1B5002AFF62 /* MockDamusState.swift */; };
|
D72A2D052AD9C1B5002AFF62 /* MockDamusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2D042AD9C1B5002AFF62 /* MockDamusState.swift */; };
|
||||||
D72A2D072AD9C1FB002AFF62 /* MockProfiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2D062AD9C1FB002AFF62 /* MockProfiles.swift */; };
|
D72A2D072AD9C1FB002AFF62 /* MockProfiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2D062AD9C1FB002AFF62 /* MockProfiles.swift */; };
|
||||||
@ -1335,6 +1336,7 @@
|
|||||||
D71DC1EB2A9129C3006E207C /* PostViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewTests.swift; sourceTree = "<group>"; };
|
D71DC1EB2A9129C3006E207C /* PostViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewTests.swift; sourceTree = "<group>"; };
|
||||||
D72341182B6864F200E1E135 /* DamusPurpleEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleEnvironment.swift; sourceTree = "<group>"; };
|
D72341182B6864F200E1E135 /* DamusPurpleEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleEnvironment.swift; sourceTree = "<group>"; };
|
||||||
D723C38D2AB8D83400065664 /* ContentFilters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentFilters.swift; sourceTree = "<group>"; };
|
D723C38D2AB8D83400065664 /* ContentFilters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentFilters.swift; sourceTree = "<group>"; };
|
||||||
|
D724D8262B64B40B00ABE789 /* DamusPurpleAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleAccountView.swift; sourceTree = "<group>"; };
|
||||||
D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventViewTests.swift; sourceTree = "<group>"; };
|
D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventViewTests.swift; sourceTree = "<group>"; };
|
||||||
D72A2D042AD9C1B5002AFF62 /* MockDamusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDamusState.swift; sourceTree = "<group>"; };
|
D72A2D042AD9C1B5002AFF62 /* MockDamusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDamusState.swift; sourceTree = "<group>"; };
|
||||||
D72A2D062AD9C1FB002AFF62 /* MockProfiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockProfiles.swift; sourceTree = "<group>"; };
|
D72A2D062AD9C1FB002AFF62 /* MockProfiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockProfiles.swift; sourceTree = "<group>"; };
|
||||||
@ -2576,6 +2578,7 @@
|
|||||||
D76556D52B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift */,
|
D76556D52B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift */,
|
||||||
D7ADD3DF2B538D4200F104C4 /* DamusPurpleURLSheetView.swift */,
|
D7ADD3DF2B538D4200F104C4 /* DamusPurpleURLSheetView.swift */,
|
||||||
D7ADD3E12B538E3500F104C4 /* DamusPurpleVerifyNpubView.swift */,
|
D7ADD3E12B538E3500F104C4 /* DamusPurpleVerifyNpubView.swift */,
|
||||||
|
D724D8262B64B40B00ABE789 /* DamusPurpleAccountView.swift */,
|
||||||
);
|
);
|
||||||
path = Purple;
|
path = Purple;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -3213,6 +3216,7 @@
|
|||||||
4CB88396296F7F8B00DC99E7 /* ReactionView.swift in Sources */,
|
4CB88396296F7F8B00DC99E7 /* ReactionView.swift in Sources */,
|
||||||
50A16FFD2AA7525700DFEC1F /* DamusVideoPlayerViewModel.swift in Sources */,
|
50A16FFD2AA7525700DFEC1F /* DamusVideoPlayerViewModel.swift in Sources */,
|
||||||
4CFF8F6B29CD0079008DB934 /* RepostedEvent.swift in Sources */,
|
4CFF8F6B29CD0079008DB934 /* RepostedEvent.swift in Sources */,
|
||||||
|
D724D8272B64B40B00ABE789 /* DamusPurpleAccountView.swift in Sources */,
|
||||||
4C8682872814DE470026224F /* ProfileView.swift in Sources */,
|
4C8682872814DE470026224F /* ProfileView.swift in Sources */,
|
||||||
5C0707D12A1ECB38004E7B51 /* DamusLogoGradient.swift in Sources */,
|
5C0707D12A1ECB38004E7B51 /* DamusLogoGradient.swift in Sources */,
|
||||||
4CDD1AE02A6B305F001CD4DF /* NdbTagElem.swift in Sources */,
|
4CDD1AE02A6B305F001CD4DF /* NdbTagElem.swift in Sources */,
|
||||||
|
@ -37,7 +37,7 @@ class DamusPurple: StoreObserverDelegate {
|
|||||||
return cached_result
|
return cached_result
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let data = await self.get_account_data(pubkey: pubkey) else { return nil }
|
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 }
|
guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { return nil }
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class DamusPurple: StoreObserverDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func account_exists(pubkey: Pubkey) async -> Bool? {
|
func account_exists(pubkey: Pubkey) async -> Bool? {
|
||||||
guard let account_data = 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 }
|
||||||
|
|
||||||
if let account_info = try? JSONDecoder().decode(AccountInfo.self, from: account_data) {
|
if let account_info = try? JSONDecoder().decode(AccountInfo.self, from: account_data) {
|
||||||
return account_info.pubkey == pubkey.hex()
|
return account_info.pubkey == pubkey.hex()
|
||||||
@ -61,19 +61,33 @@ class DamusPurple: StoreObserverDelegate {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func get_account_data(pubkey: Pubkey) async -> Data? {
|
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_account_data(pubkey: Pubkey) async throws -> Data? {
|
||||||
let url = environment.api_base_url().appendingPathComponent("accounts/\(pubkey.hex())")
|
let url = environment.api_base_url().appendingPathComponent("accounts/\(pubkey.hex())")
|
||||||
var request = URLRequest(url: url)
|
|
||||||
request.httpMethod = "GET"
|
|
||||||
|
|
||||||
do {
|
let (data, response) = try await make_nip98_authenticated_request(
|
||||||
let (data, _) = try await URLSession.shared.data(for: request)
|
method: .get,
|
||||||
return data
|
url: url,
|
||||||
} catch {
|
payload: nil,
|
||||||
print("Failed to fetch data: \(error)")
|
payload_type: nil,
|
||||||
|
auth_keypair: self.keypair
|
||||||
|
)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse {
|
||||||
|
switch httpResponse.statusCode {
|
||||||
|
case 200:
|
||||||
|
return data
|
||||||
|
case 404:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
throw PurpleError.http_response_error(status_code: httpResponse.statusCode, response: data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
throw PurpleError.error_processing_response
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func create_account(pubkey: Pubkey) async throws {
|
func create_account(pubkey: Pubkey) async throws {
|
||||||
@ -207,6 +221,42 @@ class DamusPurple: StoreObserverDelegate {
|
|||||||
formatter.numberStyle = .ordinal
|
formatter.numberStyle = .ordinal
|
||||||
return formatter.string(from: NSNumber(integerLiteral: number))
|
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 active: Bool
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(payload: Payload) -> Self? {
|
||||||
|
guard let pubkey = Pubkey(hex: payload.pubkey) else { return nil }
|
||||||
|
return Self(
|
||||||
|
pubkey: pubkey,
|
||||||
|
created_at: Date.init(timeIntervalSince1970: TimeInterval(payload.created_at)),
|
||||||
|
expiry: Date.init(timeIntervalSince1970: TimeInterval(payload.expiry)),
|
||||||
|
subscriber_number: payload.subscriber_number,
|
||||||
|
active: payload.active
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Payload: Codable {
|
||||||
|
let pubkey: String // Hex-encoded string
|
||||||
|
let created_at: UInt64 // Unix timestamp
|
||||||
|
let expiry: UInt64 // Unix timestamp
|
||||||
|
let subscriber_number: UInt
|
||||||
|
let active: Bool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,6 +276,8 @@ extension DamusPurple {
|
|||||||
extension DamusPurple {
|
extension DamusPurple {
|
||||||
enum PurpleError: Error {
|
enum PurpleError: Error {
|
||||||
case translation_error(status_code: Int, response: Data)
|
case translation_error(status_code: Int, response: Data)
|
||||||
|
case http_response_error(status_code: Int, response: Data)
|
||||||
|
case error_processing_response
|
||||||
case translation_no_response
|
case translation_no_response
|
||||||
case checkout_npub_verification_error
|
case checkout_npub_verification_error
|
||||||
}
|
}
|
||||||
|
158
damus/Views/Purple/DamusPurpleAccountView.swift
Normal file
158
damus/Views/Purple/DamusPurpleAccountView.swift
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
//
|
||||||
|
// DamusPurpleAccountView.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by Daniel D’Aquino on 2024-01-26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct DamusPurpleAccountView: View {
|
||||||
|
var colorScheme: ColorScheme = .dark
|
||||||
|
let damus_state: DamusState
|
||||||
|
let account: DamusPurple.Account
|
||||||
|
let pfp_size: CGFloat = 90.0
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
ProfilePicView(pubkey: account.pubkey, size: pfp_size, highlight: .custom(Color.black.opacity(0.4), 1.0), profiles: damus_state.profiles, disable_animation: damus_state.settings.disable_animation)
|
||||||
|
.background(Color.black.opacity(0.4).clipShape(Circle()))
|
||||||
|
.shadow(color: .black, radius: 10, x: 0.0, y: 5)
|
||||||
|
|
||||||
|
profile_name
|
||||||
|
|
||||||
|
if account.active {
|
||||||
|
active_account_badge
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inactive_account_badge
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Generalize this view instead of setting up dividers and paddings manually
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Text(NSLocalizedString("Expiry date", comment: "Label for Purple subscription expiry date"))
|
||||||
|
Spacer()
|
||||||
|
Text(DateFormatter.localizedString(from: account.expiry, dateStyle: .short, timeStyle: .none))
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.top, 20)
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text(NSLocalizedString("Account creation", comment: "Label for Purple account creation date"))
|
||||||
|
Spacer()
|
||||||
|
Text(DateFormatter.localizedString(from: account.created_at, dateStyle: .short, timeStyle: .none))
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text(NSLocalizedString("Subscriber number", comment: "Label for Purple account subscriber number"))
|
||||||
|
Spacer()
|
||||||
|
Text("#\(account.subscriber_number)")
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.bottom, 20)
|
||||||
|
}
|
||||||
|
.foregroundColor(.white.opacity(0.8))
|
||||||
|
.preferredColorScheme(.dark)
|
||||||
|
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 12, style: .continuous))
|
||||||
|
.padding()
|
||||||
|
|
||||||
|
Text(NSLocalizedString("Visit the Damus website on a web browser to manage billing", comment: "Instruction on how to manage billing externally"))
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.white.opacity(0.6))
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var profile_name: some View {
|
||||||
|
let display_name = self.profile_display_name()
|
||||||
|
return HStack(alignment: .center, spacing: 5) {
|
||||||
|
Text(display_name)
|
||||||
|
.font(.title)
|
||||||
|
.bold()
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
|
||||||
|
SupporterBadge(
|
||||||
|
percent: nil,
|
||||||
|
purple_badge_info: DamusPurple.UserBadgeInfo.from(account: account),
|
||||||
|
style: .full
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var active_account_badge: some View {
|
||||||
|
HStack(spacing: 3) {
|
||||||
|
Image("check-circle.fill")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 15, height: 15)
|
||||||
|
|
||||||
|
Text(NSLocalizedString("Active account", comment: "Badge indicating user has an active Damus Purple account"))
|
||||||
|
.font(.caption)
|
||||||
|
.bold()
|
||||||
|
}
|
||||||
|
.foregroundColor(Color.white)
|
||||||
|
.padding(.vertical, 3)
|
||||||
|
.padding(.horizontal, 8)
|
||||||
|
.background(PinkGradient)
|
||||||
|
.cornerRadius(30.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var inactive_account_badge: some View {
|
||||||
|
HStack(spacing: 3) {
|
||||||
|
Image("warning")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 15, height: 15)
|
||||||
|
|
||||||
|
Text(NSLocalizedString("Expired account", comment: "Badge indicating user has an expired Damus Purple account"))
|
||||||
|
.font(.caption)
|
||||||
|
.bold()
|
||||||
|
}
|
||||||
|
.foregroundColor(DamusColors.danger)
|
||||||
|
.padding(.vertical, 3)
|
||||||
|
.padding(.horizontal, 8)
|
||||||
|
.background(DamusColors.dangerTertiary)
|
||||||
|
.cornerRadius(30.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func profile_display_name() -> String {
|
||||||
|
let profile_txn: NdbTxn<ProfileRecord?>? = damus_state.profiles.lookup_with_timestamp(account.pubkey)
|
||||||
|
let profile: NdbProfile? = profile_txn?.unsafeUnownedValue?.profile
|
||||||
|
let display_name = parse_display_name(profile: profile, pubkey: account.pubkey).displayName
|
||||||
|
return display_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview("Active") {
|
||||||
|
DamusPurpleAccountView(
|
||||||
|
damus_state: test_damus_state,
|
||||||
|
account: DamusPurple.Account(
|
||||||
|
pubkey: test_pubkey,
|
||||||
|
created_at: Date.now,
|
||||||
|
expiry: Date.init(timeIntervalSinceNow: 60 * 60 * 24 * 30),
|
||||||
|
subscriber_number: 7,
|
||||||
|
active: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview("Expired") {
|
||||||
|
DamusPurpleAccountView(
|
||||||
|
damus_state: test_damus_state,
|
||||||
|
account: DamusPurple.Account(
|
||||||
|
pubkey: test_pubkey,
|
||||||
|
created_at: Date.init(timeIntervalSinceNow: -60 * 60 * 24 * 37),
|
||||||
|
expiry: Date.init(timeIntervalSinceNow: -60 * 60 * 24 * 7),
|
||||||
|
subscriber_number: 7,
|
||||||
|
active: false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
@ -27,6 +27,13 @@ enum ProductState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum AccountInfoState {
|
||||||
|
case loading
|
||||||
|
case loaded(account: DamusPurple.Account)
|
||||||
|
case no_account
|
||||||
|
case error(message: String)
|
||||||
|
}
|
||||||
|
|
||||||
func non_discounted_price(_ product: Product) -> String {
|
func non_discounted_price(_ product: Product) -> String {
|
||||||
return (product.price * 1.1984569224).formatted(product.priceFormatStyle)
|
return (product.price * 1.1984569224).formatted(product.priceFormatStyle)
|
||||||
}
|
}
|
||||||
@ -45,6 +52,7 @@ struct DamusPurpleView: View {
|
|||||||
let damus_state: DamusState
|
let damus_state: DamusState
|
||||||
let keypair: Keypair
|
let keypair: Keypair
|
||||||
|
|
||||||
|
@State var my_account_info_state: AccountInfoState = .loading
|
||||||
@State var products: ProductState
|
@State var products: ProductState
|
||||||
@State var purchased: PurchasedProduct? = nil
|
@State var purchased: PurchasedProduct? = nil
|
||||||
@State var selection: DamusPurpleType = .yearly
|
@State var selection: DamusPurpleType = .yearly
|
||||||
@ -86,6 +94,9 @@ struct DamusPurpleView: View {
|
|||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
notify(.display_tabbar(false))
|
notify(.display_tabbar(false))
|
||||||
|
Task {
|
||||||
|
await self.load_account()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
notify(.display_tabbar(true))
|
notify(.display_tabbar(true))
|
||||||
@ -123,6 +134,20 @@ struct DamusPurpleView: View {
|
|||||||
.manageSubscriptionsSheet(isPresented: $show_manage_subscriptions)
|
.manageSubscriptionsSheet(isPresented: $show_manage_subscriptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func load_account() async {
|
||||||
|
do {
|
||||||
|
if let account = try await damus_state.purple.get_account(pubkey: damus_state.keypair.pubkey) {
|
||||||
|
self.my_account_info_state = .loaded(account: account)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.my_account_info_state = .no_account
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
self.my_account_info_state = .error(message: NSLocalizedString("There was an error loading your account. Please try again later. If problem persists, please contact us at support@damus.io", comment: "Error label when Purple account information fails to load"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func update_user_settings_to_purple() {
|
func update_user_settings_to_purple() {
|
||||||
if damus_state.settings.translation_service == .none {
|
if damus_state.settings.translation_service == .none {
|
||||||
set_translation_settings_to_purple()
|
set_translation_settings_to_purple()
|
||||||
@ -357,6 +382,27 @@ struct DamusPurpleView: View {
|
|||||||
VStack {
|
VStack {
|
||||||
DamusPurpleLogoView()
|
DamusPurpleLogoView()
|
||||||
|
|
||||||
|
switch my_account_info_state {
|
||||||
|
case .loading:
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(.circular)
|
||||||
|
case .loaded(let account):
|
||||||
|
DamusPurpleAccountView(damus_state: damus_state, account: account)
|
||||||
|
case .no_account:
|
||||||
|
MarketingContent
|
||||||
|
case .error(let message):
|
||||||
|
Text(message)
|
||||||
|
.foregroundStyle(.red)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var MarketingContent: some View {
|
||||||
|
VStack {
|
||||||
VStack(alignment: .leading, spacing: 30) {
|
VStack(alignment: .leading, spacing: 30) {
|
||||||
Subtitle(NSLocalizedString("Help us stay independent in our mission for Freedom tech with our Purple subscription, and look cool doing it!", comment: "Damus purple subscription pitch"))
|
Subtitle(NSLocalizedString("Help us stay independent in our mission for Freedom tech with our Purple subscription, and look cool doing it!", comment: "Damus purple subscription pitch"))
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
@ -414,8 +460,8 @@ struct DamusPurpleView: View {
|
|||||||
NSLocalizedString("Learn more", comment: "Label for a link to the Damus Purple landing page"),
|
NSLocalizedString("Learn more", comment: "Label for a link to the Damus Purple landing page"),
|
||||||
destination: damus_state.purple.environment.purple_landing_page_url()
|
destination: damus_state.purple.environment.purple_landing_page_url()
|
||||||
)
|
)
|
||||||
.foregroundColor(DamusColors.pink)
|
.foregroundColor(DamusColors.pink)
|
||||||
.padding()
|
.padding()
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,9 +473,6 @@ struct DamusPurpleView: View {
|
|||||||
ProductStateView
|
ProductStateView
|
||||||
}
|
}
|
||||||
.padding([.top], 20)
|
.padding([.top], 20)
|
||||||
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user