Skip to content

Commit 19d389e

Browse files
committed
IOS-5255 Migrate object settings menu to Observation framework
Replaced Combine publishers with withObservationTracking for manual observation of nested @observable objects. Changes include: - Removed Combine dependency and cancellables - Updated @StateObject to @State in views - Converted @published properties to regular properties - Added @ObservationIgnored to injected dependencies and non-observed properties - Implemented manual observation pattern using withObservationTracking for settings and actions
1 parent 4187fdd commit 19d389e

File tree

6 files changed

+73
-48
lines changed

6 files changed

+73
-48
lines changed

Anytype/Sources/PresentationLayer/TextEditor/EditorPage/Views/Settings/ObjectActions/ObjectActionsView.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import SwiftUI
22
import AnytypeCore
33

44
struct ObjectActionsView: View {
5-
6-
@StateObject private var viewModel: ObjectActionsViewModel
5+
6+
@State private var viewModel: ObjectActionsViewModel
77
@Environment(\.dismiss) private var dismiss
8-
8+
99
init(objectId: String, spaceId: String, output: (any ObjectActionsOutput)?) {
10-
self._viewModel = StateObject(wrappedValue: ObjectActionsViewModel(objectId: objectId, spaceId: spaceId, output: output))
10+
self._viewModel = State(wrappedValue: ObjectActionsViewModel(objectId: objectId, spaceId: spaceId, output: output))
1111
}
1212

1313
var body: some View {

Anytype/Sources/PresentationLayer/TextEditor/EditorPage/Views/Settings/ObjectActions/ObjectActionsViewModel.swift

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,54 @@ import UIKit
66
import DeepLinks
77

88
@MainActor
9-
final class ObjectActionsViewModel: ObservableObject {
9+
@Observable
10+
final class ObjectActionsViewModel {
1011

12+
@ObservationIgnored
1113
private let objectId: String
14+
@ObservationIgnored
1215
private let spaceId: String
16+
@ObservationIgnored
1317
private weak var output: (any ObjectActionsOutput)?
14-
18+
19+
@ObservationIgnored
1520
private lazy var document: any BaseDocumentProtocol = {
1621
openDocumentsProvider.document(objectId: objectId, spaceId: spaceId)
1722
}()
18-
23+
24+
@ObservationIgnored
1925
private lazy var widgetObject: (any BaseDocumentProtocol)? = {
2026
guard let info = workspaceStorage.spaceInfo(spaceId: spaceId) else {
2127
anytypeAssertionFailure("info not found")
2228
return nil
2329
}
2430
return openDocumentsProvider.document(objectId: info.widgetsId, spaceId: spaceId)
2531
}()
26-
27-
@Injected(\.objectActionsService)
32+
33+
@Injected(\.objectActionsService) @ObservationIgnored
2834
private var service: any ObjectActionsServiceProtocol
29-
@Injected(\.blockService)
35+
@Injected(\.blockService) @ObservationIgnored
3036
private var blockService: any BlockServiceProtocol
31-
@Injected(\.templatesService)
37+
@Injected(\.templatesService) @ObservationIgnored
3238
private var templatesService: any TemplatesServiceProtocol
33-
@Injected(\.documentsProvider)
39+
@Injected(\.documentsProvider) @ObservationIgnored
3440
private var documentsProvider: any DocumentsProviderProtocol
35-
@Injected(\.blockWidgetService)
41+
@Injected(\.blockWidgetService) @ObservationIgnored
3642
private var blockWidgetService: any BlockWidgetServiceProtocol
37-
@Injected(\.spaceViewsStorage)
43+
@Injected(\.spaceViewsStorage) @ObservationIgnored
3844
private var workspaceStorage: any SpaceViewsStorageProtocol
39-
@Injected(\.deepLinkParser)
45+
@Injected(\.deepLinkParser) @ObservationIgnored
4046
private var deepLinkParser: any DeepLinkParserProtocol
41-
@Injected(\.universalLinkParser)
47+
@Injected(\.universalLinkParser) @ObservationIgnored
4248
private var universalLinkParser: any UniversalLinkParserProtocol
43-
@Injected(\.openedDocumentProvider)
49+
@Injected(\.openedDocumentProvider) @ObservationIgnored
4450
private var openDocumentsProvider: any OpenedDocumentsProviderProtocol
45-
@Injected(\.workspaceService)
51+
@Injected(\.workspaceService) @ObservationIgnored
4652
private var workspaceService: any WorkspaceServiceProtocol
47-
48-
@Published var objectActions: [ObjectAction] = []
49-
@Published var toastData: ToastBarData?
50-
@Published var dismiss = false
53+
54+
var objectActions: [ObjectAction] = []
55+
var toastData: ToastBarData?
56+
var dismiss = false
5157

5258
init(objectId: String, spaceId: String, output: (any ObjectActionsOutput)?) {
5359
self.objectId = objectId

Anytype/Sources/PresentationLayer/TextEditor/EditorPage/Views/Settings/ObjectSettings/ObjectSettingsView.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import Services
33
import AnytypeCore
44

55
struct ObjectSettingsView: View {
6-
7-
@StateObject private var viewModel: ObjectSettingsViewModel
8-
6+
7+
@State private var viewModel: ObjectSettingsViewModel
8+
99
init(
1010
objectId: String,
1111
spaceId: String,
1212
output: some ObjectSettingsModelOutput
1313
) {
14-
self._viewModel = StateObject(wrappedValue: ObjectSettingsViewModel(objectId: objectId, spaceId: spaceId, output: output))
14+
self._viewModel = State(wrappedValue: ObjectSettingsViewModel(objectId: objectId, spaceId: spaceId, output: output))
1515
}
1616

1717
var body: some View {

Anytype/Sources/PresentationLayer/TextEditor/EditorPage/Views/Settings/ObjectSettings/ObjectSettingsViewModel.swift

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,32 @@ protocol ObjectSettingsModelOutput: AnyObject, ObjectHeaderRouterProtocol, Objec
2626
}
2727

2828
@MainActor
29-
final class ObjectSettingsViewModel: ObservableObject, ObjectActionsOutput {
29+
@Observable
30+
final class ObjectSettingsViewModel: ObjectActionsOutput {
3031

31-
@Injected(\.openedDocumentProvider)
32+
@Injected(\.openedDocumentProvider) @ObservationIgnored
3233
private var openDocumentsProvider: any OpenedDocumentsProviderProtocol
33-
@Injected(\.propertiesService)
34+
@Injected(\.propertiesService) @ObservationIgnored
3435
private var propertiesService: any PropertiesServiceProtocol
35-
@Injected(\.objectSettingsBuilder)
36+
@Injected(\.objectSettingsBuilder) @ObservationIgnored
3637
private var settingsBuilder: any ObjectSettingsBuilderProtocol
37-
@Injected(\.objectSettingsConflictManager)
38+
@Injected(\.objectSettingsConflictManager) @ObservationIgnored
3839
private var conflictManager: any ObjectSettingsPrimitivesConflictManagerProtocol
39-
40+
41+
@ObservationIgnored
4042
private weak var output: (any ObjectSettingsModelOutput)?
41-
43+
44+
@ObservationIgnored
4245
private lazy var document: any BaseDocumentProtocol = {
4346
openDocumentsProvider.document(objectId: objectId, spaceId: spaceId)
4447
}()
45-
48+
49+
@ObservationIgnored
4650
let objectId: String
51+
@ObservationIgnored
4752
let spaceId: String
48-
@Published var settings: [ObjectSetting] = []
49-
@Published var showConflictAlert = false
53+
var settings: [ObjectSetting] = []
54+
var showConflictAlert = false
5055

5156
init(
5257
objectId: String,

Anytype/Sources/PresentationLayer/TextEditor/EditorPage/Views/Settings/ObjectSettingsMenu/ObjectSettingsMenuView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import AnytypeCore
33

44
struct ObjectSettingsMenuView: View {
55

6-
@StateObject private var viewModel: ObjectSettingsMenuViewModel
6+
@State private var viewModel: ObjectSettingsMenuViewModel
77

88
init(
99
objectId: String,
@@ -12,7 +12,7 @@ struct ObjectSettingsMenuView: View {
1212
) {
1313
let settingsVM = ObjectSettingsViewModel(objectId: objectId, spaceId: spaceId, output: output)
1414
let actionsVM = ObjectActionsViewModel(objectId: objectId, spaceId: spaceId, output: settingsVM)
15-
self._viewModel = StateObject(wrappedValue: ObjectSettingsMenuViewModel(settingsViewModel: settingsVM, actionsViewModel: actionsVM))
15+
self._viewModel = State(wrappedValue: ObjectSettingsMenuViewModel(settingsViewModel: settingsVM, actionsViewModel: actionsVM))
1616
}
1717

1818
var body: some View {

Anytype/Sources/PresentationLayer/TextEditor/EditorPage/Views/Settings/ObjectSettingsMenu/ObjectSettingsMenuViewModel.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import Foundation
2-
import Combine
32
import SwiftUI
43

54
@MainActor
6-
final class ObjectSettingsMenuViewModel: ObservableObject {
5+
@Observable
6+
final class ObjectSettingsMenuViewModel {
77

8-
@Published var menuConfig = ObjectMenuConfiguration(sections: [])
8+
var menuConfig = ObjectMenuConfiguration(sections: [])
99

10+
@ObservationIgnored
1011
let settingsViewModel: ObjectSettingsViewModel
12+
@ObservationIgnored
1113
let actionsViewModel: ObjectActionsViewModel
12-
private var cancellables = Set<AnyCancellable>()
1314

1415
var showConflictAlert: Binding<Bool> {
1516
Binding(
@@ -42,17 +43,30 @@ final class ObjectSettingsMenuViewModel: ObservableObject {
4243
}
4344

4445
private func setupSubscriptions() {
45-
settingsViewModel.$settings
46-
.sink { [weak self] _ in
46+
observeSettings()
47+
observeActions()
48+
}
49+
50+
private func observeSettings() {
51+
withObservationTracking {
52+
_ = settingsViewModel.settings
53+
} onChange: { [weak self] in
54+
Task { @MainActor [weak self] in
4755
self?.rebuildMenu()
56+
self?.observeSettings()
4857
}
49-
.store(in: &cancellables)
58+
}
59+
}
5060

51-
actionsViewModel.$objectActions
52-
.sink { [weak self] _ in
61+
private func observeActions() {
62+
withObservationTracking {
63+
_ = actionsViewModel.objectActions
64+
} onChange: { [weak self] in
65+
Task { @MainActor [weak self] in
5366
self?.rebuildMenu()
67+
self?.observeActions()
5468
}
55-
.store(in: &cancellables)
69+
}
5670
}
5771

5872
private func rebuildMenu() {

0 commit comments

Comments
 (0)