metatext-app-ios-iphone-ipad/ServiceLayer/Sources/ServiceLayer/Utilities/AppPreferences.swift

215 lines
6.0 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 }
}
}
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
}
subscript<T>(index: Item) -> T? {
get { userDefaults.value(forKey: index.rawValue) as? T }
set { userDefaults.set(newValue, forKey: index.rawValue) }
}
}