Settings refactor

This commit is contained in:
Justin Mazzocchi 2021-03-05 18:25:18 -08:00
parent 707eef959e
commit 94d0b2338f
No known key found for this signature in database
GPG Key ID: E223E6937AAFB01C
15 changed files with 39 additions and 58 deletions

View File

@ -94,8 +94,7 @@ private extension Account {
} }
.compactMap(URL.init(string:))) .compactMap(URL.init(string:)))
if !identityContext.appPreferences.shouldReduceMotion if identityContext.appPreferences.animateAvatars == .everywhere {
&& identityContext.appPreferences.animateAvatars == .everywhere {
urls.insert(avatar) urls.insert(avatar)
} else { } else {
urls.insert(avatarStatic) urls.insert(avatarStatic)

View File

@ -14,8 +14,7 @@ extension NSMutableAttributedString {
let attachment = AnimatedTextAttachment() let attachment = AnimatedTextAttachment()
let imageURL: URL? let imageURL: URL?
if !identityContext.appPreferences.shouldReduceMotion, if identityContext.appPreferences.animateCustomEmojis,
identityContext.appPreferences.animateCustomEmojis,
let urlString = emoji.url { let urlString = emoji.url {
imageURL = URL(stringEscapingPath: urlString) imageURL = URL(stringEscapingPath: urlString)
} else if let staticURLString = emoji.staticUrl { } else if let staticURLString = emoji.staticUrl {

View File

@ -192,7 +192,6 @@
"preferences.blocked-domains" = "Blocked Domains"; "preferences.blocked-domains" = "Blocked Domains";
"preferences.blocked-users" = "Blocked Users"; "preferences.blocked-users" = "Blocked Users";
"preferences.media" = "Media"; "preferences.media" = "Media";
"preferences.media.use-system-reduce-motion" = "Use system reduce motion setting";
"preferences.media.avatars" = "Avatars"; "preferences.media.avatars" = "Avatars";
"preferences.media.avatars.animate" = "Animate avatars"; "preferences.media.avatars.animate" = "Animate avatars";
"preferences.media.avatars.animate.everywhere" = "Everywhere"; "preferences.media.avatars.animate.everywhere" = "Everywhere";

View File

@ -75,7 +75,8 @@ final class NotificationService: UNNotificationServiceExtension {
private extension NotificationService { private extension NotificationService {
private static let environment = AppEnvironment.live( private static let environment = AppEnvironment.live(
userNotificationCenter: .current(), userNotificationCenter: .current(),
reduceMotion: { false }) reduceMotion: { false },
autoplayVideos: { true })
enum ImageError: Error { enum ImageError: Error {
case dataMissing case dataMissing

View File

@ -14,6 +14,7 @@ public struct AppEnvironment {
let userDefaults: UserDefaults let userDefaults: UserDefaults
let userNotificationClient: UserNotificationClient let userNotificationClient: UserNotificationClient
let reduceMotion: () -> Bool let reduceMotion: () -> Bool
let autoplayVideos: () -> Bool
let uuid: () -> UUID let uuid: () -> UUID
let inMemoryContent: Bool let inMemoryContent: Bool
let fixtureDatabase: IdentityDatabase? let fixtureDatabase: IdentityDatabase?
@ -24,6 +25,7 @@ public struct AppEnvironment {
userDefaults: UserDefaults, userDefaults: UserDefaults,
userNotificationClient: UserNotificationClient, userNotificationClient: UserNotificationClient,
reduceMotion: @escaping () -> Bool, reduceMotion: @escaping () -> Bool,
autoplayVideos: @escaping () -> Bool,
uuid: @escaping () -> UUID, uuid: @escaping () -> UUID,
inMemoryContent: Bool, inMemoryContent: Bool,
fixtureDatabase: IdentityDatabase?) { fixtureDatabase: IdentityDatabase?) {
@ -33,6 +35,7 @@ public struct AppEnvironment {
self.userDefaults = userDefaults self.userDefaults = userDefaults
self.userNotificationClient = userNotificationClient self.userNotificationClient = userNotificationClient
self.reduceMotion = reduceMotion self.reduceMotion = reduceMotion
self.autoplayVideos = autoplayVideos
self.uuid = uuid self.uuid = uuid
self.inMemoryContent = inMemoryContent self.inMemoryContent = inMemoryContent
self.fixtureDatabase = fixtureDatabase self.fixtureDatabase = fixtureDatabase
@ -42,7 +45,9 @@ public struct AppEnvironment {
public extension AppEnvironment { public extension AppEnvironment {
static let appGroup = "group.metabolist.metatext" static let appGroup = "group.metabolist.metatext"
static func live(userNotificationCenter: UNUserNotificationCenter, reduceMotion: @escaping () -> Bool) -> Self { static func live(userNotificationCenter: UNUserNotificationCenter,
reduceMotion: @escaping () -> Bool,
autoplayVideos: @escaping () -> Bool) -> Self {
Self( Self(
session: URLSession.shared, session: URLSession.shared,
webAuthSessionType: LiveWebAuthSession.self, webAuthSessionType: LiveWebAuthSession.self,
@ -50,6 +55,7 @@ public extension AppEnvironment {
userDefaults: UserDefaults(suiteName: appGroup)!, userDefaults: UserDefaults(suiteName: appGroup)!,
userNotificationClient: .live(userNotificationCenter), userNotificationClient: .live(userNotificationCenter),
reduceMotion: reduceMotion, reduceMotion: reduceMotion,
autoplayVideos: autoplayVideos,
uuid: UUID.init, uuid: UUID.init,
inMemoryContent: false, inMemoryContent: false,
fixtureDatabase: nil) fixtureDatabase: nil)

View File

@ -7,10 +7,12 @@ import Mastodon
public struct AppPreferences { public struct AppPreferences {
private let userDefaults: UserDefaults private let userDefaults: UserDefaults
private let systemReduceMotion: () -> Bool private let systemReduceMotion: () -> Bool
private let systemAutoplayVideos: () -> Bool
public init(environment: AppEnvironment) { public init(environment: AppEnvironment) {
self.userDefaults = environment.userDefaults self.userDefaults = environment.userDefaults
self.systemReduceMotion = environment.reduceMotion self.systemReduceMotion = environment.reduceMotion
self.systemAutoplayVideos = environment.autoplayVideos
} }
} }
@ -45,11 +47,6 @@ public extension AppPreferences {
public var id: String { rawValue } public var id: String { rawValue }
} }
var useSystemReduceMotionForMedia: Bool {
get { self[.useSystemReduceMotionForMedia] ?? true }
set { self[.useSystemReduceMotionForMedia] = newValue }
}
var statusWord: StatusWord { var statusWord: StatusWord {
get { get {
if let rawValue = self[.statusWord] as String?, if let rawValue = self[.statusWord] as String?,
@ -69,18 +66,18 @@ public extension AppPreferences {
return value return value
} }
return .everywhere return systemReduceMotion() ? .never : .everywhere
} }
set { self[.animateAvatars] = newValue.rawValue } set { self[.animateAvatars] = newValue.rawValue }
} }
var animateHeaders: Bool { var animateHeaders: Bool {
get { self[.animateHeaders] ?? true } get { self[.animateHeaders] ?? !systemReduceMotion() }
set { self[.animateHeaders] = newValue } set { self[.animateHeaders] = newValue }
} }
var animateCustomEmojis: Bool { var animateCustomEmojis: Bool {
get { self[.animateCustomEmojis] ?? true } get { self[.animateCustomEmojis] ?? !systemReduceMotion() }
set { self[.animateCustomEmojis] = newValue } set { self[.animateCustomEmojis] = newValue }
} }
@ -91,7 +88,7 @@ public extension AppPreferences {
return value return value
} }
return .always return (!systemAutoplayVideos() || systemReduceMotion()) ? .never : .always
} }
set { self[.autoplayGIFs] = newValue.rawValue } set { self[.autoplayGIFs] = newValue.rawValue }
} }
@ -103,7 +100,7 @@ public extension AppPreferences {
return value return value
} }
return .wifi return (!systemAutoplayVideos() || systemReduceMotion()) ? .never : .wifi
} }
set { self[.autoplayVideos] = newValue.rawValue } set { self[.autoplayVideos] = newValue.rawValue }
} }
@ -141,10 +138,6 @@ public extension AppPreferences {
set { self[.notificationSounds] = newValue.map { $0.rawValue } } set { self[.notificationSounds] = newValue.map { $0.rawValue } }
} }
var shouldReduceMotion: Bool {
systemReduceMotion() && useSystemReduceMotionForMedia
}
func positionBehavior(timeline: Timeline) -> PositionBehavior { func positionBehavior(timeline: Timeline) -> PositionBehavior {
switch timeline { switch timeline {
case .home: case .home:
@ -195,7 +188,6 @@ private extension AppPreferences {
case statusWord case statusWord
case requireDoubleTapToReblog case requireDoubleTapToReblog
case requireDoubleTapToFavorite case requireDoubleTapToFavorite
case useSystemReduceMotionForMedia
case animateAvatars case animateAvatars
case animateHeaders case animateHeaders
case animateCustomEmojis case animateCustomEmojis

View File

@ -24,6 +24,7 @@ public extension AppEnvironment {
userDefaults: userDefaults, userDefaults: userDefaults,
userNotificationClient: userNotificationClient, userNotificationClient: userNotificationClient,
reduceMotion: { false }, reduceMotion: { false },
autoplayVideos: { true },
uuid: uuid, uuid: uuid,
inMemoryContent: inMemoryContent, inMemoryContent: inMemoryContent,
fixtureDatabase: fixtureDatabase) fixtureDatabase: fixtureDatabase)

View File

@ -10,7 +10,8 @@ import ViewModels
class ShareExtensionNavigationViewController: UINavigationController { class ShareExtensionNavigationViewController: UINavigationController {
private let environment = AppEnvironment.live( private let environment = AppEnvironment.live(
userNotificationCenter: .current(), userNotificationCenter: .current(),
reduceMotion: { UIAccessibility.isReduceMotionEnabled }) reduceMotion: { UIAccessibility.isReduceMotionEnabled },
autoplayVideos: { UIAccessibility.isVideoAutoplayEnabled })
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()

View File

@ -27,5 +27,6 @@ struct MetatextApp: App {
private extension MetatextApp { private extension MetatextApp {
static let environment = AppEnvironment.live( static let environment = AppEnvironment.live(
userNotificationCenter: .current(), userNotificationCenter: .current(),
reduceMotion: { UIAccessibility.isReduceMotionEnabled }) reduceMotion: { UIAccessibility.isReduceMotionEnabled },
autoplayVideos: { UIAccessibility.isVideoAutoplayEnabled })
} }

View File

@ -28,7 +28,7 @@ public extension AccountViewModel {
var id: Account.Id { accountService.account.id } var id: Account.Id { accountService.account.id }
var headerURL: URL { var headerURL: URL {
if !identityContext.appPreferences.shouldReduceMotion, identityContext.appPreferences.animateHeaders { if identityContext.appPreferences.animateHeaders {
return accountService.account.header return accountService.account.header
} else { } else {
return accountService.account.headerStatic return accountService.account.headerStatic
@ -64,9 +64,8 @@ public extension AccountViewModel {
var isSelf: Bool { accountService.account.id == identityContext.identity.account?.id } var isSelf: Bool { accountService.account.id == identityContext.identity.account?.id }
func avatarURL(profile: Bool = false) -> URL { func avatarURL(profile: Bool = false) -> URL {
if !identityContext.appPreferences.shouldReduceMotion, if identityContext.appPreferences.animateAvatars == .everywhere
(identityContext.appPreferences.animateAvatars == .everywhere || (identityContext.appPreferences.animateAvatars == .profiles && profile) {
|| (identityContext.appPreferences.animateAvatars == .profiles && profile)) {
return accountService.account.avatar return accountService.account.avatar
} else { } else {
return accountService.account.avatarStatic return accountService.account.avatarStatic

View File

@ -82,8 +82,7 @@ public extension StatusViewModel {
var accountName: String { "@".appending(statusService.status.displayStatus.account.acct) } var accountName: String { "@".appending(statusService.status.displayStatus.account.acct) }
var avatarURL: URL { var avatarURL: URL {
if !identityContext.appPreferences.shouldReduceMotion, if identityContext.appPreferences.animateAvatars == .everywhere {
identityContext.appPreferences.animateAvatars == .everywhere {
return statusService.status.displayStatus.account.avatar return statusService.status.displayStatus.account.avatar
} else { } else {
return statusService.status.displayStatus.account.avatarStatic return statusService.status.displayStatus.account.avatarStatic
@ -91,8 +90,7 @@ public extension StatusViewModel {
} }
var rebloggerAvatarURL: URL { var rebloggerAvatarURL: URL {
if !identityContext.appPreferences.shouldReduceMotion, if identityContext.appPreferences.animateAvatars == .everywhere {
identityContext.appPreferences.animateAvatars == .everywhere {
return statusService.status.account.avatar return statusService.status.account.avatar
} else { } else {
return statusService.status.account.avatarStatic return statusService.status.account.avatarStatic

View File

@ -1,5 +1,6 @@
// Copyright © 2020 Metabolist. All rights reserved. // Copyright © 2020 Metabolist. All rights reserved.
import Combine
import Mastodon import Mastodon
import SwiftUI import SwiftUI
import ViewModels import ViewModels
@ -107,40 +108,31 @@ struct PreferencesView: View {
Toggle("preferences.links.use-universal-links", Toggle("preferences.links.use-universal-links",
isOn: $identityContext.appPreferences.useUniversalLinks) isOn: $identityContext.appPreferences.useUniversalLinks)
} }
if accessibilityReduceMotion {
Toggle("preferences.media.use-system-reduce-motion",
isOn: $identityContext.appPreferences.useSystemReduceMotionForMedia)
}
} }
Group { Group {
Picker("preferences.media.autoplay.gifs", Picker("preferences.media.autoplay.gifs",
selection: reduceMotion ? .constant(.never) : $identityContext.appPreferences.autoplayGIFs) { selection: $identityContext.appPreferences.autoplayGIFs) {
ForEach(AppPreferences.Autoplay.allCases) { option in ForEach(AppPreferences.Autoplay.allCases) { option in
Text(option.localizedStringKey).tag(option) Text(option.localizedStringKey).tag(option)
} }
} }
Picker("preferences.media.autoplay.videos", Picker("preferences.media.autoplay.videos",
selection: reduceMotion selection: $identityContext.appPreferences.autoplayVideos) {
? .constant(.never) : $identityContext.appPreferences.autoplayVideos) {
ForEach(AppPreferences.Autoplay.allCases) { option in ForEach(AppPreferences.Autoplay.allCases) { option in
Text(option.localizedStringKey).tag(option) Text(option.localizedStringKey).tag(option)
} }
} }
Picker("preferences.media.avatars.animate", Picker("preferences.media.avatars.animate",
selection: reduceMotion selection: $identityContext.appPreferences.animateAvatars) {
? .constant(.never) : $identityContext.appPreferences.animateAvatars) {
ForEach(AppPreferences.AnimateAvatars.allCases) { option in ForEach(AppPreferences.AnimateAvatars.allCases) { option in
Text(option.localizedStringKey).tag(option) Text(option.localizedStringKey).tag(option)
} }
} }
Toggle("preferences.media.custom-emojis.animate", Toggle("preferences.media.custom-emojis.animate",
isOn: reduceMotion ? .constant(false) : $identityContext.appPreferences.animateCustomEmojis) isOn: $identityContext.appPreferences.animateCustomEmojis)
.disabled(reduceMotion)
Toggle("preferences.media.headers.animate", Toggle("preferences.media.headers.animate",
isOn: reduceMotion ? .constant(false) : $identityContext.appPreferences.animateHeaders) isOn: $identityContext.appPreferences.animateHeaders)
.disabled(reduceMotion)
} }
.disabled(reduceMotion)
if viewModel.identityContext.identity.authenticated if viewModel.identityContext.identity.authenticated
&& !viewModel.identityContext.identity.pending { && !viewModel.identityContext.identity.pending {
Picker("preferences.home-timeline-position-on-startup", Picker("preferences.home-timeline-position-on-startup",
@ -154,12 +146,10 @@ struct PreferencesView: View {
} }
.navigationTitle("preferences") .navigationTitle("preferences")
.alertItem($viewModel.alertItem) .alertItem($viewModel.alertItem)
} .onReceive(NotificationCenter.default.publisher(
} for: UIAccessibility.videoAutoplayStatusDidChangeNotification)) { _ in
viewModel.objectWillChange.send()
private extension PreferencesView { }
var reduceMotion: Bool {
identityContext.appPreferences.shouldReduceMotion
} }
} }

View File

@ -195,7 +195,6 @@ private extension CompositionView {
guard let self = self else { return } guard let self = self else { return }
let avatarURL = $0.appPreferences.animateAvatars == .everywhere let avatarURL = $0.appPreferences.animateAvatars == .everywhere
&& !$0.appPreferences.shouldReduceMotion
? $0.identity.account?.avatar ? $0.identity.account?.avatar
: $0.identity.account?.avatarStatic : $0.identity.account?.avatarStatic

View File

@ -73,10 +73,7 @@ private extension AutocompleteItemView {
switch autocompleteItemConfiguration.item { switch autocompleteItemConfiguration.item {
case let .account(account): case let .account(account):
let appPreferences = autocompleteItemConfiguration.identityContext.appPreferences let appPreferences = autocompleteItemConfiguration.identityContext.appPreferences
let avatarURL = appPreferences.animateAvatars == .everywhere let avatarURL = appPreferences.animateAvatars == .everywhere ? account.avatar : account.avatarStatic
&& !appPreferences.shouldReduceMotion
? account.avatar
: account.avatarStatic
imageView.sd_setImage(with: avatarURL) imageView.sd_setImage(with: avatarURL)
imageView.isHidden = false imageView.isHidden = false

View File

@ -66,7 +66,6 @@ private extension SecondaryNavigationTitleView {
func applyViewModel() { func applyViewModel() {
let avatarURL = viewModel.identityContext.appPreferences.animateAvatars == .everywhere let avatarURL = viewModel.identityContext.appPreferences.animateAvatars == .everywhere
&& !viewModel.identityContext.appPreferences.shouldReduceMotion
? viewModel.identityContext.identity.account?.avatar ? viewModel.identityContext.identity.account?.avatar
: viewModel.identityContext.identity.account?.avatarStatic : viewModel.identityContext.identity.account?.avatarStatic