Premium posts tab on linked standard account

This commit is contained in:
Thomas Ricouard 2024-06-18 08:21:02 +02:00
parent 76220bd930
commit 9364fc8cc8
4 changed files with 39 additions and 15 deletions

View file

@ -21,7 +21,6 @@ public struct AccountDetailView: View {
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@State private var viewModel: AccountDetailViewModel @State private var viewModel: AccountDetailViewModel
@State private var isCurrentUser: Bool = false
@State private var showBlockConfirmation: Bool = false @State private var showBlockConfirmation: Bool = false
@State private var isEditingRelationshipNote: Bool = false @State private var isEditingRelationshipNote: Bool = false
@State private var showTranslateView: Bool = false @State private var showTranslateView: Bool = false
@ -57,8 +56,7 @@ public struct AccountDetailView: View {
.applyAccountDetailsRowStyle(theme: theme) .applyAccountDetailsRowStyle(theme: theme)
Picker("", selection: $viewModel.selectedTab) { Picker("", selection: $viewModel.selectedTab) {
ForEach(isCurrentUser ? AccountDetailViewModel.Tab.currentAccountTabs : AccountDetailViewModel.Tab.accountTabs, ForEach(viewModel.tabs, id: \.self)
id: \.self)
{ tab in { tab in
if tab == .boosts { if tab == .boosts {
Image("Rocket") Image("Rocket")
@ -97,8 +95,7 @@ public struct AccountDetailView: View {
} }
.onAppear { .onAppear {
guard reasons != .placeholder else { return } guard reasons != .placeholder else { return }
isCurrentUser = currentAccount.account?.id == viewModel.accountId viewModel.isCurrentUser = currentAccount.account?.id == viewModel.accountId
viewModel.isCurrentUser = isCurrentUser
viewModel.client = client viewModel.client = client
// Avoid capturing non-Sendable `self` just to access the view model. // Avoid capturing non-Sendable `self` just to access the view model.
@ -298,7 +295,7 @@ public struct AccountDetailView: View {
} }
} }
if isCurrentUser { if viewModel.isCurrentUser {
Button { Button {
routerPath.presentedSheet = .accountEditInfo routerPath.presentedSheet = .accountEditInfo
} label: { } label: {

View file

@ -16,7 +16,7 @@ import SwiftUI
} }
enum Tab: Int { enum Tab: Int {
case statuses, favorites, bookmarks, replies, boosts, media case statuses, favorites, bookmarks, replies, boosts, media, premiumPosts
static var currentAccountTabs: [Tab] { static var currentAccountTabs: [Tab] {
[.statuses, .replies, .boosts, .favorites, .bookmarks] [.statuses, .replies, .boosts, .favorites, .bookmarks]
@ -25,6 +25,10 @@ import SwiftUI
static var accountTabs: [Tab] { static var accountTabs: [Tab] {
[.statuses, .replies, .boosts, .media] [.statuses, .replies, .boosts, .media]
} }
static var premiumAccountTabs: [Tab] {
[.statuses, .premiumPosts, .replies, .boosts, .media]
}
var iconName: String { var iconName: String {
switch self { switch self {
@ -34,6 +38,7 @@ import SwiftUI
case .replies: "bubble.left.and.bubble.right" case .replies: "bubble.left.and.bubble.right"
case .boosts: "" case .boosts: ""
case .media: "photo.on.rectangle.angled" case .media: "photo.on.rectangle.angled"
case .premiumPosts: "dollarsign"
} }
} }
@ -45,9 +50,21 @@ import SwiftUI
case .replies: "accessibility.tabs.profile.picker.posts-and-replies" case .replies: "accessibility.tabs.profile.picker.posts-and-replies"
case .boosts: "accessibility.tabs.profile.picker.boosts" case .boosts: "accessibility.tabs.profile.picker.boosts"
case .media: "accessibility.tabs.profile.picker.media" case .media: "accessibility.tabs.profile.picker.media"
case .premiumPosts: "Premium Posts"
} }
} }
} }
var tabs: [Tab] {
if isCurrentUser {
return Tab.currentAccountTabs
} else if account?.isLinkedToPremiumAccount == true && premiumAccount != nil {
return Tab.premiumAccountTabs
} else {
return Tab.accountTabs
}
}
var accountState: AccountState = .loading var accountState: AccountState = .loading
var statusesState: StatusesState = .loading var statusesState: StatusesState = .loading
@ -68,7 +85,7 @@ import SwiftUI
var selectedTab = Tab.statuses { var selectedTab = Tab.statuses {
didSet { didSet {
switch selectedTab { switch selectedTab {
case .statuses, .replies, .boosts, .media: case .statuses, .replies, .boosts, .media, .premiumPosts:
tabTask?.cancel() tabTask?.cancel()
tabTask = Task { tabTask = Task {
await fetchNewestStatuses(pullToRefresh: false) await fetchNewestStatuses(pullToRefresh: false)
@ -172,8 +189,12 @@ import SwiftUI
do { do {
statusesState = .loading statusesState = .loading
boosts = [] boosts = []
var accountIdToFetch = accountId
if selectedTab == .premiumPosts, let accountId = premiumAccount?.id {
accountIdToFetch = accountId
}
statuses = statuses =
try await client.get(endpoint: Accounts.statuses(id: accountId, try await client.get(endpoint: Accounts.statuses(id: accountIdToFetch,
sinceId: nil, sinceId: nil,
tag: nil, tag: nil,
onlyMedia: selectedTab == .media, onlyMedia: selectedTab == .media,
@ -210,10 +231,14 @@ import SwiftUI
func fetchNextPage() async throws { func fetchNextPage() async throws {
guard let client else { return } guard let client else { return }
switch selectedTab { switch selectedTab {
case .statuses, .replies, .boosts, .media: case .statuses, .replies, .boosts, .media, .premiumPosts:
guard let lastId = statuses.last?.id else { return } guard let lastId = statuses.last?.id else { return }
var accountIdToFetch = accountId
if selectedTab == .premiumPosts, let accountId = premiumAccount?.id {
accountIdToFetch = accountId
}
let newStatuses: [Status] = let newStatuses: [Status] =
try await client.get(endpoint: Accounts.statuses(id: accountId, try await client.get(endpoint: Accounts.statuses(id: accountIdToFetch,
sinceId: lastId, sinceId: lastId,
tag: nil, tag: nil,
onlyMedia: selectedTab == .media, onlyMedia: selectedTab == .media,
@ -252,7 +277,7 @@ import SwiftUI
private func reloadTabState() { private func reloadTabState() {
switch selectedTab { switch selectedTab {
case .statuses, .replies, .media: case .statuses, .replies, .media, .premiumPosts:
statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage) statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage)
case .boosts: case .boosts:
statusesState = .display(statuses: boosts, nextPageState: statuses.count < 20 ? .none : .hasNextPage) statusesState = .display(statuses: boosts, nextPageState: statuses.count < 20 ? .none : .hasNextPage)
@ -301,7 +326,7 @@ extension AccountDetailViewModel {
forceVersion: .v2) forceVersion: .v2)
if let premiumAccount = results?.accounts.first { if let premiumAccount = results?.accounts.first {
self.premiumAccount = premiumAccount self.premiumAccount = premiumAccount
var relationships: [Relationship] = try await client.get(endpoint: Accounts.relationships(ids: [premiumAccount.id])) let relationships: [Relationship] = try await client.get(endpoint: Accounts.relationships(ids: [premiumAccount.id]))
self.premiumRelationship = relationships.first self.premiumRelationship = relationships.first
} }
} }

View file

@ -15,8 +15,8 @@ public struct StatusRowView: View {
@Environment(\.accessibilityVoiceOverEnabled) private var accessibilityVoiceOverEnabled @Environment(\.accessibilityVoiceOverEnabled) private var accessibilityVoiceOverEnabled
@Environment(\.isStatusFocused) private var isFocused @Environment(\.isStatusFocused) private var isFocused
@Environment(\.indentationLevel) private var indentationLevel @Environment(\.indentationLevel) private var indentationLevel
@Environment(RouterPath.self) private var routerPath: RouterPath @Environment(RouterPath.self) private var routerPath: RouterPath
@Environment(QuickLook.self) private var quickLook @Environment(QuickLook.self) private var quickLook
@Environment(Theme.self) private var theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client

View file

@ -3,10 +3,12 @@ import Env
import SwiftUI import SwiftUI
struct StatusRowPremiumView: View { struct StatusRowPremiumView: View {
@Environment(\.isHomeTimeline) private var isHomeTimeline
let viewModel: StatusRowViewModel let viewModel: StatusRowViewModel
var body: some View { var body: some View {
if viewModel.status.account.isPremiumAccount { if isHomeTimeline, viewModel.status.account.isPremiumAccount {
Text("From a subscribed premium account") Text("From a subscribed premium account")
.font(.scaledFootnote) .font(.scaledFootnote)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)