metatext/ServiceLayer/Sources/ServiceLayer/Utilities/AppPreferences.swift
2021-02-06 00:07:23 -08:00

227 lines
6.3 KiB
Swift

// Copyright © 2020 Metabolist. All rights reserved.
import CodableBloomFilter
import Foundation
import Mastodon
public struct AppPreferences {
private let userDefaults: UserDefaults
private let systemReduceMotion: () -> Bool
public init(environment: AppEnvironment) {
self.userDefaults = environment.userDefaults
self.systemReduceMotion = environment.reduceMotion
}
}
public extension AppPreferences {
enum StatusWord: String, CaseIterable, Identifiable {
case toot
case post
public var id: String { rawValue }
}
enum AnimateAvatars: String, CaseIterable, Identifiable {
case everywhere
case profiles
case never
public var id: String { rawValue }
}
enum Autoplay: String, CaseIterable, Identifiable {
case always
case wifi
case never
public var id: String { rawValue }
}
enum PositionBehavior: String, CaseIterable, Identifiable {
case rememberPosition
case syncPosition
case newest
public var id: String { rawValue }
}
var useSystemReduceMotionForMedia: Bool {
get { self[.useSystemReduceMotionForMedia] ?? true }
set { self[.useSystemReduceMotionForMedia] = newValue }
}
var statusWord: StatusWord {
get {
if let rawValue = self[.statusWord] as String?,
let value = StatusWord(rawValue: rawValue) {
return value
}
return .toot
}
set { self[.statusWord] = newValue.rawValue }
}
var animateAvatars: AnimateAvatars {
get {
if let rawValue = self[.animateAvatars] as String?,
let value = AnimateAvatars(rawValue: rawValue) {
return value
}
return .everywhere
}
set { self[.animateAvatars] = newValue.rawValue }
}
var animateHeaders: Bool {
get { self[.animateHeaders] ?? true }
set { self[.animateHeaders] = newValue }
}
var autoplayGIFs: Autoplay {
get {
if let rawValue = self[.autoplayGIFs] as String?,
let value = Autoplay(rawValue: rawValue) {
return value
}
return .always
}
set { self[.autoplayGIFs] = newValue.rawValue }
}
var autoplayVideos: Autoplay {
get {
if let rawValue = self[.autoplayVideos] as String?,
let value = Autoplay(rawValue: rawValue) {
return value
}
return .wifi
}
set { self[.autoplayVideos] = newValue.rawValue }
}
var homeTimelineBehavior: PositionBehavior {
get {
if let rawValue = self[.homeTimelineBehavior] as String?,
let value = PositionBehavior(rawValue: rawValue) {
return value
}
return .rememberPosition
}
set { self[.homeTimelineBehavior] = newValue.rawValue }
}
var notificationsTabBehavior: PositionBehavior {
get {
if let rawValue = self[.notificationsTabBehavior] as String?,
let value = PositionBehavior(rawValue: rawValue) {
return value
}
return .newest
}
set { self[.notificationsTabBehavior] = newValue.rawValue }
}
var defaultEmojiSkinTone: SystemEmoji.SkinTone? {
get {
if let rawValue = self[.defaultEmojiSkinTone] as Int?,
let value = SystemEmoji.SkinTone(rawValue: rawValue) {
return value
}
return nil
}
set { self[.defaultEmojiSkinTone] = newValue?.rawValue }
}
var notificationSounds: Set<MastodonNotification.NotificationType> {
get {
Set((self[.notificationSounds] as [String]?)?.compactMap {
MastodonNotification.NotificationType(rawValue: $0)
} ?? MastodonNotification.NotificationType.allCasesExceptUnknown)
}
set { self[.notificationSounds] = newValue.map { $0.rawValue } }
}
var shouldReduceMotion: Bool {
systemReduceMotion() && useSystemReduceMotionForMedia
}
func positionBehavior(markerTimeline: Marker.Timeline) -> PositionBehavior {
switch markerTimeline {
case .home:
return homeTimelineBehavior
case .notifications:
return notificationsTabBehavior
}
}
var showReblogAndFavoriteCounts: Bool {
get { self[.showReblogAndFavoriteCounts] ?? false }
set { self[.showReblogAndFavoriteCounts] = newValue }
}
var requireDoubleTapToReblog: Bool {
get { self[.requireDoubleTapToReblog] ?? false }
set { self[.requireDoubleTapToReblog] = newValue }
}
var requireDoubleTapToFavorite: Bool {
get { self[.requireDoubleTapToFavorite] ?? false }
set { self[.requireDoubleTapToFavorite] = newValue }
}
var notificationPictures: Bool {
get { self[.notificationPictures] ?? true }
set { self[.notificationPictures] = newValue }
}
var notificationAccountName: Bool {
get { self[.notificationAccountName] ?? false }
set { self[.notificationAccountName] = newValue }
}
var openLinksInDefaultBrowser: Bool {
get { self[.openLinksInDefaultBrowser] ?? false }
set { self[.openLinksInDefaultBrowser] = newValue }
}
var useUniversalLinks: Bool {
get { self[.useUniversalLinks] ?? true }
set { self[.useUniversalLinks] = newValue }
}
}
private extension AppPreferences {
enum Item: String {
case statusWord
case requireDoubleTapToReblog
case requireDoubleTapToFavorite
case useSystemReduceMotionForMedia
case animateAvatars
case animateHeaders
case autoplayGIFs
case autoplayVideos
case homeTimelineBehavior
case notificationsTabBehavior
case defaultEmojiSkinTone
case showReblogAndFavoriteCounts
case notificationPictures
case notificationAccountName
case notificationSounds
case openLinksInDefaultBrowser
case useUniversalLinks
}
subscript<T>(index: Item) -> T? {
get { userDefaults.value(forKey: index.rawValue) as? T }
set { userDefaults.set(newValue, forKey: index.rawValue) }
}
}