diff --git a/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift b/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift index 64a59806..cdc53c72 100644 --- a/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift +++ b/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift @@ -7,6 +7,7 @@ import Observation import StatusKit import SwiftUI +@MainActor @Observable class DisplaySettingsLocalValues { var tintColor = Theme.shared.tintColor var primaryBackgroundColor = Theme.shared.primaryBackgroundColor diff --git a/IceCubesApp/App/Tabs/Settings/SidebarEntriesSettingsView.swift b/IceCubesApp/App/Tabs/Settings/SidebarEntriesSettingsView.swift index 15704630..0d1a157f 100644 --- a/IceCubesApp/App/Tabs/Settings/SidebarEntriesSettingsView.swift +++ b/IceCubesApp/App/Tabs/Settings/SidebarEntriesSettingsView.swift @@ -2,6 +2,7 @@ import DesignSystem import Env import SwiftUI +@MainActor struct SidebarEntriesSettingsView: View { @Environment(Theme.self) private var theme @Environment(UserPreferences.self) private var userPreferences diff --git a/IceCubesApp/App/Tabs/Tabs.swift b/IceCubesApp/App/Tabs/Tabs.swift index ee0c9491..2a05600f 100644 --- a/IceCubesApp/App/Tabs/Tabs.swift +++ b/IceCubesApp/App/Tabs/Tabs.swift @@ -157,6 +157,7 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable { } } +@MainActor @Observable class SidebarTabs { struct SidedebarTab: Hashable, Codable { @@ -202,6 +203,7 @@ class SidebarTabs { } } +@MainActor @Observable class iOSTabs { enum TabEntries: String { diff --git a/Packages/Account/Sources/Account/AccountDetailView.swift b/Packages/Account/Sources/Account/AccountDetailView.swift index 83f3d8fc..18cfda0d 100644 --- a/Packages/Account/Sources/Account/AccountDetailView.swift +++ b/Packages/Account/Sources/Account/AccountDetailView.swift @@ -371,6 +371,7 @@ public struct AccountDetailView: View { } extension View { + @MainActor func applyAccountDetailsRowStyle(theme: Theme) -> some View { listRowInsets(.init()) .listRowSeparator(.hidden) diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift index 9da47fb4..e1d8841d 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift @@ -33,11 +33,11 @@ public struct AppAccountsSelectorView: View { public init(routerPath: RouterPath, accountCreationEnabled: Bool = true, - avatarConfig: AvatarView.FrameConfig = .badge) + avatarConfig: AvatarView.FrameConfig? = nil) { self.routerPath = routerPath self.accountCreationEnabled = accountCreationEnabled - self.avatarConfig = avatarConfig + self.avatarConfig = avatarConfig ?? .badge } public var body: some View { diff --git a/Packages/DesignSystem/Sources/DesignSystem/SceneDelegate.swift b/Packages/DesignSystem/Sources/DesignSystem/SceneDelegate.swift index 45858bb6..5aa5ad8a 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/SceneDelegate.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/SceneDelegate.swift @@ -2,7 +2,7 @@ import Combine import UIKit @Observable -public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable { +@MainActor public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable { public var window: UIWindow? #if os(visionOS) public private(set) var windowWidth: CGFloat = 0 @@ -47,12 +47,12 @@ public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable { } private static var observedSceneDelegate: Set = [] - private static let observer = Task { + private static let observer = Task { @MainActor in while true { try? await Task.sleep(for: .seconds(0.1)) for delegate in observedSceneDelegate { #if os(visionOS) - let newWidth = delegate.window?.bounds.size.width ?? 0 + let newWidth = delegate.window?.bounds.size.width ?? 0 if delegate.windowWidth != newWidth { delegate.windowWidth = newWidth } diff --git a/Packages/DesignSystem/Sources/DesignSystem/Theme.swift b/Packages/DesignSystem/Sources/DesignSystem/Theme.swift index a3df5acf..bfef00c9 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/Theme.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/Theme.swift @@ -1,8 +1,10 @@ import Combine import SwiftUI -@Observable public class Theme { - class ThemeStorage { +@MainActor +@Observable +public final class Theme { + final class ThemeStorage { enum ThemeKey: String { case colorScheme, tint, label, primaryBackground, secondaryBackground case avatarPosition2, avatarShape2, statusActionsDisplay, statusDisplayStyle diff --git a/Packages/DesignSystem/Sources/DesignSystem/ThemeApplier.swift b/Packages/DesignSystem/Sources/DesignSystem/ThemeApplier.swift index 6f0da968..2612d66e 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/ThemeApplier.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/ThemeApplier.swift @@ -4,7 +4,7 @@ import SwiftUI #endif public extension View { - func applyTheme(_ theme: Theme) -> some View { + @MainActor func applyTheme(_ theme: Theme) -> some View { modifier(ThemeApplier(theme: theme)) } } diff --git a/Packages/DesignSystem/Sources/DesignSystem/Views/AccountPopoverView.swift b/Packages/DesignSystem/Sources/DesignSystem/Views/AccountPopoverView.swift index 8da78d35..fb63f493 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/Views/AccountPopoverView.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/Views/AccountPopoverView.swift @@ -4,6 +4,7 @@ import Nuke import NukeUI import SwiftUI +@MainActor struct AccountPopoverView: View { let account: Account let theme: Theme // using `@Environment(Theme.self) will crash the SwiftUI preview diff --git a/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift b/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift index b341a970..ae256793 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift @@ -33,7 +33,8 @@ public struct AvatarView: View { self.config = config } - public struct FrameConfig: Equatable { + @MainActor + public struct FrameConfig: Equatable, Sendable { public let size: CGSize public var width: CGFloat { size.width } public var height: CGFloat { size.height } diff --git a/Packages/DesignSystem/Sources/DesignSystem/Views/NextPageView.swift b/Packages/DesignSystem/Sources/DesignSystem/Views/NextPageView.swift index 95437537..b849862d 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/Views/NextPageView.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/Views/NextPageView.swift @@ -1,5 +1,6 @@ import SwiftUI +@MainActor public struct NextPageView: View { @State private var isLoadingNextPage: Bool = false @State private var showRetry: Bool = false diff --git a/Packages/DesignSystem/Sources/DesignSystem/Views/ScrollViewOffsetReader.swift b/Packages/DesignSystem/Sources/DesignSystem/Views/ScrollViewOffsetReader.swift deleted file mode 100644 index 71068105..00000000 --- a/Packages/DesignSystem/Sources/DesignSystem/Views/ScrollViewOffsetReader.swift +++ /dev/null @@ -1,44 +0,0 @@ -/*! @copyright 2021 Medium */ - -import SwiftUI - -// Source: https://www.fivestars.blog/articles/scrollview-offset/ - -public struct ScrollViewOffsetReader: View { - let onOffsetChange: (CGFloat) -> Void - let content: () -> Content - - public init( - onOffsetChange: @escaping (CGFloat) -> Void, - @ViewBuilder content: @escaping () -> Content - ) { - self.onOffsetChange = onOffsetChange - self.content = content - } - - public var body: some View { - ScrollView { - offsetReader - content() - .padding(.top, -8) - } - .coordinateSpace(name: "frameLayer") - .onPreferenceChange(OffsetPreferenceKey.self, perform: onOffsetChange) - } - - var offsetReader: some View { - GeometryReader { proxy in - Color.clear - .preference( - key: OffsetPreferenceKey.self, - value: proxy.frame(in: .named("frameLayer")).minY - ) - } - .frame(height: 0) - } -} - -private struct OffsetPreferenceKey: PreferenceKey { - static var defaultValue: CGFloat = .zero - static func reduce(value _: inout CGFloat, nextValue _: () -> CGFloat) {} -} diff --git a/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift b/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift index ea8ea745..d4906bd9 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift @@ -67,6 +67,7 @@ extension Models.Notification.NotificationType { } } + @MainActor func tintColor(isPrivate: Bool) -> Color { if isPrivate { return Color.orange.opacity(0.80) diff --git a/Packages/Timeline/Sources/Timeline/View/TimelineContentFilterView.swift b/Packages/Timeline/Sources/Timeline/View/TimelineContentFilterView.swift index 4f4e110a..133a149f 100644 --- a/Packages/Timeline/Sources/Timeline/View/TimelineContentFilterView.swift +++ b/Packages/Timeline/Sources/Timeline/View/TimelineContentFilterView.swift @@ -2,6 +2,7 @@ import DesignSystem import SwiftUI import Env +@MainActor public struct TimelineContentFilterView: View { @Environment(Theme.self) private var theme @Environment(CurrentInstance.self) private var currentInstance diff --git a/Packages/Timeline/Sources/Timeline/actors/TimelineDatasource.swift b/Packages/Timeline/Sources/Timeline/actors/TimelineDatasource.swift index ac094522..40f4914d 100644 --- a/Packages/Timeline/Sources/Timeline/actors/TimelineDatasource.swift +++ b/Packages/Timeline/Sources/Timeline/actors/TimelineDatasource.swift @@ -14,7 +14,7 @@ actor TimelineDatasource { } func getFiltered() async -> [Status] { - let contentFilter = TimelineContentFilter.shared + let contentFilter = await TimelineContentFilter.shared let showReplies = await contentFilter.showReplies let showBoosts = await contentFilter.showBoosts let showThreads = await contentFilter.showThreads