damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

AppearanceSettingsView.swift (10221B)


      1 //
      2 //  TextFormattingSettings.swift
      3 //  damus
      4 //
      5 //  Created by William Casarin on 2023-04-05.
      6 //
      7 
      8 import SwiftUI
      9 
     10 fileprivate let CACHE_CLEAR_BUTTON_RESET_TIME_IN_SECONDS: Double = 60
     11 fileprivate let MINIMUM_CACHE_CLEAR_BUTTON_DELAY_IN_SECONDS: Double = 1
     12 
     13 /// A simple type to keep track of the cache clearing state
     14 fileprivate enum CacheClearingState {
     15     case not_cleared
     16     case clearing
     17     case cleared
     18 }
     19 
     20 struct ResizedEventPreview: View {
     21     let damus_state: DamusState
     22     @ObservedObject var settings: UserSettingsStore
     23 
     24     var body: some View {
     25         EventView(damus: damus_state, event: test_note, pubkey: test_note.pubkey, options: [.wide, .no_action_bar])
     26     }
     27 }
     28 
     29 struct AppearanceSettingsView: View {
     30     let damus_state: DamusState
     31     @ObservedObject var settings: UserSettingsStore
     32     @Environment(\.dismiss) var dismiss
     33     @State fileprivate var cache_clearing_state: CacheClearingState = .not_cleared
     34     @State var showing_cache_clear_alert: Bool = false
     35     
     36     @State var showing_enable_animation_alert: Bool = false
     37     @State var enable_animation_toggle_is_user_initiated: Bool = true
     38 
     39     var FontSize: some View {
     40         VStack(alignment: .leading) {
     41             Slider(value: $settings.font_size, in: 0.5...2.0, step: 0.1)
     42                 .padding()
     43 
     44             // Sample text to show how the font size would look
     45             ResizedEventPreview(damus_state: damus_state, settings: settings)
     46 
     47         }
     48     }
     49 
     50     var body: some View {
     51         Form {
     52             Section(NSLocalizedString("Font Size", comment: "Section label for font size settings.")) {
     53                 FontSize
     54             }
     55 
     56             // MARK: - Text Truncation
     57             Section(header: Text(NSLocalizedString("Text Truncation", comment: "Section header for damus text truncation user configuration"))) {
     58                 Toggle(NSLocalizedString("Truncate timeline text", comment: "Setting to truncate text in timeline"), isOn: $settings.truncate_timeline_text)
     59                     .toggleStyle(.switch)
     60                 Toggle(NSLocalizedString("Truncate notification mention text", comment: "Setting to truncate text in mention notifications"), isOn: $settings.truncate_mention_text)
     61                     .toggleStyle(.switch)
     62             }
     63 
     64             Section(header: Text("User Statuses", comment: "Section header for user profile status settings.")) {
     65                 Toggle(NSLocalizedString("Show general statuses", comment: "Settings toggle for enabling general user statuses"), isOn: $settings.show_general_statuses)
     66                     .toggleStyle(.switch)
     67 
     68                 Toggle(NSLocalizedString("Show music statuses", comment: "Settings toggle for enabling now playing music statuses"), isOn: $settings.show_music_statuses)
     69                     .toggleStyle(.switch)
     70             }
     71 
     72             // MARK: - Accessibility
     73             Section(header: Text(NSLocalizedString("Accessibility", comment: "Section header for accessibility settings"))) {
     74                 Toggle(NSLocalizedString("Left Handed", comment: "Moves the post button to the left side of the screen"), isOn: $settings.left_handed)
     75                     .toggleStyle(.switch)
     76             }
     77             
     78             // MARK: - Images
     79             Section(NSLocalizedString("Images", comment: "Section title for images configuration.")) {
     80                 self.EnableAnimationsToggle
     81                 Toggle(NSLocalizedString("Blur images", comment: "Setting to blur images"), isOn: $settings.blur_images)
     82                     .toggleStyle(.switch)
     83                 
     84                 Toggle(NSLocalizedString("Media previews", comment: "Setting to show media"), isOn: $settings.media_previews)
     85                     .toggleStyle(.switch)
     86                 
     87                 Picker(NSLocalizedString("Image uploader", comment: "Prompt selection of user's image uploader"),
     88                        selection: $settings.default_media_uploader) {
     89                     ForEach(MediaUploader.allCases, id: \.self) { uploader in
     90                         Text(uploader.model.displayName)
     91                             .tag(uploader.model.tag)
     92                     }
     93                 }
     94 
     95                 self.ClearCacheButton
     96             }
     97             
     98             // MARK: - Content filters and moderation
     99             Section(
    100                 header: Text(NSLocalizedString("Content filters", comment: "Section title for content filtering/moderation configuration.")),
    101                 footer: Text(NSLocalizedString("Notes with the #nsfw tag usually contains adult content or other \"Not safe for work\" content", comment: "Section footer clarifying what #nsfw (not safe for work) tags mean"))
    102             ) {
    103                 Toggle(NSLocalizedString("Hide notes with #nsfw tags", comment: "Setting to hide notes with the #nsfw (not safe for work) tags"), isOn: $settings.hide_nsfw_tagged_content)
    104                     .toggleStyle(.switch)
    105             }
    106             
    107             // MARK: - Profiles
    108             Section(
    109                 header: Text(NSLocalizedString("Profiles", comment: "Section title for profile view configuration.")),
    110                 footer: Text(NSLocalizedString("Profile action sheets allow you to follow, zap, or DM profiles more quickly without having to view their full profile", comment: "Section footer clarifying what the profile action sheet feature does"))
    111             ) {
    112                 Toggle(NSLocalizedString("Show profile action sheets", comment: "Setting to show profile action sheets when clicking on a user's profile picture"), isOn: $settings.show_profile_action_sheet_on_pfp_click)
    113                     .toggleStyle(.switch)
    114             }
    115                 
    116 
    117         }
    118         .navigationTitle(NSLocalizedString("Appearance", comment: "Navigation title for text and appearance settings."))
    119         .onReceive(handle_notify(.switched_timeline)) { _ in
    120             dismiss()
    121         }
    122     }
    123     
    124     func clear_cache_button_action() {
    125         cache_clearing_state = .clearing
    126         
    127         let group = DispatchGroup()
    128         
    129         group.enter()
    130         DamusCacheManager.shared.clear_cache(damus_state: self.damus_state, completion: {
    131             group.leave()
    132         })
    133         
    134         // Make clear cache button take at least a second or so to avoid issues with labor perception bias (https://growth.design/case-studies/labor-perception-bias)
    135         group.enter()
    136         DispatchQueue.main.asyncAfter(deadline: .now() + MINIMUM_CACHE_CLEAR_BUTTON_DELAY_IN_SECONDS) {
    137             group.leave()
    138         }
    139         
    140         group.notify(queue: .main) {
    141             cache_clearing_state = .cleared
    142             DispatchQueue.main.asyncAfter(deadline: .now() + CACHE_CLEAR_BUTTON_RESET_TIME_IN_SECONDS) {
    143                 cache_clearing_state = .not_cleared
    144             }
    145         }
    146     }
    147     
    148     var EnableAnimationsToggle: some View {
    149         Toggle(NSLocalizedString("Animations", comment: "Toggle to enable or disable image animation"), isOn: $settings.enable_animation)
    150             .toggleStyle(.switch)
    151             .onChange(of: settings.enable_animation) { _ in
    152                 if self.enable_animation_toggle_is_user_initiated {
    153                     self.showing_enable_animation_alert = true
    154                 }
    155                 else {
    156                     self.enable_animation_toggle_is_user_initiated = true
    157                 }
    158             }
    159             .alert(isPresented: $showing_enable_animation_alert) {
    160                 Alert(title: Text(NSLocalizedString("Confirmation", comment: "Confirmation dialog title")),
    161                       message: Text(NSLocalizedString("Changing this setting will cause the cache to be cleared. This will free space, but images may take longer to load again. Are you sure you want to proceed?", comment: "Message explaining consequences of changing the 'enable animation' setting")),
    162                       primaryButton: .default(Text(NSLocalizedString("OK", comment: "Button label indicating user wants to proceed."))) {
    163                           self.clear_cache_button_action()
    164                       },
    165                       secondaryButton: .cancel() {
    166                           // Toggle back if user cancels action
    167                           self.enable_animation_toggle_is_user_initiated = false
    168                           settings.enable_animation.toggle()
    169                       }
    170                 )
    171             }
    172     }
    173     
    174     var ClearCacheButton: some View {
    175         Button(action: { self.showing_cache_clear_alert = true }, label: {
    176             HStack(spacing: 6) {
    177                 switch cache_clearing_state {
    178                     case .not_cleared:
    179                         Text(NSLocalizedString("Clear Cache", comment: "Button to clear image cache."))
    180                     case .clearing:
    181                         ProgressView()
    182                         Text(NSLocalizedString("Clearing Cache", comment: "Loading message indicating that the cache is being cleared."))
    183                     case .cleared:
    184                         Image(systemName: "checkmark.circle.fill")
    185                             .foregroundColor(.green)
    186                         Text(NSLocalizedString("Cache has been cleared", comment: "Message indicating that the cache was successfully cleared."))
    187                 }
    188             }
    189         })
    190         .disabled(self.cache_clearing_state != .not_cleared)
    191         .alert(isPresented: $showing_cache_clear_alert) {
    192             Alert(title: Text(NSLocalizedString("Confirmation", comment: "Confirmation dialog title")),
    193                   message: Text(NSLocalizedString("Are you sure you want to clear the cache? This will free space, but images may take longer to load again.", comment: "Message explaining what it means to clear the cache, asking if user wants to proceed.")),
    194                   primaryButton: .default(Text(NSLocalizedString("OK", comment: "Button label indicating user wants to proceed."))) {
    195                       self.clear_cache_button_action()
    196                   },
    197                   secondaryButton: .cancel())
    198         }
    199     }
    200 }
    201 
    202 
    203 struct TextFormattingSettings_Previews: PreviewProvider {
    204     static var previews: some View {
    205         AppearanceSettingsView(damus_state: test_damus_state, settings: UserSettingsStore())
    206     }
    207 }