ConfigView.swift (8730B)
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 NavigationLink(value: Route.FirstAidSettings(settings: settings)) { 72 IconLabel(NSLocalizedString("First Aid", comment: "Section header for first aid tools and settings"), img_name: "help2", color: .red) 73 } 74 } 75 76 Section(NSLocalizedString("Sign Out", comment: "Section title for signing out")) { 77 Button(action: { 78 if state.keypair.privkey == nil { 79 logout(state) 80 } else { 81 confirm_logout = true 82 } 83 }, label: { 84 Label(NSLocalizedString("Sign out", comment: "Sidebar menu label to sign out of the account."), image: "logout") 85 .foregroundColor(textColor()) 86 .frame(maxWidth: .infinity, alignment: .leading) 87 }) 88 } 89 90 if state.is_privkey_user { 91 Section(header: Text("Permanently Delete Account", comment: "Section title for deleting the user")) { 92 Button(action: { 93 delete_account_warning = true 94 }, label: { 95 Label(NSLocalizedString("Delete Account", comment: "Button to delete the user's account."), image: "delete") 96 .frame(maxWidth: .infinity, alignment: .leading) 97 .foregroundColor(.red) 98 }) 99 } 100 } 101 102 Section( 103 header: Text(NSLocalizedString("Version", comment: "Section title for displaying the version number of the Damus app.")), 104 footer: Text("").padding(.bottom, tabHeight + getSafeAreaBottom()) 105 ) { 106 Text(verbatim: VersionInfo.version) 107 .contextMenu { 108 Button { 109 UIPasteboard.general.string = VersionInfo.version 110 } label: { 111 Label(NSLocalizedString("Copy", comment: "Context menu option for copying the version of damus."), image: "copy2") 112 } 113 } 114 } 115 } 116 } 117 .navigationTitle(NSLocalizedString("Settings", comment: "Navigation title for Settings view.")) 118 .navigationBarTitleDisplayMode(.large) 119 .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) { 120 121 Button(NSLocalizedString("Cancel", comment: "Cancel deleting the user."), role: .cancel) { 122 delete_account_warning = false 123 } 124 Button(NSLocalizedString("Continue", comment: "Continue with deleting the user.")) { 125 confirm_delete_account = true 126 } 127 } 128 .alert(NSLocalizedString("Permanently Delete Account", comment: "Alert for deleting the users account."), isPresented: $confirm_delete_account) { 129 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) 130 Button(NSLocalizedString("Cancel", comment: "Cancel deleting the user."), role: .cancel) { 131 confirm_delete_account = false 132 } 133 Button(NSLocalizedString("Delete", comment: "Button for deleting the users account."), role: .destructive) { 134 guard let keypair = state.keypair.to_full(), 135 delete_text == DELETE_KEYWORD, 136 let ev = created_deleted_account_profile(keypair: keypair) else { 137 return 138 } 139 state.postbox.send(ev) 140 logout(state) 141 } 142 } 143 .alert(NSLocalizedString("Logout", comment: "Alert for logging out the user."), isPresented: $confirm_logout) { 144 Button(NSLocalizedString("Cancel", comment: "Cancel out of logging out the user."), role: .cancel) { 145 confirm_logout = false 146 } 147 Button(NSLocalizedString("Logout", comment: "Button for logging out the user."), role: .destructive) { 148 logout(state) 149 } 150 } message: { 151 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.") 152 } 153 .onReceive(handle_notify(.switched_timeline)) { _ in 154 dismiss() 155 } 156 } 157 158 } 159 160 struct ConfigView_Previews: PreviewProvider { 161 static var previews: some View { 162 NavigationView { 163 ConfigView(state: test_damus_state) 164 } 165 } 166 } 167 168 169 func handle_string_amount(new_value: String) -> Int? { 170 let filtered = new_value.filter { 171 $0.isNumber 172 } 173 174 if filtered == "" { 175 return nil 176 } 177 178 guard let amt = NumberFormatter().number(from: filtered) as? Int else { 179 return nil 180 } 181 182 return amt 183 }