mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-11 00:25:35 +00:00
UserPreferences -> Observable
This commit is contained in:
parent
fd09276d49
commit
6c23569d15
32 changed files with 390 additions and 122 deletions
|
@ -113,7 +113,7 @@ extension View {
|
|||
|
||||
func withEnvironments() -> some View {
|
||||
environment(CurrentAccount.shared)
|
||||
.environmentObject(UserPreferences.shared)
|
||||
.environment(UserPreferences.shared)
|
||||
.environment(CurrentInstance.shared)
|
||||
.environment(Theme.shared)
|
||||
.environment(AppAccountsManager.shared)
|
||||
|
|
|
@ -18,7 +18,7 @@ struct IceCubesApp: App {
|
|||
@State private var appAccountsManager = AppAccountsManager.shared
|
||||
@State private var currentInstance = CurrentInstance.shared
|
||||
@State private var currentAccount = CurrentAccount.shared
|
||||
@StateObject private var userPreferences = UserPreferences.shared
|
||||
@State private var userPreferences = UserPreferences.shared
|
||||
@State private var pushNotificationsService = PushNotificationsService.shared
|
||||
@State private var watcher = StreamWatcher()
|
||||
@State private var quickLook = QuickLook()
|
||||
|
@ -48,7 +48,7 @@ struct IceCubesApp: App {
|
|||
.environment(quickLook)
|
||||
.environment(currentAccount)
|
||||
.environment(currentInstance)
|
||||
.environmentObject(userPreferences)
|
||||
.environment(userPreferences)
|
||||
.environment(theme)
|
||||
.environment(watcher)
|
||||
.environment(pushNotificationsService)
|
||||
|
|
|
@ -13,7 +13,7 @@ extension View {
|
|||
@MainActor
|
||||
private struct SafariRouter: ViewModifier {
|
||||
@Environment(Theme.self) private var theme
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(RouterPath.self) private var routerPath
|
||||
|
||||
@State private var safariManager = InAppSafariManager()
|
||||
|
|
|
@ -5,12 +5,13 @@ import Env
|
|||
import Models
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct SideBarView<Content: View>: View {
|
||||
@Environment(AppAccountsManager.self) private var appAccounts
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(StreamWatcher.self) private var watcher
|
||||
@EnvironmentObject private var userPreferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var userPreferences
|
||||
@Environment(RouterPath.self) private var routerPath
|
||||
|
||||
@Binding var selectedTab: Tab
|
||||
|
|
|
@ -7,9 +7,10 @@ import Network
|
|||
import Shimmer
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct ExploreTab: View {
|
||||
@Environment(Theme.self) private var theme
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@Environment(Client.self) private var client
|
||||
@State private var routerPath = RouterPath()
|
||||
|
|
|
@ -7,6 +7,7 @@ import Notifications
|
|||
import SwiftUI
|
||||
import Timeline
|
||||
|
||||
@MainActor
|
||||
struct NotificationsTab: View {
|
||||
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
|
@ -16,7 +17,7 @@ struct NotificationsTab: View {
|
|||
@Environment(StreamWatcher.self) private var watcher
|
||||
@Environment(AppAccountsManager.self) private var appAccount
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@EnvironmentObject private var userPreferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var userPreferences
|
||||
@Environment(PushNotificationsService.self) private var pushNotificationsService
|
||||
@State private var routerPath = RouterPath()
|
||||
@Binding var popToRootTab: Tab
|
||||
|
|
|
@ -7,11 +7,13 @@ import NukeUI
|
|||
import SwiftUI
|
||||
import UserNotifications
|
||||
|
||||
@MainActor
|
||||
struct ContentSettingsView: View {
|
||||
@EnvironmentObject private var userPreferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var userPreferences
|
||||
@Environment(Theme.self) private var theme
|
||||
|
||||
var body: some View {
|
||||
@Bindable var userPreferences = userPreferences
|
||||
Form {
|
||||
Section("settings.content.boosts") {
|
||||
Toggle(isOn: $userPreferences.suppressDupeReblogs) {
|
||||
|
|
|
@ -18,12 +18,13 @@ import SwiftUI
|
|||
init() {}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
struct DisplaySettingsView: View {
|
||||
typealias FontState = Theme.FontState
|
||||
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
@Environment(Theme.self) private var theme
|
||||
@EnvironmentObject private var userPreferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var userPreferences
|
||||
|
||||
@State private var localValues = DisplaySettingsLocalValues()
|
||||
|
||||
|
@ -180,6 +181,7 @@ struct DisplaySettingsView: View {
|
|||
@ViewBuilder
|
||||
private var layoutSection: some View {
|
||||
@Bindable var theme = theme
|
||||
@Bindable var userPreferences = userPreferences
|
||||
Section("settings.display.section.display") {
|
||||
Picker("settings.display.avatar.position", selection: $theme.avatarPosition) {
|
||||
ForEach(Theme.AvatarPosition.allCases, id: \.rawValue) { position in
|
||||
|
@ -210,6 +212,7 @@ struct DisplaySettingsView: View {
|
|||
|
||||
@ViewBuilder
|
||||
private var platformsSection: some View {
|
||||
@Bindable var userPreferences = userPreferences
|
||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||
Section("iPhone") {
|
||||
Toggle("settings.display.show-tab-label", isOn: $userPreferences.showiPhoneTabLabel)
|
||||
|
|
|
@ -4,11 +4,13 @@ import Models
|
|||
import Status
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct HapticSettingsView: View {
|
||||
@Environment(Theme.self) private var theme
|
||||
@EnvironmentObject private var userPreferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var userPreferences
|
||||
|
||||
var body: some View {
|
||||
@Bindable var userPreferences = userPreferences
|
||||
Form {
|
||||
Section {
|
||||
Toggle("settings.haptic.timeline", isOn: $userPreferences.hapticTimelineEnabled)
|
||||
|
|
|
@ -9,11 +9,12 @@ import Nuke
|
|||
import SwiftUI
|
||||
import Timeline
|
||||
|
||||
@MainActor
|
||||
struct SettingsTabs: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@Environment(PushNotificationsService.self) private var pushNotifications
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Client.self) private var client
|
||||
@Environment(CurrentInstance.self) private var currentInstance
|
||||
@Environment(AppAccountsManager.self) private var appAccountsManager
|
||||
|
@ -158,7 +159,9 @@ struct SettingsTabs: View {
|
|||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var otherSections: some View {
|
||||
@Bindable var preferences = preferences
|
||||
Section("settings.section.other") {
|
||||
if !ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
Picker(selection: $preferences.preferredBrowser) {
|
||||
|
|
|
@ -2,11 +2,13 @@ import DesignSystem
|
|||
import Env
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct SwipeActionsSettingsView: View {
|
||||
@Environment(Theme.self) private var theme
|
||||
@EnvironmentObject private var userPreferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var userPreferences
|
||||
|
||||
var body: some View {
|
||||
@Bindable var userPreferences = userPreferences
|
||||
Form {
|
||||
Section {
|
||||
Label("settings.swipeactions.status.leading", systemImage: "arrow.right")
|
||||
|
|
|
@ -2,26 +2,19 @@ import DesignSystem
|
|||
import Env
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct TranslationSettingsView: View {
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Theme.self) private var theme
|
||||
|
||||
@State private var apiKey: String = ""
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Toggle(isOn: preferences.$alwaysUseDeepl) {
|
||||
Text("settings.translation.always-deepl")
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
|
||||
deepLToggle
|
||||
if preferences.alwaysUseDeepl {
|
||||
Section("settings.translation.user-api-key") {
|
||||
Picker("settings.translation.api-key-type", selection: $preferences.userDeeplAPIFree) {
|
||||
Text("DeepL API Free").tag(true)
|
||||
Text("DeepL API Pro").tag(false)
|
||||
}
|
||||
|
||||
deepLPicker
|
||||
SecureField("settings.translation.user-api-key", text: $apiKey)
|
||||
.textContentType(.password)
|
||||
}
|
||||
|
@ -40,14 +33,7 @@ struct TranslationSettingsView: View {
|
|||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
Toggle(isOn: preferences.$autoDetectPostLanguage) {
|
||||
Text("settings.translation.auto-detect-post-language")
|
||||
}
|
||||
} footer: {
|
||||
Text("settings.translation.auto-detect-post-language-footer")
|
||||
}
|
||||
autoDetectSection
|
||||
}
|
||||
.navigationTitle("settings.translation.navigation-title")
|
||||
.scrollContentBackground(.hidden)
|
||||
|
@ -57,6 +43,36 @@ struct TranslationSettingsView: View {
|
|||
}
|
||||
.onAppear(perform: updatePrefs)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var deepLToggle: some View {
|
||||
@Bindable var preferences = preferences
|
||||
Toggle(isOn: $preferences.alwaysUseDeepl) {
|
||||
Text("settings.translation.always-deepl")
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var deepLPicker: some View {
|
||||
@Bindable var preferences = preferences
|
||||
Picker("settings.translation.api-key-type", selection: $preferences.userDeeplAPIFree) {
|
||||
Text("DeepL API Free").tag(true)
|
||||
Text("DeepL API Pro").tag(false)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var autoDetectSection: some View {
|
||||
@Bindable var preferences = preferences
|
||||
Section {
|
||||
Toggle(isOn: $preferences.autoDetectPostLanguage) {
|
||||
Text("settings.translation.auto-detect-post-language")
|
||||
}
|
||||
} footer: {
|
||||
Text("settings.translation.auto-detect-post-language-footer")
|
||||
}
|
||||
}
|
||||
|
||||
private func writeNewValue() {
|
||||
writeNewValue(value: apiKey)
|
||||
|
@ -82,6 +98,6 @@ struct TranslationSettingsView: View {
|
|||
struct TranslationSettingsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
TranslationSettingsView()
|
||||
.environmentObject(UserPreferences.shared)
|
||||
.environment(UserPreferences.shared)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,11 @@ import NukeUI
|
|||
import Shimmer
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct AddRemoteTimelineView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Theme.self) private var theme
|
||||
|
||||
@State private var instanceName: String = ""
|
||||
|
|
|
@ -7,10 +7,11 @@ import NukeUI
|
|||
import Shimmer
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct EditTagGroupView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Theme.self) private var theme
|
||||
|
||||
@State private var title: String = ""
|
||||
|
|
|
@ -7,11 +7,12 @@ import Network
|
|||
import SwiftUI
|
||||
import Timeline
|
||||
|
||||
@MainActor
|
||||
struct TimelineTab: View {
|
||||
@Environment(AppAccountsManager.self) private var appAccount
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Client.self) private var client
|
||||
@State private var routerPath = RouterPath()
|
||||
@Binding var popToRootTab: Tab
|
||||
|
|
|
@ -27,7 +27,7 @@ class ShareViewController: UIViewController {
|
|||
if let item = extensionContext?.inputItems.first as? NSExtensionItem {
|
||||
if let attachments = item.attachments {
|
||||
let view = StatusEditorView(mode: .shareExtension(items: attachments))
|
||||
.environmentObject(UserPreferences.shared)
|
||||
.environment(UserPreferences.shared)
|
||||
.environment(appAccountsManager)
|
||||
.environment(client)
|
||||
.environment(account)
|
||||
|
|
|
@ -6,7 +6,7 @@ public struct AccountDetailContextMenu: View {
|
|||
@Environment(Client.self) private var client
|
||||
@Environment(RouterPath.self) private var routerPath
|
||||
@Environment(CurrentInstance.self) private var currentInstance
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
|
||||
var viewModel: AccountDetailViewModel
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import Shimmer
|
|||
import Status
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct AccountDetailView: View {
|
||||
@Environment(\.openURL) private var openURL
|
||||
@Environment(\.redactionReasons) private var reasons
|
||||
|
@ -14,7 +15,7 @@ public struct AccountDetailView: View {
|
|||
@Environment(StreamWatcher.self) private var watcher
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@Environment(CurrentInstance.self) private var currentInstance
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(Client.self) private var client
|
||||
@Environment(RouterPath.self) private var routerPath
|
||||
|
|
|
@ -4,6 +4,7 @@ import Models
|
|||
import Network
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct FiltersListView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@ import EmojiText
|
|||
import Env
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct AppAccountView: View {
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(RouterPath.self) private var routerPath
|
||||
@Environment(AppAccountsManager.self) private var appAccounts
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
|
||||
@State var viewModel: AppAccountViewModel
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@ import DesignSystem
|
|||
import Env
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct AppAccountsSelectorView: View {
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@Environment(AppAccountsManager.self) private var appAccounts
|
||||
@Environment(Theme.self) private var theme
|
||||
|
|
|
@ -5,8 +5,9 @@ import Network
|
|||
import Shimmer
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct ConversationsListView: View {
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(RouterPath.self) private var routerPath
|
||||
@Environment(StreamWatcher.self) private var watcher
|
||||
@Environment(Client.self) private var client
|
||||
|
|
|
@ -55,7 +55,7 @@ public struct StatusEditorToolbarItem: ToolbarContent {
|
|||
@MainActor
|
||||
public struct SecondaryColumnToolbarItem: ToolbarContent {
|
||||
@Environment(\.isSecondaryColumn) private var isSecondaryColumn
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
|
||||
public init() {}
|
||||
|
||||
|
|
|
@ -5,63 +5,250 @@ import Network
|
|||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public class UserPreferences: ObservableObject {
|
||||
@Observable public class UserPreferences {
|
||||
class Storage {
|
||||
@AppStorage("remote_local_timeline") public var remoteLocalTimelines: [String] = []
|
||||
@AppStorage("tag_groups") public var tagGroups: [TagGroup] = []
|
||||
@AppStorage("preferred_browser") public var preferredBrowser: PreferredBrowser = .inAppSafari
|
||||
@AppStorage("draft_posts") public var draftsPosts: [String] = []
|
||||
@AppStorage("show_translate_button_inline") public var showTranslateButton: Bool = true
|
||||
@AppStorage("is_open_ai_enabled") public var isOpenAIEnabled: Bool = true
|
||||
|
||||
@AppStorage("recently_used_languages") public var recentlyUsedLanguages: [String] = []
|
||||
@AppStorage("social_keyboard_composer") public var isSocialKeyboardEnabled: Bool = true
|
||||
|
||||
@AppStorage("use_instance_content_settings") public var useInstanceContentSettings: Bool = true
|
||||
@AppStorage("app_auto_expand_spoilers") public var appAutoExpandSpoilers = false
|
||||
@AppStorage("app_auto_expand_media") public var appAutoExpandMedia: ServerPreferences.AutoExpandMedia = .hideSensitive
|
||||
@AppStorage("app_default_post_visibility") public var appDefaultPostVisibility: Models.Visibility = .pub
|
||||
@AppStorage("app_default_reply_visibility") public var appDefaultReplyVisibility: Models.Visibility = .pub
|
||||
@AppStorage("app_default_posts_sensitive") public var appDefaultPostsSensitive = false
|
||||
@AppStorage("autoplay_video") public var autoPlayVideo = true
|
||||
@AppStorage("always_use_deepl") public var alwaysUseDeepl = false
|
||||
@AppStorage("user_deepl_api_free") public var userDeeplAPIFree = true
|
||||
@AppStorage("auto_detect_post_language") public var autoDetectPostLanguage = true
|
||||
|
||||
@AppStorage("suppress_dupe_reblogs") public var suppressDupeReblogs: Bool = false
|
||||
|
||||
@AppStorage("inAppBrowserReaderView") public var inAppBrowserReaderView = false
|
||||
|
||||
@AppStorage("haptic_tab") public var hapticTabSelectionEnabled = true
|
||||
@AppStorage("haptic_timeline") public var hapticTimelineEnabled = true
|
||||
@AppStorage("haptic_button_press") public var hapticButtonPressEnabled = true
|
||||
@AppStorage("sound_effect_enabled") public var soundEffectEnabled = true
|
||||
|
||||
@AppStorage("show_tab_label_iphone") public var showiPhoneTabLabel = true
|
||||
@AppStorage("show_alt_text_for_media") public var showAltTextForMedia = true
|
||||
|
||||
@AppStorage("show_second_column_ipad") public var showiPadSecondaryColumn = true
|
||||
|
||||
@AppStorage("swipeactions-status-trailing-right") public var swipeActionsStatusTrailingRight = StatusAction.favorite
|
||||
@AppStorage("swipeactions-status-trailing-left") public var swipeActionsStatusTrailingLeft = StatusAction.boost
|
||||
@AppStorage("swipeactions-status-leading-left") public var swipeActionsStatusLeadingLeft = StatusAction.reply
|
||||
@AppStorage("swipeactions-status-leading-right") public var swipeActionsStatusLeadingRight = StatusAction.none
|
||||
@AppStorage("swipeactions-use-theme-color") public var swipeActionsUseThemeColor = false
|
||||
@AppStorage("swipeactions-icon-style") public var swipeActionsIconStyle: SwipeActionsIconStyle = .iconWithText
|
||||
|
||||
@AppStorage("requested_review") public var requestedReview = false
|
||||
|
||||
@AppStorage("collapse-long-posts") public var collapseLongPosts = true
|
||||
|
||||
@AppStorage("share-button-behavior") public var shareButtonBehavior: PreferredShareButtonBehavior = .linkAndText
|
||||
|
||||
init() { }
|
||||
}
|
||||
|
||||
public static let sharedDefault = UserDefaults(suiteName: "group.com.thomasricouard.IceCubesApp")
|
||||
public static let shared = UserPreferences()
|
||||
|
||||
private let storage = Storage()
|
||||
|
||||
private var client: Client?
|
||||
|
||||
@AppStorage("remote_local_timeline") public var remoteLocalTimelines: [String] = []
|
||||
@AppStorage("tag_groups") public var tagGroups: [TagGroup] = []
|
||||
@AppStorage("preferred_browser") public var preferredBrowser: PreferredBrowser = .inAppSafari
|
||||
@AppStorage("draft_posts") public var draftsPosts: [String] = []
|
||||
@AppStorage("show_translate_button_inline") public var showTranslateButton: Bool = true
|
||||
@AppStorage("is_open_ai_enabled") public var isOpenAIEnabled: Bool = true
|
||||
|
||||
@AppStorage("recently_used_languages") public var recentlyUsedLanguages: [String] = []
|
||||
@AppStorage("social_keyboard_composer") public var isSocialKeyboardEnabled: Bool = true
|
||||
|
||||
@AppStorage("use_instance_content_settings") public var useInstanceContentSettings: Bool = true
|
||||
@AppStorage("app_auto_expand_spoilers") public var appAutoExpandSpoilers = false
|
||||
@AppStorage("app_auto_expand_media") public var appAutoExpandMedia: ServerPreferences.AutoExpandMedia = .hideSensitive
|
||||
@AppStorage("app_default_post_visibility") public var appDefaultPostVisibility: Models.Visibility = .pub
|
||||
@AppStorage("app_default_reply_visibility") public var appDefaultReplyVisibility: Models.Visibility = .pub
|
||||
@AppStorage("app_default_posts_sensitive") public var appDefaultPostsSensitive = false
|
||||
@AppStorage("autoplay_video") public var autoPlayVideo = true
|
||||
@AppStorage("always_use_deepl") public var alwaysUseDeepl = false
|
||||
@AppStorage("user_deepl_api_free") public var userDeeplAPIFree = true
|
||||
@AppStorage("auto_detect_post_language") public var autoDetectPostLanguage = true
|
||||
|
||||
@AppStorage("suppress_dupe_reblogs") public var suppressDupeReblogs: Bool = false
|
||||
|
||||
@AppStorage("inAppBrowserReaderView") public var inAppBrowserReaderView = false
|
||||
|
||||
@AppStorage("haptic_tab") public var hapticTabSelectionEnabled = true
|
||||
@AppStorage("haptic_timeline") public var hapticTimelineEnabled = true
|
||||
@AppStorage("haptic_button_press") public var hapticButtonPressEnabled = true
|
||||
@AppStorage("sound_effect_enabled") public var soundEffectEnabled = true
|
||||
|
||||
@AppStorage("show_tab_label_iphone") public var showiPhoneTabLabel = true
|
||||
@AppStorage("show_alt_text_for_media") public var showAltTextForMedia = true
|
||||
|
||||
@AppStorage("show_second_column_ipad") public var showiPadSecondaryColumn = true
|
||||
|
||||
@AppStorage("swipeactions-status-trailing-right") public var swipeActionsStatusTrailingRight = StatusAction.favorite
|
||||
@AppStorage("swipeactions-status-trailing-left") public var swipeActionsStatusTrailingLeft = StatusAction.boost
|
||||
@AppStorage("swipeactions-status-leading-left") public var swipeActionsStatusLeadingLeft = StatusAction.reply
|
||||
@AppStorage("swipeactions-status-leading-right") public var swipeActionsStatusLeadingRight = StatusAction.none
|
||||
@AppStorage("swipeactions-use-theme-color") public var swipeActionsUseThemeColor = false
|
||||
@AppStorage("swipeactions-icon-style") public var swipeActionsIconStyle: SwipeActionsIconStyle = .iconWithText
|
||||
|
||||
@AppStorage("requested_review") public var requestedReview = false
|
||||
|
||||
@AppStorage("collapse-long-posts") public var collapseLongPosts = true
|
||||
|
||||
@AppStorage("share-button-behavior") public var shareButtonBehavior: PreferredShareButtonBehavior = .linkAndText
|
||||
|
||||
|
||||
public var remoteLocalTimelines: [String] {
|
||||
didSet {
|
||||
storage.remoteLocalTimelines = remoteLocalTimelines
|
||||
}
|
||||
}
|
||||
public var tagGroups: [TagGroup] {
|
||||
didSet {
|
||||
storage.tagGroups = tagGroups
|
||||
}
|
||||
}
|
||||
public var preferredBrowser: PreferredBrowser {
|
||||
didSet {
|
||||
storage.preferredBrowser = preferredBrowser
|
||||
}
|
||||
}
|
||||
public var draftsPosts: [String] {
|
||||
didSet {
|
||||
storage.draftsPosts = draftsPosts
|
||||
}
|
||||
}
|
||||
public var showTranslateButton: Bool {
|
||||
didSet {
|
||||
storage.showTranslateButton = showTranslateButton
|
||||
}
|
||||
}
|
||||
public var isOpenAIEnabled: Bool {
|
||||
didSet {
|
||||
storage.isOpenAIEnabled = isOpenAIEnabled
|
||||
}
|
||||
}
|
||||
public var recentlyUsedLanguages: [String] {
|
||||
didSet {
|
||||
storage.recentlyUsedLanguages = recentlyUsedLanguages
|
||||
}
|
||||
}
|
||||
public var isSocialKeyboardEnabled: Bool {
|
||||
didSet {
|
||||
storage.isSocialKeyboardEnabled = isSocialKeyboardEnabled
|
||||
}
|
||||
}
|
||||
public var useInstanceContentSettings: Bool {
|
||||
didSet {
|
||||
storage.useInstanceContentSettings = useInstanceContentSettings
|
||||
}
|
||||
}
|
||||
public var appAutoExpandSpoilers: Bool {
|
||||
didSet {
|
||||
storage.appAutoExpandSpoilers = appAutoExpandSpoilers
|
||||
}
|
||||
}
|
||||
public var appAutoExpandMedia: ServerPreferences.AutoExpandMedia {
|
||||
didSet {
|
||||
storage.appAutoExpandMedia = appAutoExpandMedia
|
||||
}
|
||||
}
|
||||
public var appDefaultPostVisibility: Models.Visibility {
|
||||
didSet {
|
||||
storage.appDefaultPostVisibility = appDefaultPostVisibility
|
||||
}
|
||||
}
|
||||
public var appDefaultReplyVisibility: Models.Visibility {
|
||||
didSet {
|
||||
storage.appDefaultReplyVisibility = appDefaultReplyVisibility
|
||||
}
|
||||
}
|
||||
public var appDefaultPostsSensitive: Bool {
|
||||
didSet {
|
||||
storage.appDefaultPostsSensitive = appDefaultPostsSensitive
|
||||
}
|
||||
}
|
||||
public var autoPlayVideo: Bool {
|
||||
didSet {
|
||||
storage.autoPlayVideo = autoPlayVideo
|
||||
}
|
||||
}
|
||||
public var alwaysUseDeepl: Bool {
|
||||
didSet {
|
||||
storage.alwaysUseDeepl = alwaysUseDeepl
|
||||
}
|
||||
}
|
||||
public var userDeeplAPIFree: Bool {
|
||||
didSet {
|
||||
storage.userDeeplAPIFree = userDeeplAPIFree
|
||||
}
|
||||
}
|
||||
public var autoDetectPostLanguage: Bool {
|
||||
didSet {
|
||||
storage.autoDetectPostLanguage = autoDetectPostLanguage
|
||||
}
|
||||
}
|
||||
public var suppressDupeReblogs: Bool {
|
||||
didSet {
|
||||
storage.suppressDupeReblogs = suppressDupeReblogs
|
||||
}
|
||||
}
|
||||
public var inAppBrowserReaderView: Bool {
|
||||
didSet {
|
||||
storage.inAppBrowserReaderView = inAppBrowserReaderView
|
||||
}
|
||||
}
|
||||
public var hapticTabSelectionEnabled: Bool {
|
||||
didSet {
|
||||
storage.hapticTabSelectionEnabled = hapticTabSelectionEnabled
|
||||
}
|
||||
}
|
||||
public var hapticTimelineEnabled: Bool {
|
||||
didSet {
|
||||
storage.hapticTimelineEnabled = hapticTimelineEnabled
|
||||
}
|
||||
}
|
||||
public var hapticButtonPressEnabled: Bool {
|
||||
didSet {
|
||||
storage.hapticButtonPressEnabled = hapticButtonPressEnabled
|
||||
}
|
||||
}
|
||||
public var soundEffectEnabled: Bool {
|
||||
didSet {
|
||||
storage.soundEffectEnabled = soundEffectEnabled
|
||||
}
|
||||
}
|
||||
public var showiPhoneTabLabel: Bool {
|
||||
didSet {
|
||||
storage.showiPhoneTabLabel = showiPhoneTabLabel
|
||||
}
|
||||
}
|
||||
public var showAltTextForMedia: Bool {
|
||||
didSet {
|
||||
storage.showAltTextForMedia = showAltTextForMedia
|
||||
}
|
||||
}
|
||||
public var showiPadSecondaryColumn: Bool {
|
||||
didSet {
|
||||
storage.showiPadSecondaryColumn = showiPadSecondaryColumn
|
||||
}
|
||||
}
|
||||
public var swipeActionsStatusTrailingRight: StatusAction {
|
||||
didSet {
|
||||
storage.swipeActionsStatusTrailingRight = swipeActionsStatusTrailingRight
|
||||
}
|
||||
}
|
||||
public var swipeActionsStatusTrailingLeft: StatusAction {
|
||||
didSet {
|
||||
storage.swipeActionsStatusTrailingLeft = swipeActionsStatusTrailingLeft
|
||||
}
|
||||
}
|
||||
public var swipeActionsStatusLeadingLeft: StatusAction {
|
||||
didSet {
|
||||
storage.swipeActionsStatusLeadingLeft = swipeActionsStatusLeadingLeft
|
||||
}
|
||||
}
|
||||
public var swipeActionsStatusLeadingRight: StatusAction {
|
||||
didSet {
|
||||
storage.swipeActionsStatusLeadingRight = swipeActionsStatusLeadingRight
|
||||
}
|
||||
}
|
||||
public var swipeActionsUseThemeColor: Bool {
|
||||
didSet {
|
||||
storage.swipeActionsUseThemeColor = swipeActionsUseThemeColor
|
||||
}
|
||||
}
|
||||
public var swipeActionsIconStyle: SwipeActionsIconStyle {
|
||||
didSet {
|
||||
storage.swipeActionsIconStyle = swipeActionsIconStyle
|
||||
}
|
||||
}
|
||||
public var requestedReview: Bool {
|
||||
didSet {
|
||||
storage.requestedReview = requestedReview
|
||||
}
|
||||
}
|
||||
public var collapseLongPosts: Bool {
|
||||
didSet {
|
||||
storage.collapseLongPosts = collapseLongPosts
|
||||
}
|
||||
}
|
||||
public var shareButtonBehavior: PreferredShareButtonBehavior {
|
||||
didSet {
|
||||
storage.shareButtonBehavior = shareButtonBehavior
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum SwipeActionsIconStyle: String, CaseIterable {
|
||||
case iconWithText, iconOnly
|
||||
|
||||
|
||||
public var description: LocalizedStringKey {
|
||||
switch self {
|
||||
case .iconWithText:
|
||||
|
@ -70,7 +257,7 @@ public class UserPreferences: ObservableObject {
|
|||
"enum.swipeactions.icon-only"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Have to implement this manually here due to compiler not implicitly
|
||||
// inserting `nonisolated`, which leads to a warning:
|
||||
//
|
||||
|
@ -81,7 +268,7 @@ public class UserPreferences: ObservableObject {
|
|||
[.iconWithText, .iconOnly]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var postVisibility: Models.Visibility {
|
||||
if useInstanceContentSettings {
|
||||
serverPreferences?.postVisibility ?? .pub
|
||||
|
@ -89,26 +276,26 @@ public class UserPreferences: ObservableObject {
|
|||
appDefaultPostVisibility
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func conformReplyVisibilityConstraints() {
|
||||
appDefaultReplyVisibility = getReplyVisibility()
|
||||
}
|
||||
|
||||
|
||||
private func getReplyVisibility() -> Models.Visibility {
|
||||
getMinVisibility(postVisibility, appDefaultReplyVisibility)
|
||||
}
|
||||
|
||||
|
||||
public func getReplyVisibility(of status: Status) -> Models.Visibility {
|
||||
getMinVisibility(getReplyVisibility(), status.visibility)
|
||||
}
|
||||
|
||||
|
||||
private func getMinVisibility(_ vis1: Models.Visibility, _ vis2: Models.Visibility) -> Models.Visibility {
|
||||
let no1 = Self.getIntOfVisibility(vis1)
|
||||
let no2 = Self.getIntOfVisibility(vis2)
|
||||
|
||||
|
||||
return no1 < no2 ? vis1 : vis2
|
||||
}
|
||||
|
||||
|
||||
public var postIsSensitive: Bool {
|
||||
if useInstanceContentSettings {
|
||||
serverPreferences?.postIsSensitive ?? false
|
||||
|
@ -116,7 +303,7 @@ public class UserPreferences: ObservableObject {
|
|||
appDefaultPostsSensitive
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var autoExpandSpoilers: Bool {
|
||||
if useInstanceContentSettings {
|
||||
serverPreferences?.autoExpandSpoilers ?? true
|
||||
|
@ -124,7 +311,7 @@ public class UserPreferences: ObservableObject {
|
|||
appAutoExpandSpoilers
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var autoExpandMedia: ServerPreferences.AutoExpandMedia {
|
||||
if useInstanceContentSettings {
|
||||
serverPreferences?.autoExpandMedia ?? .hideSensitive
|
||||
|
@ -132,8 +319,8 @@ public class UserPreferences: ObservableObject {
|
|||
appAutoExpandMedia
|
||||
}
|
||||
}
|
||||
|
||||
@Published public var notificationsCount: [OauthToken: Int] = [:] {
|
||||
|
||||
public var notificationsCount: [OauthToken: Int] = [:] {
|
||||
didSet {
|
||||
for (key, value) in notificationsCount {
|
||||
Self.sharedDefault?.set(value, forKey: "push_notifications_count_\(key.createdAt)")
|
||||
|
@ -152,22 +339,20 @@ public class UserPreferences: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
@Published public var serverPreferences: ServerPreferences?
|
||||
|
||||
private init() {}
|
||||
|
||||
public var serverPreferences: ServerPreferences?
|
||||
|
||||
public func setClient(client: Client) {
|
||||
self.client = client
|
||||
Task {
|
||||
await refreshServerPreferences()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func refreshServerPreferences() async {
|
||||
guard let client, client.isAuth else { return }
|
||||
serverPreferences = try? await client.get(endpoint: Accounts.preferences)
|
||||
}
|
||||
|
||||
|
||||
public func markLanguageAsSelected(isoCode: String) {
|
||||
var copy = recentlyUsedLanguages
|
||||
if let index = copy.firstIndex(of: isoCode) {
|
||||
|
@ -176,7 +361,7 @@ public class UserPreferences: ObservableObject {
|
|||
copy.insert(isoCode, at: 0)
|
||||
recentlyUsedLanguages = Array(copy.prefix(3))
|
||||
}
|
||||
|
||||
|
||||
public static func getIntOfVisibility(_ vis: Models.Visibility) -> Int {
|
||||
switch vis {
|
||||
case .direct:
|
||||
|
@ -189,4 +374,43 @@ public class UserPreferences: ObservableObject {
|
|||
3
|
||||
}
|
||||
}
|
||||
|
||||
private init() {
|
||||
remoteLocalTimelines = storage.remoteLocalTimelines
|
||||
tagGroups = storage.tagGroups
|
||||
preferredBrowser = storage.preferredBrowser
|
||||
draftsPosts = storage.draftsPosts
|
||||
showTranslateButton = storage.showTranslateButton
|
||||
isOpenAIEnabled = storage.isOpenAIEnabled
|
||||
recentlyUsedLanguages = storage.recentlyUsedLanguages
|
||||
isSocialKeyboardEnabled = storage.isSocialKeyboardEnabled
|
||||
useInstanceContentSettings = storage.useInstanceContentSettings
|
||||
appAutoExpandSpoilers = storage.appAutoExpandSpoilers
|
||||
appAutoExpandMedia = storage.appAutoExpandMedia
|
||||
appDefaultPostVisibility = storage.appDefaultPostVisibility
|
||||
appDefaultReplyVisibility = storage.appDefaultReplyVisibility
|
||||
appDefaultPostsSensitive = storage.appDefaultPostsSensitive
|
||||
autoPlayVideo = storage.autoPlayVideo
|
||||
alwaysUseDeepl = storage.alwaysUseDeepl
|
||||
userDeeplAPIFree = storage.userDeeplAPIFree
|
||||
autoDetectPostLanguage = storage.autoDetectPostLanguage
|
||||
suppressDupeReblogs = storage.suppressDupeReblogs
|
||||
inAppBrowserReaderView = storage.inAppBrowserReaderView
|
||||
hapticTabSelectionEnabled = storage.hapticTabSelectionEnabled
|
||||
hapticTimelineEnabled = storage.hapticTimelineEnabled
|
||||
hapticButtonPressEnabled = storage.hapticButtonPressEnabled
|
||||
soundEffectEnabled = storage.soundEffectEnabled
|
||||
showiPhoneTabLabel = storage.showiPhoneTabLabel
|
||||
showAltTextForMedia = storage.showAltTextForMedia
|
||||
showiPadSecondaryColumn = storage.showiPadSecondaryColumn
|
||||
swipeActionsStatusTrailingRight = storage.swipeActionsStatusTrailingRight
|
||||
swipeActionsStatusTrailingLeft = storage.swipeActionsStatusTrailingLeft
|
||||
swipeActionsStatusLeadingLeft = storage.swipeActionsStatusLeadingLeft
|
||||
swipeActionsStatusLeadingRight = storage.swipeActionsStatusLeadingRight
|
||||
swipeActionsUseThemeColor = storage.swipeActionsUseThemeColor
|
||||
swipeActionsIconStyle = storage.swipeActionsIconStyle
|
||||
requestedReview = storage.requestedReview
|
||||
collapseLongPosts = storage.collapseLongPosts
|
||||
shareButtonBehavior = storage.shareButtonBehavior
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ import NukeUI
|
|||
import PhotosUI
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct StatusEditorAccessoryView: View {
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(CurrentInstance.self) private var currentInstance
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
|
|
@ -14,7 +14,7 @@ import UIKit
|
|||
@MainActor
|
||||
public struct StatusEditorView: View {
|
||||
@Environment(AppAccountsManager.self) private var appAccounts
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(Client.self) private var client
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
|
|
|
@ -51,7 +51,7 @@ import SwiftUI
|
|||
struct VideoPlayerView: View {
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
@Environment(\.isCompact) private var isCompact
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(Theme.self) private var theme
|
||||
|
||||
@State var viewModel: VideoPlayerViewModel
|
||||
|
|
|
@ -4,11 +4,12 @@ import Models
|
|||
import Network
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct StatusRowActionsView: View {
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@Environment(StatusDataController.self) private var statusDataController
|
||||
@EnvironmentObject private var userPreferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var userPreferences
|
||||
|
||||
@Environment(\.isStatusFocused) private var isFocused
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ struct StatusRowContextMenu: View {
|
|||
|
||||
@Environment(Client.self) private var client
|
||||
@Environment(SceneDelegate.self) private var sceneDelegate
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(CurrentAccount.self) private var account
|
||||
@Environment(CurrentInstance.self) private var currentInstance
|
||||
@Environment(StatusDataController.self) private var statusDataController
|
||||
|
@ -87,7 +87,7 @@ struct StatusRowContextMenu: View {
|
|||
}
|
||||
.environment(\.isInCaptureMode, true)
|
||||
.environment(Theme.shared)
|
||||
.environmentObject(preferences)
|
||||
.environment(preferences)
|
||||
.environment(account)
|
||||
.environment(currentInstance)
|
||||
.environment(SceneDelegate())
|
||||
|
|
|
@ -5,6 +5,7 @@ import Nuke
|
|||
import NukeUI
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct StatusRowMediaPreviewView: View {
|
||||
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
|
||||
@Environment(\.extraLeadingInset) private var extraLeadingInset: CGFloat
|
||||
|
@ -12,7 +13,7 @@ public struct StatusRowMediaPreviewView: View {
|
|||
@Environment(\.isCompact) private var isCompact: Bool
|
||||
|
||||
@Environment(SceneDelegate.self) private var sceneDelegate
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(QuickLook.self) private var quickLook
|
||||
@Environment(Theme.self) private var theme
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@ import Env
|
|||
import Models
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct StatusRowSwipeView: View {
|
||||
@Environment(Theme.self) private var theme
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@Environment(StatusDataController.self) private var statusDataController
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@ import Env
|
|||
import Models
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct StatusRowTranslateView: View {
|
||||
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
|
||||
@Environment(\.isCompact) private var isCompact: Bool
|
||||
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@Environment(UserPreferences.self) private var preferences
|
||||
|
||||
var viewModel: StatusRowViewModel
|
||||
|
||||
|
|
Loading…
Reference in a new issue