diff --git a/Anytype/Sources/ApplicationLayer/GlobalEnv/GlobalEnvModifier.swift b/Anytype/Sources/ApplicationLayer/GlobalEnv/GlobalEnvModifier.swift index 01ccd6020f..40dc858554 100644 --- a/Anytype/Sources/ApplicationLayer/GlobalEnv/GlobalEnvModifier.swift +++ b/Anytype/Sources/ApplicationLayer/GlobalEnv/GlobalEnvModifier.swift @@ -4,10 +4,7 @@ import SwiftUI private struct GlobalEnvModifier: ViewModifier { @State private var windowHolder = WindowHolder(window: nil) - @Injected(\.userDefaultsStorage) - private var userDefaults: any UserDefaultsStorageProtocol - @Injected(\.legacyViewControllerProvider) - private var viewControllerProvider: any ViewControllerProviderProtocol + @State private var model = GlobalEnvModifierModel() func body(content: Content) -> some View { content @@ -17,13 +14,30 @@ private struct GlobalEnvModifier: ViewModifier { .setAppInterfaceStyleEnv(window: windowHolder.window) // Legacy :( .onChange(of: windowHolder) { _, newValue in - viewControllerProvider.setSceneWindow(newValue.window) - newValue.window?.overrideUserInterfaceStyle = userDefaults.userInterfaceStyle + model.setSceneWindow(newValue.window) + newValue.window?.overrideUserInterfaceStyle = model.userInterfaceStyle } } } +@MainActor +@Observable +private final class GlobalEnvModifierModel { + @Injected(\.userDefaultsStorage) @ObservationIgnored + private var userDefaults: any UserDefaultsStorageProtocol + @Injected(\.legacyViewControllerProvider) @ObservationIgnored + private var viewControllerProvider: any ViewControllerProviderProtocol + + var userInterfaceStyle: UIUserInterfaceStyle { + userDefaults.userInterfaceStyle + } + + func setSceneWindow(_ window: UIWindow?) { + viewControllerProvider.setSceneWindow(window) + } +} + extension View { func setupGlobalEnv() -> some View { self.modifier(GlobalEnvModifier()) diff --git a/Anytype/Sources/PresentationLayer/Common/SwiftUI/IconView/Specific/Object/TodoIconView.swift b/Anytype/Sources/PresentationLayer/Common/SwiftUI/IconView/Specific/Object/TodoIconView.swift index fc3d5d37c3..36b91baff4 100644 --- a/Anytype/Sources/PresentationLayer/Common/SwiftUI/IconView/Specific/Object/TodoIconView.swift +++ b/Anytype/Sources/PresentationLayer/Common/SwiftUI/IconView/Specific/Object/TodoIconView.swift @@ -5,9 +5,7 @@ import Services struct TodoIconView: View { private static let maxSide = 28.0 - - @Injected(\.objectActionsService) - private var objectActionsService: any ObjectActionsServiceProtocol + @State private var model = TodoIconViewModel() let checked: Bool let objectId: String? @@ -20,10 +18,22 @@ struct TodoIconView: View { .frame(maxWidth: 28, maxHeight: 28) .onTapGesture { guard let objectId else { return } - Task { - try await objectActionsService.updateBundledDetails(contextID: objectId, details: [.done(!checked)]) - UIImpactFeedbackGenerator(style: .rigid).impactOccurred() - } + model.updateDone(objectId: objectId, checked: !checked) } } } + +@MainActor +@Observable +private final class TodoIconViewModel { + + @Injected(\.objectActionsService) @ObservationIgnored + private var objectActionsService: any ObjectActionsServiceProtocol + + func updateDone(objectId: String, checked: Bool) { + Task { + try await objectActionsService.updateBundledDetails(contextID: objectId, details: [.done(checked)]) + UIImpactFeedbackGenerator(style: .rigid).impactOccurred() + } + } +} diff --git a/Anytype/Sources/PresentationLayer/Debug/ExportStackGoroutines/ExportStackGoroutinesViewModifier.swift b/Anytype/Sources/PresentationLayer/Debug/ExportStackGoroutines/ExportStackGoroutinesViewModifier.swift index a28b84f290..00095a07c4 100644 --- a/Anytype/Sources/PresentationLayer/Debug/ExportStackGoroutines/ExportStackGoroutinesViewModifier.swift +++ b/Anytype/Sources/PresentationLayer/Debug/ExportStackGoroutines/ExportStackGoroutinesViewModifier.swift @@ -1,11 +1,9 @@ import SwiftUI import Services - struct ExportStackGoroutinesViewModifier: ViewModifier { - @Injected(\.debugService) - private var debugService: any DebugServiceProtocol + @State private var model = ExportStackGoroutinesViewModel() @State private var shareUrlFile: URL? @Binding var isPresented: Bool @@ -21,10 +19,21 @@ struct ExportStackGoroutinesViewModifier: ViewModifier { } private func exportStackGoroutines() { - Task { shareUrlFile = try await debugService.exportStackGoroutinesZip() } + Task { shareUrlFile = try await model.exportStackGoroutinesZip() } } } +@MainActor +@Observable +private final class ExportStackGoroutinesViewModel { + + @Injected(\.debugService) @ObservationIgnored + private var debugService: any DebugServiceProtocol + + func exportStackGoroutinesZip() async throws -> URL { + try await debugService.exportStackGoroutinesZip() + } +} extension View { func exportStackGoroutinesSheet(isPresented: Binding) -> some View { diff --git a/Anytype/Sources/PresentationLayer/Modules/Chat/AttachmentProcessor.swift b/Anytype/Sources/PresentationLayer/Modules/Chat/AttachmentProcessor.swift index 34c54a22af..3f2d70e840 100644 --- a/Anytype/Sources/PresentationLayer/Modules/Chat/AttachmentProcessor.swift +++ b/Anytype/Sources/PresentationLayer/Modules/Chat/AttachmentProcessor.swift @@ -7,19 +7,19 @@ import Factory import AnytypeCore @MainActor -protocol AttachmentProcessor { +protocol AttachmentProcessor: AnyObject { associatedtype Input func process(_ input: Input, spaceId: String) throws -> ChatLinkedObject } @MainActor -protocol AsyncAttachmentProcessor { +protocol AsyncAttachmentProcessor: AnyObject { associatedtype Input func process(_ input: Input, spaceId: String) async throws -> ChatLinkedObject } @MainActor -struct FileAttachmentProcessor: AttachmentProcessor { +final class FileAttachmentProcessor: AttachmentProcessor { @Injected(\.fileActionsService) private var fileActionsService: any FileActionsServiceProtocol @@ -39,7 +39,7 @@ struct FileAttachmentProcessor: AttachmentProcessor { } @MainActor -struct CameraMediaProcessor: AttachmentProcessor { +final class CameraMediaProcessor: AttachmentProcessor { @Injected(\.fileActionsService) private var fileActionsService: any FileActionsServiceProtocol @@ -61,7 +61,7 @@ struct CameraMediaProcessor: AttachmentProcessor { } @MainActor -struct PhotosPickerProcessor: AsyncAttachmentProcessor { +final class PhotosPickerProcessor: AsyncAttachmentProcessor { @Injected(\.fileActionsService) private var fileActionsService: any FileActionsServiceProtocol @@ -73,7 +73,7 @@ struct PhotosPickerProcessor: AsyncAttachmentProcessor { } @MainActor -struct PasteBufferProcessor: AsyncAttachmentProcessor { +final class PasteBufferProcessor: AsyncAttachmentProcessor { @Injected(\.fileActionsService) private var fileActionsService: any FileActionsServiceProtocol @@ -87,7 +87,7 @@ struct PasteBufferProcessor: AsyncAttachmentProcessor { } @MainActor -struct LinkPreviewProcessor: AsyncAttachmentProcessor { +final class LinkPreviewProcessor: AsyncAttachmentProcessor { @Injected(\.bookmarkService) private var bookmarkService: any BookmarkServiceProtocol @@ -106,7 +106,7 @@ struct LinkPreviewProcessor: AsyncAttachmentProcessor { } @MainActor -struct UploadedObjectProcessor: AttachmentProcessor { +final class UploadedObjectProcessor: AttachmentProcessor { func process(_ input: MessageAttachmentDetails, spaceId: String) throws -> ChatLinkedObject { return .uploadedObject(input) diff --git a/Anytype/Sources/PresentationLayer/Modules/Chat/AttachmentValidator.swift b/Anytype/Sources/PresentationLayer/Modules/Chat/AttachmentValidator.swift index a783630652..c4ca16cfc0 100644 --- a/Anytype/Sources/PresentationLayer/Modules/Chat/AttachmentValidator.swift +++ b/Anytype/Sources/PresentationLayer/Modules/Chat/AttachmentValidator.swift @@ -13,7 +13,7 @@ struct AttachmentValidationResult { } @MainActor -struct ChatAttachmentValidator { +final class ChatAttachmentValidator { @Injected(\.chatMessageLimits) private var chatMessageLimits: any ChatMessageLimitsProtocol diff --git a/Anytype/Sources/PresentationLayer/TextEditor/BlocksViews/Blocks/File/Image/BlockImageViewModel.swift b/Anytype/Sources/PresentationLayer/TextEditor/BlocksViews/Blocks/File/Image/BlockImageViewModel.swift index 748c2d4971..250e697c45 100644 --- a/Anytype/Sources/PresentationLayer/TextEditor/BlocksViews/Blocks/File/Image/BlockImageViewModel.swift +++ b/Anytype/Sources/PresentationLayer/TextEditor/BlocksViews/Blocks/File/Image/BlockImageViewModel.swift @@ -4,7 +4,7 @@ import Combine import AnytypeCore @MainActor -struct BlockImageViewModel: BlockViewModelProtocol { +final class BlockImageViewModel: BlockViewModelProtocol { typealias Action = (_ arg: T) -> Void @Injected(\.openedDocumentProvider)