Skip to content

Commit

Permalink
introduce AppFlow to support different application flows (#587)
Browse files Browse the repository at this point in the history
Co-authored-by: Sjmarf <[email protected]>
  • Loading branch information
2 people authored and boscojwho committed Oct 7, 2023
1 parent 2974da7 commit a2f5c7f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 47 deletions.
92 changes: 53 additions & 39 deletions Mlem/Views/Shared/Accounts/Accounts Page.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Instance and Community List View.swift
// AccountsPage.swift
// Mlem
//
// Created by David Bureš on 27.03.2022.
Expand All @@ -11,84 +11,98 @@ import SwiftUI
struct AccountsPage: View {
@Dependency(\.accountsTracker) var accountsTracker

@Environment(\.setAppFlow) private var setFlow

@EnvironmentObject var appState: AppState

@Environment(\.forceOnboard) var forceOnboard

@State private var isShowingInstanceAdditionSheet: Bool = false
@State var selectedAccount: SavedAccount?

@State var isShowingDeleteConfirm: Bool = false

let onboarding: Bool

init(onboarding: Bool = false) {
self.onboarding = onboarding
}
@State var accountForDeletion: SavedAccount?

@Environment(\.dismiss) var dismiss

var body: some View {
let instances = Array(accountsTracker.accountsByInstance.keys).sorted()

Group {
if onboarding || instances.isEmpty || isShowingInstanceAdditionSheet {
AddSavedInstanceView(
onboarding: onboarding,
currentAccount: $selectedAccount
)
if instances.isEmpty || isShowingInstanceAdditionSheet {
AddSavedInstanceView(onboarding: false)
} else {
List {
ForEach(instances, id: \.self) { instance in
Section(header: Text(instance)) {
ForEach(accountsTracker.accountsByInstance[instance] ?? []) { account in
Button(account.username) {
dismiss()

// this tiny delay prevents the modal dismiss animation from being cancelled
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
appState.setActiveAccount(account)
}
setFlow(using: account)
}
.swipeActions {
Button("Remove", role: .destructive) {
accountsTracker.removeAccount(account: account, appState: appState, forceOnboard: forceOnboard)
dismiss()
accountsTracker.removeAccount(account: account)
if account == appState.currentActiveAccount {
// if we just deleted the current account we (currently!) have a decision to make
if let first = accountsTracker.savedAccounts.first {
// if we have another account available, go to that...

// TODO: once onboarding is updated to support showing a user's
// current accounts, we can scrap this and always go to onboarding.
// This leaves the decision of which account to enter in the
// user's hands, as opposed to us picking the first account with `.first`.
setFlow(using: first)
} else {
// no accounts, so go to onboarding
setFlow(using: nil)
}
}
}
}
.foregroundColor(appState.currentActiveAccount == account ? .secondary : .primary)
.foregroundColor(color(for: account))
}
}
}

Button {
isShowingInstanceAdditionSheet = true
} label: {
Text("Add Account")
Label("Add Account", systemImage: AppConstants.switchUserSymbolName)
}
.accessibilityLabel("Add a new account.")

Button(role: .destructive) {
isShowingDeleteConfirm = true
} label: {
Label("Delete Current Account", systemImage: "trash")
.foregroundColor(.red)
if let account = appState.currentActiveAccount {
Button(role: .destructive) {
accountForDeletion = account
} label: {
Label("Delete Current Account", systemImage: "trash")
.foregroundColor(.red)
}
}
}
}
}
.hoistNavigation(dismiss: dismiss)
.onAppear {
selectedAccount = appState.currentActiveAccount
}
.onChange(of: selectedAccount) { account in
guard let account else { return }
appState.setActiveAccount(account)
}
.sheet(isPresented: $isShowingInstanceAdditionSheet) {
AddSavedInstanceView(onboarding: false, currentAccount: $selectedAccount)
AddSavedInstanceView(onboarding: false)
}
.sheet(isPresented: $isShowingDeleteConfirm) {
DeleteAccountView()
.sheet(item: $accountForDeletion) { account in
DeleteAccountView(account: account)
}
}

private func color(for account: SavedAccount) -> Color {
guard let currentAccount = appState.currentActiveAccount else { return .primary }
return account == currentAccount ? .secondary : .primary
}

private func setFlow(using account: SavedAccount?) {
// this tiny delay prevents the modal dismiss animation from being cancelled
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
if let account {
setFlow(.account(account))
return
}

setFlow(.onboarding)
}
}
}
3 changes: 1 addition & 2 deletions Mlem/Views/Tabs/Feeds/Feed Root.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ struct FeedRoot: View {
ScrollViewReader { proxy in
NavigationSplitView(columnVisibility: $columnVisibility) {
CommunityListView(selectedCommunity: $rootDetails)
.id(appState.currentActiveAccount.id)
} detail: {
NavigationStack(path: $feedRouter.path) {
if let rootDetails {
Expand All @@ -54,7 +53,7 @@ struct FeedRoot: View {
Text("Please select a community")
}
}
.id((rootDetails?.id ?? 0) + appState.currentActiveAccount.id)
.id(rootDetails?.id ?? 0)
}
.environment(\.scrollViewProxy, proxy)
}
Expand Down
8 changes: 2 additions & 6 deletions Mlem/Views/Tabs/Profile/User View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ struct UserView: View {
}

private func isShowingOwnProfile() -> Bool {
userID == appState.currentActiveAccount.id
appState.isCurrentAccountId(userID)
}

@MainActor
Expand Down Expand Up @@ -405,11 +405,7 @@ struct UserViewPreview: PreviewProvider {
person: generatePreviewUser(name: "actualUsername", displayName: "PreferredUsername", userType: .normal),
counts: APIPersonAggregates(id: 123, personId: 123, postCount: 123, postScore: 567, commentCount: 14, commentScore: 974)
)
).environmentObject(AppState(defaultAccount: SavedAccount(
id: 0,
instanceLink: URL(string: "https://google.com")!,
accessToken: "",
username: "Preview User"), selectedAccount: Binding.constant(nil)))
).environmentObject(AppState())
}
}

Expand Down

0 comments on commit a2f5c7f

Please sign in to comment.