// // Preferences.swift // Tusker // // Created by Shadowfacts on 8/28/18. // Copyright © 2018 Shadowfacts. All rights reserved. // import Foundation import Pachyderm import Combine class Preferences: Codable, ObservableObject { static var shared: Preferences = load() private static var documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! private static var archiveURL = Preferences.documentsDirectory.appendingPathComponent("preferences").appendingPathExtension("plist") static func save() { let encoder = PropertyListEncoder() let data = try? encoder.encode(shared) try? data?.write(to: archiveURL, options: .noFileProtection) } static func load() -> Preferences { let decoder = PropertyListDecoder() if let data = try? Data(contentsOf: archiveURL), let preferences = try? decoder.decode(Preferences.self, from: data) { return preferences } return Preferences() } private init() {} required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.theme = try container.decode(UIUserInterfaceStyle.self, forKey: .theme) self.showRepliesInProfiles = try container.decode(Bool.self, forKey: .showRepliesInProfiles) self.avatarStyle = try container.decode(AvatarStyle.self, forKey: .avatarStyle) self.hideCustomEmojiInUsernames = try container.decode(Bool.self, forKey: .hideCustomEmojiInUsernames) self.showIsStatusReplyIcon = try container.decode(Bool.self, forKey: .showIsStatusReplyIcon) self.defaultPostVisibility = try container.decode(Status.Visibility.self, forKey: .defaultPostVisibility) self.automaticallySaveDrafts = try container.decode(Bool.self, forKey: .automaticallySaveDrafts) self.requireAttachmentDescriptions = try container.decode(Bool.self, forKey: .requireAttachmentDescriptions) self.contentWarningCopyMode = try container.decode(ContentWarningCopyMode.self, forKey: .contentWarningCopyMode) self.mentionReblogger = try container.decode(Bool.self, forKey: .mentionReblogger) self.blurAllMedia = try container.decode(Bool.self, forKey: .blurAllMedia) self.automaticallyPlayGifs = try container.decode(Bool.self, forKey: .automaticallyPlayGifs) self.openLinksInApps = try container.decode(Bool.self, forKey: .openLinksInApps) self.useInAppSafari = try container.decode(Bool.self, forKey: .useInAppSafari) self.inAppSafariAutomaticReaderMode = try container.decode(Bool.self, forKey: .inAppSafariAutomaticReaderMode) self.showFavoriteAndReblogCounts = try container.decode(Bool.self, forKey: .showFavoriteAndReblogCounts) self.defaultNotificationsMode = try container.decode(NotificationsMode.self, forKey: .defaultNotificationsType) self.silentActions = try container.decode([String: Permission].self, forKey: .silentActions) self.statusContentType = try container.decode(StatusContentType.self, forKey: .statusContentType) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(theme, forKey: .theme) try container.encode(showRepliesInProfiles, forKey: .showRepliesInProfiles) try container.encode(avatarStyle, forKey: .avatarStyle) try container.encode(hideCustomEmojiInUsernames, forKey: .hideCustomEmojiInUsernames) try container.encode(showIsStatusReplyIcon, forKey: .showIsStatusReplyIcon) try container.encode(defaultPostVisibility, forKey: .defaultPostVisibility) try container.encode(automaticallySaveDrafts, forKey: .automaticallySaveDrafts) try container.encode(requireAttachmentDescriptions, forKey: .requireAttachmentDescriptions) try container.encode(contentWarningCopyMode, forKey: .contentWarningCopyMode) try container.encode(mentionReblogger, forKey: .mentionReblogger) try container.encode(blurAllMedia, forKey: .blurAllMedia) try container.encode(automaticallyPlayGifs, forKey: .automaticallyPlayGifs) try container.encode(openLinksInApps, forKey: .openLinksInApps) try container.encode(useInAppSafari, forKey: .useInAppSafari) try container.encode(inAppSafariAutomaticReaderMode, forKey: .inAppSafariAutomaticReaderMode) try container.encode(showFavoriteAndReblogCounts, forKey: .showFavoriteAndReblogCounts) try container.encode(defaultNotificationsMode, forKey: .defaultNotificationsType) try container.encode(silentActions, forKey: .silentActions) try container.encode(statusContentType, forKey: .statusContentType) } // MARK: Appearance @Published var theme = UIUserInterfaceStyle.unspecified @Published var showRepliesInProfiles = false @Published var avatarStyle = AvatarStyle.roundRect @Published var hideCustomEmojiInUsernames = false @Published var showIsStatusReplyIcon = false // MARK: Composing @Published var defaultPostVisibility = Status.Visibility.public @Published var automaticallySaveDrafts = true @Published var requireAttachmentDescriptions = false @Published var contentWarningCopyMode = ContentWarningCopyMode.asIs @Published var mentionReblogger = false // MARK: Media @Published var blurAllMedia = false @Published var automaticallyPlayGifs = true // MARK: Behavior @Published var openLinksInApps = true @Published var useInAppSafari = true @Published var inAppSafariAutomaticReaderMode = false // MARK: Digital Wellness @Published var showFavoriteAndReblogCounts = true @Published var defaultNotificationsMode = NotificationsMode.allNotifications // MARK: Advanced @Published var silentActions: [String: Permission] = [:] @Published var statusContentType: StatusContentType = .plain enum CodingKeys: String, CodingKey { case theme case showRepliesInProfiles case avatarStyle case hideCustomEmojiInUsernames case showIsStatusReplyIcon case defaultPostVisibility case automaticallySaveDrafts case requireAttachmentDescriptions case contentWarningCopyMode case mentionReblogger case blurAllMedia case automaticallyPlayGifs case openLinksInApps case useInAppSafari case inAppSafariAutomaticReaderMode case showFavoriteAndReblogCounts case defaultNotificationsType case silentActions case statusContentType } } extension Preferences { enum Permission: String, Codable { case undecided, accepted, rejected } } extension UIUserInterfaceStyle: Codable {}