Skip to content

Commit 2565eb8

Browse files
authored
Merge pull request #1518 from planetary-social/bdm/80-delete-account-ui
added Delete Account UI #80
2 parents 86791b5 + 90a144c commit 2565eb8

File tree

5 files changed

+117
-4
lines changed

5 files changed

+117
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
- Fixed alert when uploading big files suggesting users pay for nostr.build. [#1321](https://github.com/planetary-social/nos/issues/1321)
2525
- Fixed issue where push notifications were not re-registered after account change. [#1501](https://github.com/planetary-social/nos/issues/1501)
2626
- Added support for NIP-62 Request to Vanish events. [#80](https://github.com/planetary-social/nos/issues/80)
27+
- Added Delete Account UI. [#80](https://github.com/planetary-social/nos/issues/80)
2728

2829
### Internal Changes
2930
- Use NIP-92 media metadata to display media in the proper orientation. Currently behind the “Enable new media display” feature flag. [#1172](https://github.com/planetary-social/nos/issues/1172)

Nos/Assets/Localization/Localizable.xcstrings

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,6 +3056,50 @@
30563056
}
30573057
}
30583058
},
3059+
"delete" : {
3060+
"extractionState" : "manual",
3061+
"localizations" : {
3062+
"en" : {
3063+
"stringUnit" : {
3064+
"state" : "translated",
3065+
"value" : "Delete"
3066+
}
3067+
}
3068+
}
3069+
},
3070+
"deleteAccount" : {
3071+
"extractionState" : "manual",
3072+
"localizations" : {
3073+
"en" : {
3074+
"stringUnit" : {
3075+
"state" : "translated",
3076+
"value" : "Delete Account"
3077+
}
3078+
}
3079+
}
3080+
},
3081+
"deleteAccountDescription" : {
3082+
"extractionState" : "manual",
3083+
"localizations" : {
3084+
"en" : {
3085+
"stringUnit" : {
3086+
"state" : "translated",
3087+
"value" : "Deleting your account will delete all your data from Nos servers and ask all your relays to do the same."
3088+
}
3089+
}
3090+
}
3091+
},
3092+
"deleteMyAccount" : {
3093+
"extractionState" : "manual",
3094+
"localizations" : {
3095+
"en" : {
3096+
"stringUnit" : {
3097+
"state" : "translated",
3098+
"value" : "Delete my Account"
3099+
}
3100+
}
3101+
}
3102+
},
30593103
"deleteNote" : {
30603104
"extractionState" : "manual",
30613105
"localizations" : {
@@ -3727,6 +3771,17 @@
37273771
}
37283772
}
37293773
},
3774+
"enableAccountDeletion" : {
3775+
"extractionState" : "manual",
3776+
"localizations" : {
3777+
"en" : {
3778+
"stringUnit" : {
3779+
"state" : "translated",
3780+
"value" : "Enable account deletion"
3781+
}
3782+
}
3783+
}
3784+
},
37303785
"enableNewMediaDisplay" : {
37313786
"comment" : "Setting for new media feature flag",
37323787
"extractionState" : "manual",

Nos/Service/FeatureFlags.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Foundation
22
import Dependencies
3+
import SwiftUI
34

45
/// Feature flags for enabling experimental or beta features.
56
enum FeatureFlag {
@@ -9,6 +10,9 @@ enum FeatureFlag {
910
/// Whether the new moderation flow should be enabled or not.
1011
/// - Note: See [#1489](https://github.com/planetary-social/nos/issues/1489) for details on the new moderation flow.
1112
case newModerationFlow
13+
/// Whether delete account UI is enabled or not.
14+
/// - Note: See [#80](https://github.com/planetary-social/nos/issues/80) for details on deleting accounts.
15+
case deleteAccount
1216
}
1317

1418
/// The set of feature flags used by the app.
@@ -24,7 +28,7 @@ protocol FeatureFlags {
2428
}
2529

2630
/// The default set of feature flag values for the app.
27-
class DefaultFeatureFlags: FeatureFlags, DependencyKey {
31+
@Observable class DefaultFeatureFlags: FeatureFlags, DependencyKey {
2832
/// The one and only instance of `DefaultFeatureFlags`.
2933
static let liveValue = DefaultFeatureFlags()
3034

@@ -33,7 +37,8 @@ class DefaultFeatureFlags: FeatureFlags, DependencyKey {
3337
/// Feature flags and their values.
3438
private var featureFlags: [FeatureFlag: Bool] = [
3539
.newMediaDisplay: false,
36-
.newModerationFlow: false
40+
.newModerationFlow: false,
41+
.deleteAccount: false
3742
]
3843

3944
/// Returns true if the feature is enabled.

Nos/Views/Components/Button/ActionButton.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct ActionButton: View {
1212
var font: Font = .clarity(.bold)
1313
var image: Image?
1414
var imageAlignment: ImageAlignment = .left
15+
var padding = EdgeInsets(top: 8, leading: 13, bottom: 8, trailing: 13)
1516
var textColor = Color.white
1617
var depthEffectColor = Color.actionPrimaryDepthEffect
1718
var backgroundGradient = LinearGradient(
@@ -67,6 +68,7 @@ struct ActionButton: View {
6768
.buttonStyle(ActionButtonStyle(
6869
depthEffectColor: depthEffectColor,
6970
backgroundGradient: backgroundGradient,
71+
padding: padding,
7072
textShadow: textShadow,
7173
shouldFillHorizontalSpace: shouldFillHorizontalSpace
7274
))
@@ -107,6 +109,7 @@ struct ActionButtonStyle: ButtonStyle {
107109
let cornerRadius: CGFloat = 17
108110
let depthEffectColor: Color
109111
let backgroundGradient: LinearGradient
112+
let padding: EdgeInsets
110113
var textShadow: Bool
111114
/// A flag used to fill the available horizontal space (centering the
112115
/// contents) or to fit the horizontal space to the contents of the action
@@ -125,8 +128,7 @@ struct ActionButtonStyle: ButtonStyle {
125128
configuration.label
126129
.foregroundColor(.white)
127130
.font(.body)
128-
.padding(.vertical, 8)
129-
.padding(.horizontal, 13)
131+
.padding(padding)
130132
.shadow(
131133
color: textShadow ? Color.actionButtonTextShadow : .clear,
132134
radius: 2,

Nos/Views/Settings/SettingsView.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import SwiftUI
22
import Dependencies
3+
import Logger
34
import SwiftUINavigation
45

56
let showReportWarningsKey = "com.verse.nos.settings.showReportWarnings"
@@ -32,6 +33,7 @@ struct SettingsView: View {
3233

3334
fileprivate enum AlertAction {
3435
case logout
36+
case deleteAccount
3537
}
3638

3739
fileprivate enum CopyButtonState {
@@ -217,6 +219,32 @@ struct SettingsView: View {
217219
.padding(.vertical, 15)
218220
}
219221
.listRowGradientBackground()
222+
223+
#if STAGING || DEBUG
224+
if isDeleteAccountEnabled.wrappedValue {
225+
ActionButton(
226+
title: .localizable.deleteMyAccount,
227+
font: .clarityBold(.title3),
228+
padding: EdgeInsets(top: 16, leading: 0, bottom: 16, trailing: 0),
229+
depthEffectColor: .actionSecondaryDepthEffect,
230+
backgroundGradient: .verticalAccentSecondary,
231+
shouldFillHorizontalSpace: true
232+
) {
233+
alert = AlertState(
234+
title: { TextState(String(localized: .localizable.deleteAccount)) },
235+
actions: {
236+
ButtonState(role: .destructive, action: .send(.deleteAccount)) {
237+
TextState(String(localized: .localizable.delete))
238+
}
239+
},
240+
message: { TextState(String(localized: .localizable.deleteAccountDescription)) }
241+
)
242+
}
243+
.clipShape(Capsule())
244+
.listRowBackground(Color.clear)
245+
.listRowInsets(EdgeInsets())
246+
}
247+
#endif
220248
}
221249
.scrollContentBackground(.hidden)
222250
.background(Color.appBg)
@@ -236,6 +264,13 @@ struct SettingsView: View {
236264
switch action {
237265
case .logout:
238266
await logout()
267+
case .deleteAccount:
268+
do {
269+
try await currentUser.publishRequestToVanish()
270+
await logout()
271+
} catch {
272+
Log.error(error)
273+
}
239274
}
240275
}
241276

@@ -276,6 +311,19 @@ extension SettingsView {
276311
private var newModerationFlowToggle: some View {
277312
NosToggle(isOn: isNewModerationFlowEnabled, labelText: .localizable.enableNewModerationFlow)
278313
}
314+
315+
/// Whether account deletion is enabled.
316+
private var isDeleteAccountEnabled: Binding<Bool> {
317+
Binding<Bool>(
318+
get: { featureFlags.isEnabled(.deleteAccount) },
319+
set: { featureFlags.setFeature(.deleteAccount, enabled: $0) }
320+
)
321+
}
322+
323+
/// A toggle for account deletion that allows the user to turn the feature on or off.
324+
private var deleteAccountToggle: some View {
325+
NosToggle(isOn: isDeleteAccountEnabled, labelText: .localizable.enableAccountDeletion)
326+
}
279327
}
280328
#endif
281329

@@ -285,6 +333,7 @@ extension SettingsView {
285333
@MainActor private var stagingControls: some View {
286334
newMediaFeatureToggle
287335
newModerationFlowToggle
336+
deleteAccountToggle
288337
}
289338
}
290339
#endif
@@ -296,6 +345,7 @@ extension SettingsView {
296345
Group {
297346
newMediaFeatureToggle
298347
newModerationFlowToggle
348+
deleteAccountToggle
299349
Text(.localizable.sampleDataInstructions)
300350
.foregroundColor(.primaryTxt)
301351
Button(String(localized: .localizable.loadSampleData)) {

0 commit comments

Comments
 (0)