Skip to content

Commit 0622bea

Browse files
authored
Merge pull request #4184 from anyproto/ios-5388-migrate-chat-coordinator-chat-view-to-observable-2
IOS-5388 Core | Migrate chat view to @observable
2 parents 49f6152 + fd9691b commit 0622bea

File tree

2 files changed

+83
-63
lines changed

2 files changed

+83
-63
lines changed

Anytype/Sources/PresentationLayer/Modules/Chat/ChatView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import AnytypeCore
44

55
struct ChatView: View {
66

7-
@StateObject private var model: ChatViewModel
7+
@State private var model: ChatViewModel
88
@State private var actionState = ChatActionOverlayState()
99
@Environment(\.keyboardDismiss) private var keyboardDismiss
1010
@Environment(\.chatActionProvider) private var chatActionProvider
1111

1212
init(spaceId: String, chatId: String, output: (any ChatModuleOutput)?) {
13-
self._model = StateObject(wrappedValue: ChatViewModel(spaceId: spaceId, chatId: chatId, output: output))
13+
self._model = State(wrappedValue: ChatViewModel(spaceId: spaceId, chatId: chatId, output: output))
1414
}
1515

1616
var body: some View {

Anytype/Sources/PresentationLayer/Modules/Chat/ChatViewModel.swift

Lines changed: 81 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,51 @@ import ProtobufMessages
1010
@preconcurrency import Combine
1111

1212
@MainActor
13-
final class ChatViewModel: ObservableObject, MessageModuleOutput, ChatActionProviderHandler {
13+
@Observable
14+
final class ChatViewModel: MessageModuleOutput, ChatActionProviderHandler {
1415

1516
// MARK: - DI
1617

1718
let spaceId: String
1819
let chatId: String
20+
@ObservationIgnored
1921
private weak var output: (any ChatModuleOutput)?
2022

21-
@Injected(\.blockService)
23+
@Injected(\.blockService) @ObservationIgnored
2224
private var blockService: any BlockServiceProtocol
23-
@Injected(\.participantsStorage)
25+
@Injected(\.participantsStorage) @ObservationIgnored
2426
private var accountParticipantsStorage: any ParticipantsStorageProtocol
25-
@Injected(\.mentionObjectsService)
27+
@Injected(\.mentionObjectsService) @ObservationIgnored
2628
private var mentionObjectsService: any MentionObjectsServiceProtocol
27-
@Injected(\.chatActionService)
29+
@Injected(\.chatActionService) @ObservationIgnored
2830
private var chatActionService: any ChatActionServiceProtocol
29-
@Injected(\.fileActionsService)
31+
@Injected(\.fileActionsService) @ObservationIgnored
3032
private var fileActionsService: any FileActionsServiceProtocol
31-
@Injected(\.chatService)
33+
@Injected(\.chatService) @ObservationIgnored
3234
private var chatService: any ChatServiceProtocol
33-
@Injected(\.chatInputConverter)
35+
@Injected(\.chatInputConverter) @ObservationIgnored
3436
private var chatInputConverter: any ChatInputConverterProtocol
35-
@Injected(\.chatMessageLimits)
37+
@Injected(\.chatMessageLimits) @ObservationIgnored
3638
private var chatMessageLimits: any ChatMessageLimitsProtocol
37-
@Injected(\.messageTextBuilder)
39+
@Injected(\.messageTextBuilder) @ObservationIgnored
3840
private var messageTextBuilder: any MessageTextBuilderProtocol
39-
@Injected(\.searchService)
41+
@Injected(\.searchService) @ObservationIgnored
4042
private var searchService: any SearchServiceProtocol
41-
@Injected(\.objectTypeProvider)
43+
@Injected(\.objectTypeProvider) @ObservationIgnored
4244
private var objectTypeProvider: any ObjectTypeProviderProtocol
43-
@Injected(\.iconColorService)
45+
@Injected(\.iconColorService) @ObservationIgnored
4446
private var iconColorService: any IconColorServiceProtocol
45-
@Injected(\.bookmarkService)
47+
@Injected(\.bookmarkService) @ObservationIgnored
4648
private var bookmarkService: any BookmarkServiceProtocol
47-
@Injected(\.participantSpacesStorage)
49+
@Injected(\.participantSpacesStorage) @ObservationIgnored
4850
private var participantSpacesStorage: any ParticipantSpacesStorageProtocol
49-
@Injected(\.pushNotificationsAlertHandler)
51+
@Injected(\.pushNotificationsAlertHandler) @ObservationIgnored
5052
private var pushNotificationsAlertHandler: any PushNotificationsAlertHandlerProtocol
51-
@Injected(\.notificationsCenterService)
53+
@Injected(\.notificationsCenterService) @ObservationIgnored
5254
private var notificationsCenterService: any NotificationsCenterServiceProtocol
53-
@Injected(\.workspaceService)
55+
@Injected(\.workspaceService) @ObservationIgnored
5456
private var workspaceService: any WorkspaceServiceProtocol
55-
@Injected(\.universalLinkParser)
57+
@Injected(\.universalLinkParser) @ObservationIgnored
5658
private var universalLinkParser: any UniversalLinkParserProtocol
5759

5860
private let participantSubscription: any ParticipantsSubscriptionProtocol
@@ -65,64 +67,75 @@ final class ChatViewModel: ObservableObject, MessageModuleOutput, ChatActionProv
6567

6668
// Global
6769

68-
@Published var dataLoaded = false
69-
@Published var canEdit = false
70-
@Published var qrCodeInviteUrl: URL?
70+
var dataLoaded = false
71+
var canEdit = false
72+
var qrCodeInviteUrl: URL?
73+
@ObservationIgnored
7174
var keyboardDismiss: KeyboardDismiss?
7275

7376
// Input Message
7477

75-
@Published var message = NSAttributedString()
76-
@Published var inputFocused = false
77-
@Published var replyToMessage: ChatInputReplyModel?
78-
@Published var editMessage: ChatMessage?
79-
@Published var sendMessageTaskInProgress: Bool = false
80-
@Published var sendButtonIsLoading: Bool = false
81-
@Published var messageTextLimit: String?
82-
@Published var textLimitReached = false
83-
@Published var typesForCreateObject: [ObjectType] = []
84-
@Published var participantSpaceView: ParticipantSpaceViewData?
78+
var message = NSAttributedString()
79+
var inputFocused = false
80+
var replyToMessage: ChatInputReplyModel?
81+
var editMessage: ChatMessage?
82+
var sendMessageTaskInProgress: Bool = false
83+
var sendButtonIsLoading: Bool = false
84+
var messageTextLimit: String?
85+
var textLimitReached = false
86+
var typesForCreateObject: [ObjectType] = []
87+
var participantSpaceView: ParticipantSpaceViewData?
8588

8689
// Actions
87-
@Published var actionModel: ChatActionPanelModel = .hidden
90+
var actionModel: ChatActionPanelModel = .hidden
8891

8992
// Attachment Handler
9093
let attachmentHandler: any ChatAttachmentHandlerProtocol
9194

9295
// Attachment Handler Published State
93-
@Published var linkedObjects: [ChatLinkedObject] = []
94-
@Published var attachmentsDownloading: Bool = false
95-
@Published var photosItemsTask = UUID()
96+
var linkedObjects: [ChatLinkedObject] = []
97+
var attachmentsDownloading: Bool = false
98+
var photosItemsTask = UUID()
9699

97100
// List
98101

99-
@Published var mentionSearchState = ChatTextMention.finish
100-
@Published var mesageBlocks: [MessageSectionData] = []
101-
@Published var mentionObjectsModels: [MentionObjectModel] = []
102-
@Published var collectionViewScrollProxy = ChatCollectionScrollProxy()
103-
@Published var messageYourBackgroundColor: Color = .Background.Chat.bubbleYour
104-
@Published var messageHiglightId: String = ""
102+
var mentionSearchState = ChatTextMention.finish
103+
var mesageBlocks: [MessageSectionData] = []
104+
var mentionObjectsModels: [MentionObjectModel] = []
105+
var collectionViewScrollProxy = ChatCollectionScrollProxy()
106+
var messageYourBackgroundColor: Color = .Background.Chat.bubbleYour
107+
var messageHiglightId: String = ""
105108

109+
@ObservationIgnored
106110
private var messages: [FullChatMessage] = []
111+
@ObservationIgnored
107112
private var chatState: ChatState?
113+
@ObservationIgnored
108114
private var participants: [Participant] = []
115+
@ObservationIgnored
109116
private var firstUnreadMessageOrderId: String?
117+
@ObservationIgnored
110118
private var bottomVisibleOrderId: String?
119+
@ObservationIgnored
111120
private var bigDistanceToBottom: Bool = false
121+
@ObservationIgnored
112122
private var forceHiddenActionPanel: Bool = true
123+
@ObservationIgnored
113124
private var showScreenLogged = false
114-
125+
@ObservationIgnored
115126
var showEmptyState: Bool { mesageBlocks.isEmpty && dataLoaded }
127+
@ObservationIgnored
116128
var conversationType: ConversationType {
117129
participantSpaceView?.spaceView.uxType.asConversationType ?? .chat
118130
}
131+
@ObservationIgnored
119132
var participantPermissions: ParticipantPermissions? { participantSpaceView?.participant?.permission }
120133

121134
// Alerts
122135

123-
@Published var deleteMessageConfirmation: MessageViewData?
124-
@Published var showSendLimitAlert = false
125-
@Published var toastBarData: ToastBarData?
136+
var deleteMessageConfirmation: MessageViewData?
137+
var showSendLimitAlert = false
138+
var toastBarData: ToastBarData?
126139

127140
init(spaceId: String, chatId: String, output: (any ChatModuleOutput)?) {
128141
self.spaceId = spaceId
@@ -134,20 +147,6 @@ final class ChatViewModel: ObservableObject, MessageModuleOutput, ChatActionProv
134147
// Open object. Middleware will know that we are using the object and will be make a refresh after open from background
135148
self.chatObject = openDocumentProvider.document(objectId: chatId, spaceId: spaceId)
136149
self.attachmentHandler = ChatAttachmentHandler(spaceId: spaceId)
137-
138-
setupAttachmentHandler()
139-
}
140-
141-
private func setupAttachmentHandler() {
142-
// Subscribe to attachment handler publishers
143-
attachmentHandler.linkedObjectsPublisher
144-
.assign(to: &$linkedObjects)
145-
146-
attachmentHandler.attachmentsDownloadingPublisher
147-
.assign(to: &$attachmentsDownloading)
148-
149-
attachmentHandler.photosItemsTaskPublisher
150-
.assign(to: &$photosItemsTask)
151150
}
152151

153152
func onAppear() {
@@ -231,8 +230,11 @@ final class ChatViewModel: ObservableObject, MessageModuleOutput, ChatActionProv
231230
async let typesSub: () = subscribeOnTypes()
232231
async let messageBackgroundSub: () = subscribeOnMessageBackground()
233232
async let spaceViewSub: () = subscribeOnSpaceView()
233+
async let linkedObjectsSub: () = subscribeOnLinkedObjects()
234+
async let attachmentsDownloadingSub: () = subscribeOnAttachmentsDownloading()
235+
async let photosItemsTaskSub: () = subscribeOnPhotosItemsTask()
234236

235-
(_, _, _, _, _) = await (permissionsSub, participantsSub, typesSub, messageBackgroundSub, spaceViewSub)
237+
_ = await (permissionsSub, participantsSub, typesSub, messageBackgroundSub, spaceViewSub, linkedObjectsSub, attachmentsDownloadingSub, photosItemsTaskSub)
236238
}
237239

238240
func subscribeOnMessages() async throws {
@@ -650,6 +652,24 @@ final class ChatViewModel: ObservableObject, MessageModuleOutput, ChatActionProv
650652
await handlePushNotificationsAlert()
651653
}
652654
}
655+
656+
private func subscribeOnLinkedObjects() async {
657+
for await linkedObjects in attachmentHandler.linkedObjectsPublisher.values {
658+
self.linkedObjects = linkedObjects
659+
}
660+
}
661+
662+
private func subscribeOnAttachmentsDownloading() async {
663+
for await attachmentsDownloading in attachmentHandler.attachmentsDownloadingPublisher.values {
664+
self.attachmentsDownloading = attachmentsDownloading
665+
}
666+
}
667+
668+
private func subscribeOnPhotosItemsTask() async {
669+
for await photosItemsTask in attachmentHandler.photosItemsTaskPublisher.values {
670+
self.photosItemsTask = photosItemsTask
671+
}
672+
}
653673

654674
func updateInviteState() async {
655675
do {

0 commit comments

Comments
 (0)