ConfigView.swift (8320B)
1 // 2 // ConfigView.swift 3 // damus 4 // 5 // Created by William Casarin on 2022-06-09. 6 // 7 import AVFoundation 8 import Kingfisher 9 import SwiftUI 10 import LocalAuthentication 11 import Combine 12 13 struct ConfigView: View { 14 let state: DamusState 15 @Environment(\.colorScheme) var colorScheme 16 @Environment(\.dismiss) var dismiss 17 @State var confirm_logout: Bool = false 18 @State var delete_account_warning: Bool = false 19 @State var confirm_delete_account: Bool = false 20 @State var delete_text: String = "" 21 22 @ObservedObject var settings: UserSettingsStore 23 24 private let DELETE_KEYWORD = "DELETE" 25 26 init(state: DamusState) { 27 self.state = state 28 _settings = ObservedObject(initialValue: state.settings) 29 } 30 31 func textColor() -> Color { 32 colorScheme == .light ? DamusColors.black : DamusColors.white 33 } 34 35 var body: some View { 36 ZStack(alignment: .leading) { 37 Form { 38 Section { 39 NavigationLink(value: Route.KeySettings(keypair: state.keypair)) { 40 IconLabel(NSLocalizedString("Keys", comment: "Settings section for managing keys"), img_name: "Key", color: .purple) 41 } 42 43 NavigationLink(value: Route.AppearanceSettings(settings: settings)) { 44 IconLabel(NSLocalizedString("Appearance and filters", comment: "Section header for text, appearance, and content filter settings"), img_name: "eye", color: .red) 45 } 46 47 NavigationLink(value: Route.SearchSettings(settings: settings)) { 48 IconLabel(NSLocalizedString("Search/Universe", comment: "Section header for search/universe settings"), img_name: "search", color: .red) 49 } 50 51 NavigationLink(value: Route.NotificationSettings(settings: settings)) { 52 IconLabel(NSLocalizedString("Notifications", comment: "Section header for Damus notifications"), img_name: "notification-bell-on", color: .blue) 53 } 54 55 NavigationLink(value: Route.ZapSettings(settings: settings)) { 56 IconLabel(NSLocalizedString("Zaps", comment: "Section header for zap settings"), img_name: "zap.fill", color: .orange) 57 } 58 59 NavigationLink(value: Route.TranslationSettings(settings: settings)) { 60 IconLabel(NSLocalizedString("Translation", comment: "Section header for text and appearance settings"), img_name: "globe", color: .green) 61 } 62 63 NavigationLink(value: Route.ReactionsSettings(settings: settings)) { 64 IconLabel(NSLocalizedString("Reactions", comment: "Section header for reactions settings"), img_name: "shaka.fill", color: .purple) 65 } 66 67 NavigationLink(value: Route.DeveloperSettings(settings: settings)) { 68 IconLabel(NSLocalizedString("Developer", comment: "Section header for developer settings"), img_name: "magic-stick2.fill", color: DamusColors.adaptableBlack) 69 } 70 } 71 72 Section(NSLocalizedString("Sign Out", comment: "Section title for signing out")) { 73 Button(action: { 74 if state.keypair.privkey == nil { 75 logout(state) 76 } else { 77 confirm_logout = true 78 } 79 }, label: { 80 Label(NSLocalizedString("Sign out", comment: "Sidebar menu label to sign out of the account."), image: "logout") 81 .foregroundColor(textColor()) 82 .frame(maxWidth: .infinity, alignment: .leading) 83 }) 84 } 85 86 if state.is_privkey_user { 87 Section(header: Text(NSLocalizedString("Permanently Delete Account", comment: "Section title for deleting the user"))) { 88 Button(action: { 89 delete_account_warning = true 90 }, label: { 91 Label(NSLocalizedString("Delete Account", comment: "Button to delete the user's account."), image: "delete") 92 .frame(maxWidth: .infinity, alignment: .leading) 93 .foregroundColor(.red) 94 }) 95 } 96 } 97 98 Section(NSLocalizedString("Version", comment: "Section title for displaying the version number of the Damus app.")) { 99 Text(verbatim: VersionInfo.version) 100 .contextMenu { 101 Button { 102 UIPasteboard.general.string = VersionInfo.version 103 } label: { 104 Label(NSLocalizedString("Copy", comment: "Context menu option for copying the version of damus."), image: "copy2") 105 } 106 } 107 } 108 } 109 } 110 .navigationTitle(NSLocalizedString("Settings", comment: "Navigation title for Settings view.")) 111 .navigationBarTitleDisplayMode(.large) 112 .alert(NSLocalizedString("WARNING:\n\nTHIS WILL SIGN AN EVENT THAT DELETES THIS ACCOUNT.\n\nYOU WILL NO LONGER BE ABLE TO LOG INTO DAMUS USING THIS ACCOUNT KEY.\n\n ARE YOU SURE YOU WANT TO CONTINUE?", comment: "Alert for deleting the users account."), isPresented: $delete_account_warning) { 113 114 Button(NSLocalizedString("Cancel", comment: "Cancel deleting the user."), role: .cancel) { 115 delete_account_warning = false 116 } 117 Button(NSLocalizedString("Continue", comment: "Continue with deleting the user.")) { 118 confirm_delete_account = true 119 } 120 } 121 .alert(NSLocalizedString("Permanently Delete Account", comment: "Alert for deleting the users account."), isPresented: $confirm_delete_account) { 122 TextField(String(format: NSLocalizedString("Type %@ to delete", comment: "Text field prompt asking user to type DELETE in all caps to confirm that they want to proceed with deleting their account."), DELETE_KEYWORD), text: $delete_text) 123 Button(NSLocalizedString("Cancel", comment: "Cancel deleting the user."), role: .cancel) { 124 confirm_delete_account = false 125 } 126 Button(NSLocalizedString("Delete", comment: "Button for deleting the users account."), role: .destructive) { 127 guard let keypair = state.keypair.to_full(), 128 delete_text == DELETE_KEYWORD, 129 let ev = created_deleted_account_profile(keypair: keypair) else { 130 return 131 } 132 state.postbox.send(ev) 133 logout(state) 134 } 135 } 136 .alert(NSLocalizedString("Logout", comment: "Alert for logging out the user."), isPresented: $confirm_logout) { 137 Button(NSLocalizedString("Cancel", comment: "Cancel out of logging out the user."), role: .cancel) { 138 confirm_logout = false 139 } 140 Button(NSLocalizedString("Logout", comment: "Button for logging out the user."), role: .destructive) { 141 logout(state) 142 } 143 } message: { 144 Text("Make sure your nsec account key is saved before you logout or you will lose access to this account", comment: "Reminder message in alert to get customer to verify that their private security account key is saved saved before logging out.") 145 } 146 .onReceive(handle_notify(.switched_timeline)) { _ in 147 dismiss() 148 } 149 } 150 151 } 152 153 struct ConfigView_Previews: PreviewProvider { 154 static var previews: some View { 155 NavigationView { 156 ConfigView(state: test_damus_state) 157 } 158 } 159 } 160 161 162 func handle_string_amount(new_value: String) -> Int? { 163 let filtered = new_value.filter { 164 $0.isNumber 165 } 166 167 if filtered == "" { 168 return nil 169 } 170 171 guard let amt = NumberFormatter().number(from: filtered) as? Int else { 172 return nil 173 } 174 175 return amt 176 }