// // 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.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.alwaysShowStatusVisibilityIcon = try container.decode(Bool.self, forKey: .alwaysShowStatusVisibilityIcon) 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.expandAllContentWarnings = try container.decodeIfPresent(Bool.self, forKey: .expandAllContentWarnings) ?? false self.collapseLongPosts = try container.decodeIfPresent(Bool.self, forKey: .collapseLongPosts) ?? true self.oppositeCollapseKeywords = try container.decodeIfPresent([String].self, forKey: .oppositeCollapseKeywords) ?? [] self.confirmBeforeReblog = try container.decodeIfPresent(Bool.self, forKey: .confirmBeforeReblog) ?? false self.showFavoriteAndReblogCounts = try container.decode(Bool.self, forKey: .showFavoriteAndReblogCounts) self.defaultNotificationsMode = try container.decode(NotificationsMode.self, forKey: .defaultNotificationsType) self.grayscaleImages = try container.decodeIfPresent(Bool.self, forKey: .grayscaleImages) ?? false 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(avatarStyle, forKey: .avatarStyle) try container.encode(hideCustomEmojiInUsernames, forKey: .hideCustomEmojiInUsernames) try container.encode(showIsStatusReplyIcon, forKey: .showIsStatusReplyIcon) try container.encode(alwaysShowStatusVisibilityIcon, forKey: .alwaysShowStatusVisibilityIcon) 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(expandAllContentWarnings, forKey: .expandAllContentWarnings) try container.encode(collapseLongPosts, forKey: .collapseLongPosts) try container.encode(oppositeCollapseKeywords, forKey: .oppositeCollapseKeywords) try container.encode(confirmBeforeReblog, forKey: .confirmBeforeReblog) try container.encode(showFavoriteAndReblogCounts, forKey: .showFavoriteAndReblogCounts) try container.encode(defaultNotificationsMode, forKey: .defaultNotificationsType) try container.encode(grayscaleImages, forKey: .grayscaleImages) try container.encode(silentActions, forKey: .silentActions) try container.encode(statusContentType, forKey: .statusContentType) } // MARK: Appearance @Published var theme = UIUserInterfaceStyle.unspecified @Published var avatarStyle = AvatarStyle.roundRect @Published var hideCustomEmojiInUsernames = false @Published var showIsStatusReplyIcon = false @Published var alwaysShowStatusVisibilityIcon = 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 @Published var expandAllContentWarnings = false @Published var collapseLongPosts = true @Published var oppositeCollapseKeywords: [String] = [] @Published var confirmBeforeReblog = false // MARK: Digital Wellness @Published var showFavoriteAndReblogCounts = true @Published var defaultNotificationsMode = NotificationsMode.allNotifications @Published var grayscaleImages = false // MARK: Advanced @Published var silentActions: [String: Permission] = [:] @Published var statusContentType: StatusContentType = .plain private enum CodingKeys: String, CodingKey { case theme case avatarStyle case hideCustomEmojiInUsernames case showIsStatusReplyIcon case alwaysShowStatusVisibilityIcon case defaultPostVisibility case automaticallySaveDrafts case requireAttachmentDescriptions case contentWarningCopyMode case mentionReblogger case blurAllMedia case automaticallyPlayGifs case openLinksInApps case useInAppSafari case inAppSafariAutomaticReaderMode case expandAllContentWarnings case collapseLongPosts case oppositeCollapseKeywords case confirmBeforeReblog case showFavoriteAndReblogCounts case defaultNotificationsType case grayscaleImages case silentActions case statusContentType } } extension Preferences { enum Permission: String, Codable { case undecided, accepted, rejected } } extension UIUserInterfaceStyle: Codable {}