Convert Theme to Observable

This commit is contained in:
Thomas Ricouard 2023-09-18 21:03:52 +02:00
parent 625b7f8137
commit f9c0355f1d
78 changed files with 356 additions and 148 deletions

View file

@ -115,7 +115,7 @@ extension View {
environment(CurrentAccount.shared) environment(CurrentAccount.shared)
.environmentObject(UserPreferences.shared) .environmentObject(UserPreferences.shared)
.environment(CurrentInstance.shared) .environment(CurrentInstance.shared)
.environmentObject(Theme.shared) .environment(Theme.shared)
.environment(AppAccountsManager.shared) .environment(AppAccountsManager.shared)
.environment(PushNotificationsService.shared) .environment(PushNotificationsService.shared)
.environment(AppAccountsManager.shared.currentClient) .environment(AppAccountsManager.shared.currentClient)

View file

@ -22,7 +22,7 @@ struct IceCubesApp: App {
@State private var pushNotificationsService = PushNotificationsService.shared @State private var pushNotificationsService = PushNotificationsService.shared
@State private var watcher = StreamWatcher() @State private var watcher = StreamWatcher()
@State private var quickLook = QuickLook() @State private var quickLook = QuickLook()
@StateObject private var theme = Theme.shared @State private var theme = Theme.shared
@State private var sidebarRouterPath = RouterPath() @State private var sidebarRouterPath = RouterPath()
@State private var selectedTab: Tab = .timeline @State private var selectedTab: Tab = .timeline
@ -49,7 +49,7 @@ struct IceCubesApp: App {
.environment(currentAccount) .environment(currentAccount)
.environment(currentInstance) .environment(currentInstance)
.environmentObject(userPreferences) .environmentObject(userPreferences)
.environmentObject(theme) .environment(theme)
.environment(watcher) .environment(watcher)
.environment(pushNotificationsService) .environment(pushNotificationsService)
.environment(\.isSupporter, isSupporter) .environment(\.isSupporter, isSupporter)

View file

@ -8,7 +8,7 @@ import SwiftUI
public struct ReportView: View { public struct ReportView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
let status: Status let status: Status

View file

@ -12,7 +12,7 @@ extension View {
@MainActor @MainActor
private struct SafariRouter: ViewModifier { private struct SafariRouter: ViewModifier {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath

View file

@ -8,7 +8,7 @@ import SwiftUI
struct SideBarView<Content: View>: View { struct SideBarView<Content: View>: View {
@Environment(AppAccountsManager.self) private var appAccounts @Environment(AppAccountsManager.self) private var appAccounts
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(StreamWatcher.self) private var watcher @Environment(StreamWatcher.self) private var watcher
@EnvironmentObject private var userPreferences: UserPreferences @EnvironmentObject private var userPreferences: UserPreferences
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@ -155,7 +155,7 @@ struct SideBarView<Content: View>: View {
} }
private struct SideBarIcon: View { private struct SideBarIcon: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
let systemIconName: String let systemIconName: String
let isSelected: Bool let isSelected: Bool

View file

@ -8,7 +8,7 @@ import Shimmer
import SwiftUI import SwiftUI
struct ExploreTab: View { struct ExploreTab: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(Client.self) private var client @Environment(Client.self) private var client

View file

@ -8,8 +8,9 @@ import Network
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
struct MessagesTab: View { struct MessagesTab: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(StreamWatcher.self) private var watcher @Environment(StreamWatcher.self) private var watcher
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount

View file

@ -11,7 +11,7 @@ struct NotificationsTab: View {
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool @Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(StreamWatcher.self) private var watcher @Environment(StreamWatcher.self) private var watcher
@Environment(AppAccountsManager.self) private var appAccount @Environment(AppAccountsManager.self) private var appAccount

View file

@ -8,9 +8,10 @@ import Network
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
struct ProfileTab: View { struct ProfileTab: View {
@Environment(AppAccountsManager.self) private var appAccount @Environment(AppAccountsManager.self) private var appAccount
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@State private var routerPath = RouterPath() @State private var routerPath = RouterPath()

View file

@ -2,9 +2,10 @@ import DesignSystem
import Env import Env
import SwiftUI import SwiftUI
@MainActor
struct AboutView: View { struct AboutView: View {
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
let versionNumber: String let versionNumber: String
@ -101,6 +102,6 @@ struct AboutView: View {
struct AboutView_Previews: PreviewProvider { struct AboutView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
AboutView() AboutView()
.environmentObject(Theme.shared) .environment(Theme.shared)
} }
} }

View file

@ -14,7 +14,7 @@ struct AccountSettingsView: View {
@Environment(PushNotificationsService.self) private var pushNotifications @Environment(PushNotificationsService.self) private var pushNotifications
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(AppAccountsManager.self) private var appAccountsManager @Environment(AppAccountsManager.self) private var appAccountsManager
@Environment(Client.self) private var client @Environment(Client.self) private var client

View file

@ -9,6 +9,7 @@ import SafariServices
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
struct AddAccountView: View { struct AddAccountView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@ -17,7 +18,7 @@ struct AddAccountView: View {
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
@Environment(PushNotificationsService.self) private var pushNotifications @Environment(PushNotificationsService.self) private var pushNotifications
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var instanceName: String = "" @State private var instanceName: String = ""
@State private var instance: Instance? @State private var instance: Instance?

View file

@ -9,7 +9,7 @@ import UserNotifications
struct ContentSettingsView: View { struct ContentSettingsView: View {
@EnvironmentObject private var userPreferences: UserPreferences @EnvironmentObject private var userPreferences: UserPreferences
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
var body: some View { var body: some View {
Form { Form {

View file

@ -15,15 +15,14 @@ import SwiftUI
var lineSpacing = Theme.shared.lineSpacing var lineSpacing = Theme.shared.lineSpacing
var fontSizeScale = Theme.shared.fontSizeScale var fontSizeScale = Theme.shared.fontSizeScale
init() {}
init() { }
} }
struct DisplaySettingsView: View { struct DisplaySettingsView: View {
typealias FontState = Theme.FontState typealias FontState = Theme.FontState
@Environment(\.colorScheme) private var colorScheme @Environment(\.colorScheme) private var colorScheme
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@EnvironmentObject private var userPreferences: UserPreferences @EnvironmentObject private var userPreferences: UserPreferences
@State private var localValues = DisplaySettingsLocalValues() @State private var localValues = DisplaySettingsLocalValues()
@ -51,27 +50,27 @@ struct DisplaySettingsView: View {
.scrollContentBackground(.hidden) .scrollContentBackground(.hidden)
.background(theme.secondaryBackgroundColor) .background(theme.secondaryBackgroundColor)
.task(id: localValues.tintColor) { .task(id: localValues.tintColor) {
do { try await Task.sleep(for: .microseconds(500)) } catch { } do { try await Task.sleep(for: .microseconds(500)) } catch {}
Theme.shared.tintColor = localValues.tintColor Theme.shared.tintColor = localValues.tintColor
} }
.task(id: localValues.primaryBackgroundColor) { .task(id: localValues.primaryBackgroundColor) {
do { try await Task.sleep(for: .microseconds(500)) } catch { } do { try await Task.sleep(for: .microseconds(500)) } catch {}
Theme.shared.primaryBackgroundColor = localValues.primaryBackgroundColor Theme.shared.primaryBackgroundColor = localValues.primaryBackgroundColor
} }
.task(id: localValues.secondaryBackgroundColor) { .task(id: localValues.secondaryBackgroundColor) {
do { try await Task.sleep(for: .microseconds(500)) } catch { } do { try await Task.sleep(for: .microseconds(500)) } catch {}
Theme.shared.secondaryBackgroundColor = localValues.secondaryBackgroundColor Theme.shared.secondaryBackgroundColor = localValues.secondaryBackgroundColor
} }
.task(id: localValues.labelColor) { .task(id: localValues.labelColor) {
do { try await Task.sleep(for: .microseconds(500)) } catch { } do { try await Task.sleep(for: .microseconds(500)) } catch {}
Theme.shared.labelColor = localValues.labelColor Theme.shared.labelColor = localValues.labelColor
} }
.task(id: localValues.lineSpacing) { .task(id: localValues.lineSpacing) {
do { try await Task.sleep(for: .microseconds(500)) } catch { } do { try await Task.sleep(for: .microseconds(500)) } catch {}
Theme.shared.lineSpacing = localValues.lineSpacing Theme.shared.lineSpacing = localValues.lineSpacing
} }
.task(id: localValues.fontSizeScale) { .task(id: localValues.fontSizeScale) {
do { try await Task.sleep(for: .microseconds(500)) } catch { } do { try await Task.sleep(for: .microseconds(500)) } catch {}
Theme.shared.fontSizeScale = localValues.fontSizeScale Theme.shared.fontSizeScale = localValues.fontSizeScale
} }
examplePost examplePost
@ -96,7 +95,9 @@ struct DisplaySettingsView: View {
} }
} }
@ViewBuilder
private var themeSection: some View { private var themeSection: some View {
@Bindable var theme = theme
Section { Section {
Toggle("settings.display.theme.systemColor", isOn: $theme.followSystemColorScheme) Toggle("settings.display.theme.systemColor", isOn: $theme.followSystemColorScheme)
themeSelectorButton themeSelectorButton
@ -176,7 +177,9 @@ struct DisplaySettingsView: View {
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
} }
@ViewBuilder
private var layoutSection: some View { private var layoutSection: some View {
@Bindable var theme = theme
Section("settings.display.section.display") { Section("settings.display.section.display") {
Picker("settings.display.avatar.position", selection: $theme.avatarPosition) { Picker("settings.display.avatar.position", selection: $theme.avatarPosition) {
ForEach(Theme.AvatarPosition.allCases, id: \.rawValue) { position in ForEach(Theme.AvatarPosition.allCases, id: \.rawValue) { position in

View file

@ -5,7 +5,7 @@ import Status
import SwiftUI import SwiftUI
struct HapticSettingsView: View { struct HapticSettingsView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@EnvironmentObject private var userPreferences: UserPreferences @EnvironmentObject private var userPreferences: UserPreferences
var body: some View { var body: some View {

View file

@ -1,6 +1,7 @@
import DesignSystem import DesignSystem
import SwiftUI import SwiftUI
@MainActor
struct IconSelectorView: View { struct IconSelectorView: View {
enum Icon: Int, CaseIterable, Identifiable { enum Icon: Int, CaseIterable, Identifiable {
var id: String { var id: String {
@ -62,7 +63,7 @@ struct IconSelectorView: View {
] ]
} }
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var currentIcon = UIApplication.shared.alternateIconName ?? Icon.primary.appIconName @State private var currentIcon = UIApplication.shared.alternateIconName ?? Icon.primary.appIconName
private let columns = [GridItem(.adaptive(minimum: 125, maximum: 1024))] private let columns = [GridItem(.adaptive(minimum: 125, maximum: 1024))]

View file

@ -4,7 +4,7 @@ import NukeUI
import SwiftUI import SwiftUI
struct InstanceInfoView: View { struct InstanceInfoView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
let instance: Instance let instance: Instance
@ -19,7 +19,7 @@ struct InstanceInfoView: View {
} }
public struct InstanceInfoSection: View { public struct InstanceInfoSection: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
let instance: Instance let instance: Instance

View file

@ -7,8 +7,9 @@ import NukeUI
import SwiftUI import SwiftUI
import UserNotifications import UserNotifications
@MainActor
struct PushNotificationsView: View { struct PushNotificationsView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(AppAccountsManager.self) private var appAccountsManager @Environment(AppAccountsManager.self) private var appAccountsManager
@Environment(PushNotificationsService.self) private var pushNotifications @Environment(PushNotificationsService.self) private var pushNotifications

View file

@ -17,7 +17,7 @@ struct SettingsTabs: View {
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
@Environment(AppAccountsManager.self) private var appAccountsManager @Environment(AppAccountsManager.self) private var appAccountsManager
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var routerPath = RouterPath() @State private var routerPath = RouterPath()
@State private var addAccountSheetPresented = false @State private var addAccountSheetPresented = false

View file

@ -4,6 +4,7 @@ import RevenueCat
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
struct SupportAppView: View { struct SupportAppView: View {
enum Tip: String, CaseIterable { enum Tip: String, CaseIterable {
case one, two, three, four, supporter case one, two, three, four, supporter
@ -47,7 +48,7 @@ struct SupportAppView: View {
} }
} }
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(\.openURL) private var openURL @Environment(\.openURL) private var openURL

View file

@ -3,7 +3,7 @@ import Env
import SwiftUI import SwiftUI
struct SwipeActionsSettingsView: View { struct SwipeActionsSettingsView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@EnvironmentObject private var userPreferences: UserPreferences @EnvironmentObject private var userPreferences: UserPreferences
var body: some View { var body: some View {

View file

@ -4,7 +4,7 @@ import SwiftUI
struct TranslationSettingsView: View { struct TranslationSettingsView: View {
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var apiKey: String = "" @State private var apiKey: String = ""

View file

@ -11,7 +11,7 @@ struct AddRemoteTimelineView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var instanceName: String = "" @State private var instanceName: String = ""
@State private var instance: Instance? @State private var instance: Instance?

View file

@ -11,7 +11,7 @@ struct EditTagGroupView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var title: String = "" @State private var title: String = ""
@State private var sfSymbolName: String = "" @State private var sfSymbolName: String = ""

View file

@ -9,7 +9,7 @@ import Timeline
struct TimelineTab: View { struct TimelineTab: View {
@Environment(AppAccountsManager.self) private var appAccount @Environment(AppAccountsManager.self) private var appAccount
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@Environment(Client.self) private var client @Environment(Client.self) private var client

View file

@ -31,7 +31,7 @@ class ShareViewController: UIViewController {
.environment(appAccountsManager) .environment(appAccountsManager)
.environment(client) .environment(client)
.environment(account) .environment(account)
.environmentObject(theme) .environment(theme)
.environment(instance) .environment(instance)
.tint(theme.tintColor) .tint(theme.tintColor)
.preferredColorScheme(colorScheme == .light ? .light : .dark) .preferredColorScheme(colorScheme == .light ? .light : .dark)

View file

@ -6,12 +6,13 @@ import NukeUI
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
struct AccountDetailHeaderView: View { struct AccountDetailHeaderView: View {
enum Constants { enum Constants {
static let headerHeight: CGFloat = 200 static let headerHeight: CGFloat = 200
} }
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(QuickLook.self) private var quickLook @Environment(QuickLook.self) private var quickLook
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount

View file

@ -15,7 +15,7 @@ public struct AccountDetailView: View {
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath

View file

@ -20,8 +20,9 @@ import SwiftUI
} }
} }
@MainActor
public struct AccountsListRow: View { public struct AccountsListRow: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@Environment(Client.self) private var client @Environment(Client.self) private var client
@ -117,7 +118,7 @@ public struct AccountsListRow: View {
.listStyle(.plain) .listStyle(.plain)
.scrollContentBackground(.hidden) .scrollContentBackground(.hidden)
.background(theme.primaryBackgroundColor) .background(theme.primaryBackgroundColor)
.environmentObject(theme) .environment(theme)
.environment(currentAccount) .environment(currentAccount)
.environment(client) .environment(client)
} }

View file

@ -5,8 +5,9 @@ import Network
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
public struct AccountsListView: View { public struct AccountsListView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@State private var viewModel: AccountsListViewModel @State private var viewModel: AccountsListViewModel

View file

@ -3,10 +3,11 @@ import Models
import Network import Network
import SwiftUI import SwiftUI
@MainActor
public struct EditAccountView: View { public struct EditAccountView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@Environment(Client.self) private var client @Environment(Client.self) private var client
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var viewModel = EditAccountViewModel() @State private var viewModel = EditAccountViewModel()

View file

@ -2,9 +2,10 @@ import DesignSystem
import Network import Network
import SwiftUI import SwiftUI
@MainActor
public struct EditRelationshipNoteView: View { public struct EditRelationshipNoteView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@State var accountDetailViewModel: AccountDetailViewModel @State var accountDetailViewModel: AccountDetailViewModel

View file

@ -4,10 +4,11 @@ import Models
import Network import Network
import SwiftUI import SwiftUI
@MainActor
struct EditFilterView: View { struct EditFilterView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var account @Environment(CurrentAccount.self) private var account
@Environment(Client.self) private var client @Environment(Client.self) private var client

View file

@ -7,7 +7,7 @@ import SwiftUI
public struct FiltersListView: View { public struct FiltersListView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var account @Environment(CurrentAccount.self) private var account
@Environment(Client.self) private var client @Environment(Client.self) private var client

View file

@ -4,7 +4,7 @@ import Env
import SwiftUI import SwiftUI
public struct AppAccountView: View { public struct AppAccountView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@Environment(AppAccountsManager.self) private var appAccounts @Environment(AppAccountsManager.self) private var appAccounts
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences

View file

@ -6,7 +6,7 @@ public struct AppAccountsSelectorView: View {
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(AppAccountsManager.self) private var appAccounts @Environment(AppAccountsManager.self) private var appAccounts
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
var routerPath: RouterPath var routerPath: RouterPath

View file

@ -5,6 +5,7 @@ import Network
import NukeUI import NukeUI
import SwiftUI import SwiftUI
@MainActor
public struct ConversationDetailView: View { public struct ConversationDetailView: View {
private enum Constants { private enum Constants {
static let bottomAnchor = "bottom" static let bottomAnchor = "bottom"
@ -14,7 +15,7 @@ public struct ConversationDetailView: View {
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(Client.self) private var client @Environment(Client.self) private var client
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(StreamWatcher.self) private var watcher @Environment(StreamWatcher.self) private var watcher
@State private var viewModel: ConversationDetailViewModel @State private var viewModel: ConversationDetailViewModel

View file

@ -5,12 +5,13 @@ import Network
import NukeUI import NukeUI
import SwiftUI import SwiftUI
@MainActor
struct ConversationMessageView: View { struct ConversationMessageView: View {
@Environment(QuickLook.self) private var quickLook @Environment(QuickLook.self) private var quickLook
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(Client.self) private var client @Environment(Client.self) private var client
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
let message: Status let message: Status
let conversation: Conversation let conversation: Conversation

View file

@ -5,10 +5,11 @@ import Models
import Network import Network
import SwiftUI import SwiftUI
@MainActor
struct ConversationsListRow: View { struct ConversationsListRow: View {
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Binding var conversation: Conversation @Binding var conversation: Conversation

View file

@ -10,7 +10,7 @@ public struct ConversationsListView: View {
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@Environment(StreamWatcher.self) private var watcher @Environment(StreamWatcher.self) private var watcher
@Environment(Client.self) private var client @Environment(Client.self) private var client
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var viewModel = ConversationsListViewModel() @State private var viewModel = ConversationsListViewModel()

View file

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1500"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DesignSystem"
BuildableName = "DesignSystem"
BlueprintName = "DesignSystem"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DesignSystem"
BuildableName = "DesignSystem"
BlueprintName = "DesignSystem"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -1,14 +1,35 @@
import Combine import Combine
import SwiftUI import SwiftUI
public class Theme: ObservableObject { @Observable public class Theme {
enum ThemeKey: String { class ThemeStorage {
case colorScheme, tint, label, primaryBackground, secondaryBackground enum ThemeKey: String {
case avatarPosition, avatarShape, statusActionsDisplay, statusDisplayStyle case colorScheme, tint, label, primaryBackground, secondaryBackground
case selectedSet, selectedScheme case avatarPosition, avatarShape, statusActionsDisplay, statusDisplayStyle
case followSystemColorSchme case selectedSet, selectedScheme
case displayFullUsernameTimeline case followSystemColorSchme
case lineSpacing case displayFullUsernameTimeline
case lineSpacing
}
@AppStorage("is_previously_set") public var isThemePreviouslySet: Bool = false
@AppStorage(ThemeKey.selectedScheme.rawValue) public var selectedScheme: ColorScheme = .dark
@AppStorage(ThemeKey.tint.rawValue) public var tintColor: Color = .black
@AppStorage(ThemeKey.primaryBackground.rawValue) public var primaryBackgroundColor: Color = .white
@AppStorage(ThemeKey.secondaryBackground.rawValue) public var secondaryBackgroundColor: Color = .gray
@AppStorage(ThemeKey.label.rawValue) public var labelColor: Color = .black
@AppStorage(ThemeKey.avatarPosition.rawValue) var rawAvatarPosition: String = AvatarPosition.top.rawValue
@AppStorage(ThemeKey.avatarShape.rawValue) var rawAvatarShape: String = AvatarShape.rounded.rawValue
@AppStorage(ThemeKey.selectedSet.rawValue) var storedSet: ColorSetName = .iceCubeDark
@AppStorage(ThemeKey.statusActionsDisplay.rawValue) public var statusActionsDisplay: StatusActionsDisplay = .full
@AppStorage(ThemeKey.statusDisplayStyle.rawValue) public var statusDisplayStyle: StatusDisplayStyle = .large
@AppStorage(ThemeKey.followSystemColorSchme.rawValue) public var followSystemColorScheme: Bool = true
@AppStorage(ThemeKey.displayFullUsernameTimeline.rawValue) public var displayFullUsername: Bool = true
@AppStorage(ThemeKey.lineSpacing.rawValue) public var lineSpacing: Double = 0.8
@AppStorage("font_size_scale") public var fontSizeScale: Double = 1
@AppStorage("chosen_font") public var chosenFontData: Data?
init() {}
} }
public enum FontState: Int, CaseIterable { public enum FontState: Int, CaseIterable {
@ -18,7 +39,6 @@ public class Theme: ObservableObject {
case SFRounded case SFRounded
case custom case custom
@MainActor
public var title: LocalizedStringKey { public var title: LocalizedStringKey {
switch self { switch self {
case .system: case .system:
@ -115,60 +135,144 @@ public class Theme: ObservableObject {
} }
} }
@AppStorage("is_previously_set") public var isThemePreviouslySet: Bool = false let themeStorage = ThemeStorage()
@AppStorage(ThemeKey.selectedScheme.rawValue) public var selectedScheme: ColorScheme = .dark
@AppStorage(ThemeKey.tint.rawValue) public var tintColor: Color = .black
@AppStorage(ThemeKey.primaryBackground.rawValue) public var primaryBackgroundColor: Color = .white
@AppStorage(ThemeKey.secondaryBackground.rawValue) public var secondaryBackgroundColor: Color = .gray
@AppStorage(ThemeKey.label.rawValue) public var labelColor: Color = .black
@AppStorage(ThemeKey.avatarPosition.rawValue) var rawAvatarPosition: String = AvatarPosition.top.rawValue
@AppStorage(ThemeKey.avatarShape.rawValue) var rawAvatarShape: String = AvatarShape.rounded.rawValue
@AppStorage(ThemeKey.selectedSet.rawValue) var storedSet: ColorSetName = .iceCubeDark
@AppStorage(ThemeKey.statusActionsDisplay.rawValue) public var statusActionsDisplay: StatusActionsDisplay = .full
@AppStorage(ThemeKey.statusDisplayStyle.rawValue) public var statusDisplayStyle: StatusDisplayStyle = .large
@AppStorage(ThemeKey.followSystemColorSchme.rawValue) public var followSystemColorScheme: Bool = true
@AppStorage(ThemeKey.displayFullUsernameTimeline.rawValue) public var displayFullUsername: Bool = true
@AppStorage(ThemeKey.lineSpacing.rawValue) public var lineSpacing: Double = 0.8
@AppStorage("font_size_scale") public var fontSizeScale: Double = 1
@AppStorage("chosen_font") public private(set) var chosenFontData: Data?
@Published public var avatarPosition: AvatarPosition = .top public var isThemePreviouslySet: Bool {
@Published public var avatarShape: AvatarShape = .rounded didSet {
@Published public var selectedSet: ColorSetName = .iceCubeDark themeStorage.isThemePreviouslySet = isThemePreviouslySet
}
}
private var cancellables = Set<AnyCancellable>() public var selectedScheme: ColorScheme {
didSet {
themeStorage.selectedScheme = selectedScheme
}
}
public var tintColor: Color {
didSet {
themeStorage.tintColor = tintColor
}
}
public var primaryBackgroundColor: Color {
didSet {
themeStorage.primaryBackgroundColor = primaryBackgroundColor
}
}
public var secondaryBackgroundColor: Color {
didSet {
themeStorage.secondaryBackgroundColor = secondaryBackgroundColor
}
}
public var labelColor: Color {
didSet {
themeStorage.labelColor = labelColor
}
}
private var rawAvatarPosition: String {
didSet {
themeStorage.rawAvatarPosition = rawAvatarPosition
}
}
private var rawAvatarShape: String {
didSet {
themeStorage.rawAvatarShape = rawAvatarShape
}
}
private var storedSet: ColorSetName {
didSet {
themeStorage.storedSet = storedSet
}
}
public var statusActionsDisplay: StatusActionsDisplay {
didSet {
themeStorage.statusActionsDisplay = statusActionsDisplay
}
}
public var statusDisplayStyle: StatusDisplayStyle {
didSet {
themeStorage.statusDisplayStyle = statusDisplayStyle
}
}
public var followSystemColorScheme: Bool {
didSet {
themeStorage.followSystemColorScheme = followSystemColorScheme
}
}
public var displayFullUsername: Bool {
didSet {
themeStorage.displayFullUsername = displayFullUsername
}
}
public var lineSpacing: Double {
didSet {
themeStorage.lineSpacing = lineSpacing
}
}
public var fontSizeScale: Double {
didSet {
themeStorage.fontSizeScale = fontSizeScale
}
}
public private(set) var chosenFontData: Data? {
didSet {
themeStorage.chosenFontData = chosenFontData
}
}
public var avatarPosition: AvatarPosition = .top {
didSet {
rawAvatarPosition = avatarShape.rawValue
}
}
public var avatarShape: AvatarShape = .rounded {
didSet {
rawAvatarShape = avatarShape.rawValue
}
}
public var selectedSet: ColorSetName = .iceCubeDark {
didSet {
setColor(withName: selectedSet)
}
}
public static let shared = Theme() public static let shared = Theme()
private init() { private init() {
isThemePreviouslySet = themeStorage.isThemePreviouslySet
selectedScheme = themeStorage.selectedScheme
tintColor = themeStorage.tintColor
primaryBackgroundColor = themeStorage.primaryBackgroundColor
secondaryBackgroundColor = themeStorage.secondaryBackgroundColor
labelColor = themeStorage.labelColor
rawAvatarPosition = themeStorage.rawAvatarPosition
rawAvatarShape = themeStorage.rawAvatarShape
storedSet = themeStorage.storedSet
statusActionsDisplay = themeStorage.statusActionsDisplay
statusDisplayStyle = themeStorage.statusDisplayStyle
followSystemColorScheme = themeStorage.followSystemColorScheme
displayFullUsername = themeStorage.displayFullUsername
lineSpacing = themeStorage.lineSpacing
fontSizeScale = themeStorage.fontSizeScale
chosenFontData = themeStorage.chosenFontData
selectedSet = storedSet selectedSet = storedSet
avatarPosition = AvatarPosition(rawValue: rawAvatarPosition) ?? .top avatarPosition = AvatarPosition(rawValue: rawAvatarPosition) ?? .top
avatarShape = AvatarShape(rawValue: rawAvatarShape) ?? .rounded avatarShape = AvatarShape(rawValue: rawAvatarShape) ?? .rounded
$avatarPosition
.dropFirst()
.map(\.rawValue)
.sink { [weak self] position in
self?.rawAvatarPosition = position
}
.store(in: &cancellables)
$avatarShape
.dropFirst()
.map(\.rawValue)
.sink { [weak self] shape in
self?.rawAvatarShape = shape
}
.store(in: &cancellables)
// Workaround, since @AppStorage can't be directly observed
$selectedSet
.dropFirst()
.sink { [weak self] colorSetName in
self?.setColor(withName: colorSetName)
}
.store(in: &cancellables)
} }
public static var allColorSet: [ColorSet] { public static var allColorSet: [ColorSet] {

View file

@ -9,10 +9,11 @@ public extension View {
} }
} }
@MainActor
struct ThemeApplier: ViewModifier { struct ThemeApplier: ViewModifier {
@Environment(\EnvironmentValues.colorScheme) var colorScheme @Environment(\EnvironmentValues.colorScheme) var colorScheme
@ObservedObject var theme: Theme var theme: Theme
var actualColorScheme: SwiftUI.ColorScheme? { var actualColorScheme: SwiftUI.ColorScheme? {
if theme.followSystemColorScheme { if theme.followSystemColorScheme {

View file

@ -0,0 +1 @@
import SwiftUI

View file

@ -6,7 +6,7 @@ import SwiftUI
@MainActor @MainActor
public struct AvatarView: View { public struct AvatarView: View {
@Environment(\.redactionReasons) private var reasons @Environment(\.redactionReasons) private var reasons
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
public enum Size { public enum Size {
case account, status, embed, badge, list, boost case account, status, embed, badge, list, boost

View file

@ -3,7 +3,7 @@ import SwiftUI
public struct ThemePreviewView: View { public struct ThemePreviewView: View {
private let gutterSpace: Double = 8 private let gutterSpace: Double = 8
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
public init() {} public init() {}
@ -25,7 +25,7 @@ public struct ThemePreviewView: View {
} }
struct ThemeBoxView: View { struct ThemeBoxView: View {
@EnvironmentObject var theme: Theme @Environment(Theme.self) private var theme
private let gutterSpace = 8.0 private let gutterSpace = 8.0
@State private var isSelected = false @State private var isSelected = false

View file

@ -59,7 +59,7 @@ public extension EnvironmentValues {
get { self[IsStatusFocused.self] } get { self[IsStatusFocused.self] }
set { self[IsStatusFocused.self] = newValue } set { self[IsStatusFocused.self] = newValue }
} }
var isStatusReplyToPrevious: Bool { var isStatusReplyToPrevious: Bool {
get { self[IsStatusReplyToPrevious.self] } get { self[IsStatusReplyToPrevious.self] }
set { self[IsStatusReplyToPrevious.self] = newValue } set { self[IsStatusReplyToPrevious.self] = newValue }

View file

@ -7,8 +7,9 @@ import Shimmer
import Status import Status
import SwiftUI import SwiftUI
@MainActor
public struct ExploreView: View { public struct ExploreView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath

View file

@ -3,7 +3,7 @@ import Models
import SwiftUI import SwiftUI
public struct TagsListView: View { public struct TagsListView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
let tags: [Tag] let tags: [Tag]

View file

@ -4,10 +4,11 @@ import Models
import Network import Network
import SwiftUI import SwiftUI
@MainActor
public struct ListAddAccountView: View { public struct ListAddAccountView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@Environment(Client.self) private var client @Environment(Client.self) private var client
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@State private var viewModel: ListAddAccountViewModel @State private var viewModel: ListAddAccountViewModel

View file

@ -4,9 +4,10 @@ import Models
import Network import Network
import SwiftUI import SwiftUI
@MainActor
public struct ListEditView: View { public struct ListEditView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@State private var viewModel: ListEditViewModel @State private var viewModel: ListEditViewModel

View file

@ -6,8 +6,9 @@ import Network
import Status import Status
import SwiftUI import SwiftUI
@MainActor
struct NotificationRowView: View { struct NotificationRowView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(\.redactionReasons) private var reasons @Environment(\.redactionReasons) private var reasons
let notification: ConsolidatedNotification let notification: ConsolidatedNotification

View file

@ -5,9 +5,10 @@ import Network
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
public struct NotificationsListView: View { public struct NotificationsListView: View {
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(StreamWatcher.self) private var watcher @Environment(StreamWatcher.self) private var watcher
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath

View file

@ -5,8 +5,9 @@ import Network
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
public struct StatusDetailView: View { public struct StatusDetailView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(StreamWatcher.self) private var watcher @Environment(StreamWatcher.self) private var watcher
@Environment(Client.self) private var client @Environment(Client.self) private var client

View file

@ -19,7 +19,7 @@ import SwiftUI
var state: State = .loading var state: State = .loading
var title: LocalizedStringKey = "" var title: LocalizedStringKey = ""
var scrollToId: String? var scrollToId: String?
@ObservationIgnored @ObservationIgnored
var isReplyToPreviousCache: [String: Bool] = [:] var isReplyToPreviousCache: [String: Bool] = [:]
@ -127,7 +127,7 @@ import SwiftUI
isReplyToPreviousCache[status.id] = isReplyToPrevious isReplyToPreviousCache[status.id] = isReplyToPrevious
} }
} }
func handleEvent(event: any StreamEvent, currentAccount: Account?) { func handleEvent(event: any StreamEvent, currentAccount: Account?) {
Task { Task {
if let event = event as? StreamEventUpdate, if let event = event as? StreamEventUpdate,

View file

@ -7,7 +7,7 @@ import SwiftUI
struct StatusEditorAccessoryView: View { struct StatusEditorAccessoryView: View {
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
@Environment(\.colorScheme) private var colorScheme @Environment(\.colorScheme) private var colorScheme

View file

@ -3,8 +3,9 @@ import EmojiText
import Foundation import Foundation
import SwiftUI import SwiftUI
@MainActor
struct StatusEditorAutoCompleteView: View { struct StatusEditorAutoCompleteView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
var viewModel: StatusEditorViewModel var viewModel: StatusEditorViewModel
var body: some View { var body: some View {

View file

@ -6,7 +6,7 @@ import SwiftUI
struct StatusEditorMediaEditView: View { struct StatusEditorMediaEditView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
var viewModel: StatusEditorViewModel var viewModel: StatusEditorViewModel
let container: StatusEditorMediaContainer let container: StatusEditorMediaContainer

View file

@ -5,8 +5,9 @@ import Models
import NukeUI import NukeUI
import SwiftUI import SwiftUI
@MainActor
struct StatusEditorMediaView: View { struct StatusEditorMediaView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
var viewModel: StatusEditorViewModel var viewModel: StatusEditorViewModel
@State private var editingContainer: StatusEditorMediaContainer? @State private var editingContainer: StatusEditorMediaContainer?

View file

@ -2,6 +2,7 @@ import DesignSystem
import Env import Env
import SwiftUI import SwiftUI
@MainActor
struct StatusEditorPollView: View { struct StatusEditorPollView: View {
enum FocusField: Hashable { enum FocusField: Hashable {
case option(Int) case option(Int)
@ -11,7 +12,7 @@ struct StatusEditorPollView: View {
@State private var currentFocusIndex: Int = 0 @State private var currentFocusIndex: Int = 0
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
var viewModel: StatusEditorViewModel var viewModel: StatusEditorViewModel

View file

@ -11,10 +11,11 @@ import StoreKit
import SwiftUI import SwiftUI
import UIKit import UIKit
@MainActor
public struct StatusEditorView: View { public struct StatusEditorView: View {
@Environment(AppAccountsManager.self) private var appAccounts @Environment(AppAccountsManager.self) private var appAccounts
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(RouterPath.self) private var routerPath @Environment(RouterPath.self) private var routerPath
@ -238,7 +239,7 @@ public struct StatusEditorView: View {
avatarSize: .status) avatarSize: .status)
} else { } else {
AvatarView(url: account.avatar, size: .status) AvatarView(url: account.avatar, size: .status)
.environmentObject(theme) .environment(theme)
.accessibilityHidden(true) .accessibilityHidden(true)
} }
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {

View file

@ -7,7 +7,7 @@ import SwiftUI
@MainActor @MainActor
public struct StatusEmbeddedView: View { public struct StatusEmbeddedView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
public let status: Status public let status: Status
public let client: Client public let client: Client

View file

@ -7,7 +7,7 @@ public struct StatusEditHistoryView: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@Environment(Client.self) private var client @Environment(Client.self) private var client
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
private let statusId: String private let statusId: String

View file

@ -5,8 +5,9 @@ import Network
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher { public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var fetcher: Fetcher @State private var fetcher: Fetcher
// Whether this status is on a remote local timeline (many actions are unavailable if so) // Whether this status is on a remote local timeline (many actions are unavailable if so)

View file

@ -52,7 +52,7 @@ struct VideoPlayerView: View {
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@Environment(\.isCompact) private var isCompact @Environment(\.isCompact) private var isCompact
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State var viewModel: VideoPlayerViewModel @State var viewModel: VideoPlayerViewModel

View file

@ -4,8 +4,9 @@ import Models
import Network import Network
import SwiftUI import SwiftUI
@MainActor
public struct StatusPollView: View { public struct StatusPollView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@Environment(CurrentInstance.self) private var currentInstance @Environment(CurrentInstance.self) private var currentInstance
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount

View file

@ -7,6 +7,7 @@ import Network
import Shimmer import Shimmer
import SwiftUI import SwiftUI
@MainActor
public struct StatusRowView: View { public struct StatusRowView: View {
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool @Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
@Environment(\.redactionReasons) private var reasons @Environment(\.redactionReasons) private var reasons
@ -16,7 +17,7 @@ public struct StatusRowView: View {
@Environment(\.isStatusReplyToPrevious) private var isStatusReplyToPrevious @Environment(\.isStatusReplyToPrevious) private var isStatusReplyToPrevious
@Environment(QuickLook.self) private var quickLook @Environment(QuickLook.self) private var quickLook
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@State private var viewModel: StatusRowViewModel @State private var viewModel: StatusRowViewModel
@ -95,7 +96,7 @@ public struct StatusRowView: View {
viewModel.navigateToDetail() viewModel.navigateToDetail()
} }
} }
if isFocused { if isFocused {
StatusRowDetailView(viewModel: viewModel) StatusRowDetailView(viewModel: viewModel)
} }

View file

@ -15,10 +15,10 @@ import SwiftUI
let showActions: Bool let showActions: Bool
let textDisabled: Bool let textDisabled: Bool
let finalStatus: AnyStatus let finalStatus: AnyStatus
let client: Client let client: Client
let routerPath: RouterPath let routerPath: RouterPath
private let theme = Theme.shared private let theme = Theme.shared
private let userMentionned: Bool private let userMentionned: Bool

View file

@ -5,7 +5,7 @@ import Network
import SwiftUI import SwiftUI
struct StatusRowActionsView: View { struct StatusRowActionsView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(StatusDataController.self) private var statusDataController @Environment(StatusDataController.self) private var statusDataController
@EnvironmentObject private var userPreferences: UserPreferences @EnvironmentObject private var userPreferences: UserPreferences
@ -13,7 +13,7 @@ struct StatusRowActionsView: View {
@Environment(\.isStatusFocused) private var isFocused @Environment(\.isStatusFocused) private var isFocused
var viewModel: StatusRowViewModel var viewModel: StatusRowViewModel
func privateBoost() -> Bool { func privateBoost() -> Bool {
viewModel.status.visibility == .priv && viewModel.status.account.id == currentAccount.account?.id viewModel.status.visibility == .priv && viewModel.status.account.id == currentAccount.account?.id
} }

View file

@ -9,7 +9,7 @@ public struct StatusRowCardView: View {
@Environment(\.openURL) private var openURL @Environment(\.openURL) private var openURL
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool @Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
let card: Card let card: Card

View file

@ -8,7 +8,7 @@ struct StatusRowContentView: View {
@Environment(\.isCompact) private var isCompact @Environment(\.isCompact) private var isCompact
@Environment(\.isStatusFocused) private var isFocused @Environment(\.isStatusFocused) private var isFocused
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
var viewModel: StatusRowViewModel var viewModel: StatusRowViewModel

View file

@ -4,6 +4,7 @@ import Foundation
import Network import Network
import SwiftUI import SwiftUI
@MainActor
struct StatusRowContextMenu: View { struct StatusRowContextMenu: View {
@Environment(\.displayScale) var displayScale @Environment(\.displayScale) var displayScale
@ -85,7 +86,7 @@ struct StatusRowContextMenu: View {
.padding(16) .padding(16)
} }
.environment(\.isInCaptureMode, true) .environment(\.isInCaptureMode, true)
.environmentObject(Theme.shared) .environment(Theme.shared)
.environmentObject(preferences) .environmentObject(preferences)
.environment(account) .environment(account)
.environment(currentInstance) .environment(currentInstance)

View file

@ -75,7 +75,7 @@ struct StatusRowDetailView: View {
.buttonStyle(.borderless) .buttonStyle(.borderless)
.transition(.move(edge: .leading)) .transition(.move(edge: .leading))
} }
if viewModel.actionsAccountsFetched, statusDataController.reblogsCount > 0 { if viewModel.actionsAccountsFetched, statusDataController.reblogsCount > 0 {
Divider() Divider()
Button { Button {

View file

@ -3,11 +3,12 @@ import Env
import Models import Models
import SwiftUI import SwiftUI
@MainActor
struct StatusRowHeaderView: View { struct StatusRowHeaderView: View {
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool @Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
@Environment(\.isStatusFocused) private var isFocused @Environment(\.isStatusFocused) private var isFocused
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
let viewModel: StatusRowViewModel let viewModel: StatusRowViewModel

View file

@ -14,7 +14,7 @@ public struct StatusRowMediaPreviewView: View {
@Environment(SceneDelegate.self) private var sceneDelegate @Environment(SceneDelegate.self) private var sceneDelegate
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@Environment(QuickLook.self) private var quickLook @Environment(QuickLook.self) private var quickLook
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
public let attachments: [MediaAttachment] public let attachments: [MediaAttachment]
public let sensitive: Bool public let sensitive: Bool

View file

@ -4,7 +4,7 @@ import Models
import SwiftUI import SwiftUI
struct StatusRowSwipeView: View { struct StatusRowSwipeView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@Environment(CurrentAccount.self) private var currentAccount @Environment(CurrentAccount.self) private var currentAccount
@Environment(StatusDataController.self) private var statusDataController @Environment(StatusDataController.self) private var statusDataController

View file

@ -3,8 +3,9 @@ import Env
import Models import Models
import SwiftUI import SwiftUI
@MainActor
struct StatusRowTextView: View { struct StatusRowTextView: View {
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(\.isStatusFocused) private var isFocused @Environment(\.isStatusFocused) private var isFocused
var viewModel: StatusRowViewModel var viewModel: StatusRowViewModel

View file

@ -7,13 +7,14 @@ import Status
import SwiftUI import SwiftUI
import SwiftUIIntrospect import SwiftUIIntrospect
@MainActor
public struct TimelineView: View { public struct TimelineView: View {
private enum Constants { private enum Constants {
static let scrollToTop = "top" static let scrollToTop = "top"
} }
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@EnvironmentObject private var theme: Theme @Environment(Theme.self) private var theme
@Environment(CurrentAccount.self) private var account @Environment(CurrentAccount.self) private var account
@Environment(StreamWatcher.self) private var watcher @Environment(StreamWatcher.self) private var watcher
@Environment(Client.self) private var client @Environment(Client.self) private var client