From af3722a3f1e3c1f12b72fbd92ae2687a059e9270 Mon Sep 17 00:00:00 2001 From: Eric Andrews Date: Fri, 11 Aug 2023 16:42:35 -0400 Subject: [PATCH] 1.0.1 Hotfix: Delete Accounts (#489) --- Mlem.xcodeproj/project.pbxproj | 36 +++++++--- Mlem/API/APIClient.swift | 6 ++ Mlem/API/Requests/User/DeleteUser.swift | 35 ++++++++++ .../Decode Data from File.swift | 0 .../Views/Shared/Accounts/Accounts Page.swift | 16 ++++- .../Shared/Accounts/DeleteAccountView.swift | 67 +++++++++++++++++++ 6 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 Mlem/API/Requests/User/DeleteUser.swift delete mode 100644 Mlem/Logic/File Management/Decode Data from File.swift create mode 100644 Mlem/Views/Shared/Accounts/DeleteAccountView.swift diff --git a/Mlem.xcodeproj/project.pbxproj b/Mlem.xcodeproj/project.pbxproj index 6c6306ec4..6491e3386 100644 --- a/Mlem.xcodeproj/project.pbxproj +++ b/Mlem.xcodeproj/project.pbxproj @@ -328,6 +328,8 @@ CDC1C93F2A7AB8C700072E3D /* AccessibilitySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC1C93E2A7AB8C700072E3D /* AccessibilitySettingsView.swift */; }; CDC1C9412A7ABA9C00072E3D /* ReadMarkStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC1C9402A7ABA9C00072E3D /* ReadMarkStyle.swift */; }; CDC1C9432A7AC24600072E3D /* ReadCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC1C9422A7AC24600072E3D /* ReadCheck.swift */; }; + CDC65D8F2A86B6DD007205E5 /* DeleteUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC65D8E2A86B6DD007205E5 /* DeleteUser.swift */; }; + CDC65D912A86B830007205E5 /* DeleteAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC65D902A86B830007205E5 /* DeleteAccountView.swift */; }; CDC6A8CA2A6F1C8D00CC11AC /* AssociatedIconProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC6A8C92A6F1C8D00CC11AC /* AssociatedIconProtocol.swift */; }; CDDB08782A5DF1330075BFEE /* CommentSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDB08772A5DF1330075BFEE /* CommentSettingsView.swift */; }; CDDCF6432A66343D003DA3AC /* FancyTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF6422A66343D003DA3AC /* FancyTabBar.swift */; }; @@ -365,9 +367,9 @@ CDF842682A49FB9000723DA0 /* Inbox View Logic.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF842672A49FB9000723DA0 /* Inbox View Logic.swift */; }; CDF8426B2A4A2AB600723DA0 /* Inbox Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF8426A2A4A2AB600723DA0 /* Inbox Item.swift */; }; CDF8426F2A4A385A00723DA0 /* Inbox Item Type.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF8426E2A4A385A00723DA0 /* Inbox Item Type.swift */; }; + E453A1D02A81C2140004BB8A /* QuickLookPreviewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E453A1CF2A81C2140004BB8A /* QuickLookPreviewController.swift */; }; E4D4DBA02A7C7B9D00C4F3DE /* Comments.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4D4DB9F2A7C7B9D00C4F3DE /* Comments.swift */; }; E4DDB4322A81819300B3A7E0 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DDB4312A81819300B3A7E0 /* Double.swift */; }; - E453A1D02A81C2140004BB8A /* QuickLookPreviewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E453A1CF2A81C2140004BB8A /* QuickLookPreviewController.swift */; }; E4DDB4342A819C8000B3A7E0 /* QuickLookView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DDB4332A819C8000B3A7E0 /* QuickLookView.swift */; }; /* End PBXBuildFile section */ @@ -708,6 +710,8 @@ CDC1C93E2A7AB8C700072E3D /* AccessibilitySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilitySettingsView.swift; sourceTree = ""; }; CDC1C9402A7ABA9C00072E3D /* ReadMarkStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkStyle.swift; sourceTree = ""; }; CDC1C9422A7AC24600072E3D /* ReadCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadCheck.swift; sourceTree = ""; }; + CDC65D8E2A86B6DD007205E5 /* DeleteUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteUser.swift; sourceTree = ""; }; + CDC65D902A86B830007205E5 /* DeleteAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteAccountView.swift; sourceTree = ""; }; CDC6A8C92A6F1C8D00CC11AC /* AssociatedIconProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssociatedIconProtocol.swift; sourceTree = ""; }; CDDB08772A5DF1330075BFEE /* CommentSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentSettingsView.swift; sourceTree = ""; }; CDDCF6422A66343D003DA3AC /* FancyTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FancyTabBar.swift; sourceTree = ""; }; @@ -745,9 +749,9 @@ CDF842672A49FB9000723DA0 /* Inbox View Logic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Inbox View Logic.swift"; sourceTree = ""; }; CDF8426A2A4A2AB600723DA0 /* Inbox Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Inbox Item.swift"; sourceTree = ""; }; CDF8426E2A4A385A00723DA0 /* Inbox Item Type.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Inbox Item Type.swift"; sourceTree = ""; }; + E453A1CF2A81C2140004BB8A /* QuickLookPreviewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickLookPreviewController.swift; sourceTree = ""; }; E4D4DB9F2A7C7B9D00C4F3DE /* Comments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comments.swift; sourceTree = ""; }; E4DDB4312A81819300B3A7E0 /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = ""; }; - E453A1CF2A81C2140004BB8A /* QuickLookPreviewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickLookPreviewController.swift; sourceTree = ""; }; E4DDB4332A819C8000B3A7E0 /* QuickLookView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickLookView.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1122,6 +1126,7 @@ children = ( 6332FDCE27EFDD2E0009A98A /* Accounts Page.swift */, 63F0C7B82A0533C700A18C5D /* Add Account View.swift */, + CDC65D902A86B830007205E5 /* DeleteAccountView.swift */, ); path = Accounts; sourceTree = ""; @@ -1393,6 +1398,7 @@ 637218242A3A2AAD008C4816 /* Requests */ = { isa = PBXGroup; children = ( + CDC65D8D2A86B6D4007205E5 /* User */, CDF842622A49EAEC00723DA0 /* Messages */, 637218252A3A2AAD008C4816 /* LoginRequest.swift */, 637218262A3A2AAD008C4816 /* Post */, @@ -1811,6 +1817,14 @@ path = Accessibility; sourceTree = ""; }; + CDC65D8D2A86B6D4007205E5 /* User */ = { + isa = PBXGroup; + children = ( + CDC65D8E2A86B6DD007205E5 /* DeleteUser.swift */, + ); + path = User; + sourceTree = ""; + }; CDC6A8C82A6F1C8000CC11AC /* Protocols */ = { isa = PBXGroup; children = ( @@ -1932,14 +1946,6 @@ path = Messages; sourceTree = ""; }; - E4D4DB9E2A7C7A5800C4F3DE /* Animations */ = { - isa = PBXGroup; - children = ( - E4D4DB9F2A7C7B9D00C4F3DE /* Comments.swift */, - ); - path = Animations; - sourceTree = ""; - }; E453A1CE2A81C1F20004BB8A /* Quick Look */ = { isa = PBXGroup; children = ( @@ -1949,6 +1955,14 @@ path = "Quick Look"; sourceTree = ""; }; + E4D4DB9E2A7C7A5800C4F3DE /* Animations */ = { + isa = PBXGroup; + children = ( + E4D4DB9F2A7C7B9D00C4F3DE /* Comments.swift */, + ); + path = Animations; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -2210,6 +2224,7 @@ CDA145ED2A510AC100DDAFC9 /* MarkCommentReplyAsReadRequest.swift in Sources */, CD391F982A537E8E00E213B5 /* ReplyToComment.swift in Sources */, 5064D03D2A6DE0AA00B22EE3 /* Notifier.swift in Sources */, + CDC65D912A86B830007205E5 /* DeleteAccountView.swift in Sources */, CD391F9C2A53980900E213B5 /* ReplyToCommentReply.swift in Sources */, 630737892A1CD1E900039852 /* String.swift in Sources */, 63A01E542A2B980100C84E04 /* Subscribe Button.swift in Sources */, @@ -2254,6 +2269,7 @@ CD64832D2A38CE4E00EE6CA3 /* Vote Complex Style.swift in Sources */, 637218492A3A2AAD008C4816 /* APICommentReplyView.swift in Sources */, 6317ABCB2A37292700603D76 /* FeedType.swift in Sources */, + CDC65D8F2A86B6DD007205E5 /* DeleteUser.swift in Sources */, CD6483382A3A0F2200EE6CA3 /* NSFW Tag.swift in Sources */, 637218642A3A2AAD008C4816 /* GetPost.swift in Sources */, 63E5D3942A13CF3600EC1FBD /* Favorite Community.swift in Sources */, diff --git a/Mlem/API/APIClient.swift b/Mlem/API/APIClient.swift index e34f8e391..4542f6d28 100644 --- a/Mlem/API/APIClient.swift +++ b/Mlem/API/APIClient.swift @@ -245,4 +245,10 @@ extension APIClient { let request = MarkAllAsRead(session: try session) try await perform(request: request) } + + // MARK: User Requests + func deleteUser(user: SavedAccount, password: String) async throws { + let request = DeleteAccountRequest(account: user, password: password) + try await perform(request: request) + } } diff --git a/Mlem/API/Requests/User/DeleteUser.swift b/Mlem/API/Requests/User/DeleteUser.swift new file mode 100644 index 000000000..63b59a55a --- /dev/null +++ b/Mlem/API/Requests/User/DeleteUser.swift @@ -0,0 +1,35 @@ +// +// DeleteUser.swift +// Mlem +// +// Created by Eric Andrews on 2023-08-11 +// + +import Foundation + +struct DeleteAccountRequest: APIPostRequest { + typealias Response = DeleteAccountResponse + + let instanceURL: URL + let path = "user/delete_account" + let body: Body + + // lemmy_api_common::person::DeleteAccount + struct Body: Encodable { + let password: String + let auth: String + } + + init( + account: SavedAccount, + password: String + ) { + self.instanceURL = account.instanceLink + self.body = .init( + password: password, + auth: account.accessToken + ) + } +} + +struct DeleteAccountResponse: Decodable {} diff --git a/Mlem/Logic/File Management/Decode Data from File.swift b/Mlem/Logic/File Management/Decode Data from File.swift deleted file mode 100644 index e69de29bb..000000000 diff --git a/Mlem/Views/Shared/Accounts/Accounts Page.swift b/Mlem/Views/Shared/Accounts/Accounts Page.swift index f40d99120..60c43efc2 100644 --- a/Mlem/Views/Shared/Accounts/Accounts Page.swift +++ b/Mlem/Views/Shared/Accounts/Accounts Page.swift @@ -15,6 +15,8 @@ struct AccountsPage: View { @State private var isShowingInstanceAdditionSheet: Bool = false @State var selectedAccount: SavedAccount? + @State var isShowingDeleteConfirm: Bool = false + let onboarding: Bool @Environment(\.dismiss) var dismiss @@ -40,7 +42,7 @@ struct AccountsPage: View { } } .swipeActions { - Button("Delete", role: .destructive) { + Button("Remove", role: .destructive) { accountsTracker.removeAccount(account: account, appState: appState, forceOnboard: forceOnboard) } } @@ -52,9 +54,16 @@ struct AccountsPage: View { 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) + } } } } @@ -65,5 +74,8 @@ struct AccountsPage: View { guard let account else { return } appState.setActiveAccount(account) } + .sheet(isPresented: $isShowingDeleteConfirm) { + DeleteAccountView() + } } } diff --git a/Mlem/Views/Shared/Accounts/DeleteAccountView.swift b/Mlem/Views/Shared/Accounts/DeleteAccountView.swift new file mode 100644 index 000000000..b98ec2838 --- /dev/null +++ b/Mlem/Views/Shared/Accounts/DeleteAccountView.swift @@ -0,0 +1,67 @@ +// +// DeleteAccountView.swift +// Mlem +// +// Created by Eric Andrews on 2023-08-11. +// + +import Foundation +import SwiftUI +import Dependencies + +struct DeleteAccountView: View { + + @EnvironmentObject var appState: AppState + @EnvironmentObject var accountsTracker: SavedAccountTracker + + @Environment(\.dismiss) var dismiss + @Environment(\.forceOnboard) var forceOnboard + + @Dependency(\.apiClient) private var apiClient + @Dependency(\.errorHandler) var errorHandler + + @State private var password = "" + + var body: some View { + VStack(alignment: .center, spacing: 20) { + Text("Really delete \(appState.currentActiveAccount.username)?") + .font(.title) + .fontWeight(.bold) + + // swiftlint:disable line_length + Text("Please note that this will *permanently* remove it from \(appState.currentActiveAccount.hostName ?? "the instance"), not just Mlem!") + // swiftlint:enable line_length + + Text("To confirm, please enter your password:") + + SecureField("", text: $password) + .padding(4) + .background(Color.secondarySystemBackground) + .cornerRadius(AppConstants.smallItemCornerRadius) + .textContentType(.password) + .submitLabel(.go) + .onSubmit { + deleteAccount() + } + + Button("Cancel") { + dismiss() + } + } + .multilineTextAlignment(.center) + .padding() + } + + func deleteAccount() { + Task { + do { + try await apiClient.deleteUser(user: appState.currentActiveAccount, password: password) + accountsTracker.removeAccount(account: appState.currentActiveAccount, + appState: appState, + forceOnboard: forceOnboard) + } catch { + errorHandler.handle(.init(underlyingError: error)) + } + } + } +}