From 599e4c406e47dcb2b58a824c434de68ea62bd0ff Mon Sep 17 00:00:00 2001 From: Vova Ignatov Date: Wed, 15 Oct 2025 13:03:08 +0100 Subject: [PATCH] IOS-5356 Add invite members button to chat navbar --- .../Modules/Chat/ChatView.swift | 13 ++++-- .../Subviews/ChatHeader/ChatHeaderView.swift | 42 ++++++++++++++----- .../ChatHeader/ChatHeaderViewModel.swift | 36 ++++++++++------ 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/Anytype/Sources/PresentationLayer/Modules/Chat/ChatView.swift b/Anytype/Sources/PresentationLayer/Modules/Chat/ChatView.swift index 576f33d78a..501d2d49e6 100644 --- a/Anytype/Sources/PresentationLayer/Modules/Chat/ChatView.swift +++ b/Anytype/Sources/PresentationLayer/Modules/Chat/ChatView.swift @@ -20,9 +20,16 @@ struct ChatView: View { .ignoresSafeArea() } .overlay(alignment: .top) { - ChatHeaderView(spaceId: model.spaceId, chatId: model.chatId) { - model.onTapWidgets() - } + ChatHeaderView( + spaceId: model.spaceId, + chatId: model.chatId, + onTapOpenWidgets: { + model.onTapWidgets() + }, + onTapAddMembers: { + model.onTapInviteLink() + } + ) } .onAppear { model.keyboardDismiss = keyboardDismiss diff --git a/Anytype/Sources/PresentationLayer/Modules/Chat/Subviews/ChatHeader/ChatHeaderView.swift b/Anytype/Sources/PresentationLayer/Modules/Chat/Subviews/ChatHeader/ChatHeaderView.swift index 0c71c65533..e8dbdf684d 100644 --- a/Anytype/Sources/PresentationLayer/Modules/Chat/Subviews/ChatHeader/ChatHeaderView.swift +++ b/Anytype/Sources/PresentationLayer/Modules/Chat/Subviews/ChatHeader/ChatHeaderView.swift @@ -1,12 +1,23 @@ import Foundation import SwiftUI +import Services struct ChatHeaderView: View { - + @StateObject private var model: ChatHeaderViewModel - - init(spaceId: String, chatId: String, onTapOpenWidgets: @escaping () -> Void) { - self._model = StateObject(wrappedValue: ChatHeaderViewModel(spaceId: spaceId, chatId: chatId, onTapOpenWidgets: onTapOpenWidgets)) + + init( + spaceId: String, + chatId: String, + onTapOpenWidgets: @escaping () -> Void, + onTapAddMembers: @escaping (() -> Void) + ) { + self._model = StateObject(wrappedValue: ChatHeaderViewModel( + spaceId: spaceId, + chatId: chatId, + onTapOpenWidgets: onTapOpenWidgets, + onTapAddMembers: onTapAddMembers + )) } var body: some View { @@ -33,12 +44,23 @@ struct ChatHeaderView: View { } } } rightView: { - if model.showWidgetsButton { - IncreaseTapButton { - model.tapOpenWidgets() - } label: { - IconView(icon: model.icon) - .frame(width: 28, height: 28) + HStack(spacing: 16) { + if model.showAddMembersButton { + IncreaseTapButton { + model.tapAddMembers() + } label: { + Image(systemName: "person.fill.badge.plus") + .foregroundColor(.Control.transparentSecondary) + .frame(width: 28, height: 28) + } + } + if model.showWidgetsButton { + IncreaseTapButton { + model.tapOpenWidgets() + } label: { + IconView(icon: model.icon) + .frame(width: 28, height: 28) + } } } } diff --git a/Anytype/Sources/PresentationLayer/Modules/Chat/Subviews/ChatHeader/ChatHeaderViewModel.swift b/Anytype/Sources/PresentationLayer/Modules/Chat/Subviews/ChatHeader/ChatHeaderViewModel.swift index 6156a87a2a..4a10b7b02f 100644 --- a/Anytype/Sources/PresentationLayer/Modules/Chat/Subviews/ChatHeader/ChatHeaderViewModel.swift +++ b/Anytype/Sources/PresentationLayer/Modules/Chat/Subviews/ChatHeader/ChatHeaderViewModel.swift @@ -6,33 +6,41 @@ import AnytypeCore @MainActor final class ChatHeaderViewModel: ObservableObject { - + @Injected(\.workspaceStorage) private var workspaceStorage: any WorkspacesStorageProtocol @Injected(\.syncStatusStorage) private var syncStatusStorage: any SyncStatusStorageProtocol + @Injected(\.participantSpacesStorage) + private var participantSpacesStorage: any ParticipantSpacesStorageProtocol private let openDocumentProvider: any OpenedDocumentsProviderProtocol = Container.shared.openedDocumentProvider() - + @Published var title: String? @Published var icon: Icon? @Published var showWidgetsButton: Bool = false @Published var chatLoading = false @Published var spaceLoading = false @Published var muted = false - - var showLoading: Bool { - chatLoading || spaceLoading - } - + @Published var showAddMembersButton: Bool = false + + var showLoading: Bool { chatLoading || spaceLoading } + private let spaceId: String private let chatId: String private let onTapOpenWidgets: () -> Void + private let onTapAddMembers: (() -> Void) private let chatObject: any BaseDocumentProtocol - - init(spaceId: String, chatId: String, onTapOpenWidgets: @escaping () -> Void) { + + init( + spaceId: String, + chatId: String, + onTapOpenWidgets: @escaping () -> Void, + onTapAddMembers: @escaping (() -> Void) + ) { self.spaceId = spaceId self.chatId = chatId self.onTapOpenWidgets = onTapOpenWidgets + self.onTapAddMembers = onTapAddMembers self.chatObject = openDocumentProvider.document(objectId: chatId, spaceId: spaceId) } @@ -44,18 +52,20 @@ final class ChatHeaderViewModel: ObservableObject { _ = await (spaceViewSub, chatSub, spaceStatusSub) } - func tapOpenWidgets() { - onTapOpenWidgets() - } + func tapOpenWidgets() { onTapOpenWidgets() } + + func tapAddMembers() { onTapAddMembers() } // MARK: - Private private func subscribeOnSpaceView() async { - for await spaceView in workspaceStorage.spaceViewPublisher(spaceId: spaceId).values { + for await participantSpaceView in participantSpacesStorage.participantSpaceViewPublisher(spaceId: spaceId).values { + let spaceView = participantSpaceView.spaceView title = spaceView.title icon = spaceView.objectIconImage showWidgetsButton = spaceView.chatId == chatId && spaceView.initialScreenIsChat muted = FeatureFlags.muteSpacePossibility && !spaceView.pushNotificationMode.isUnmutedAll + showAddMembersButton = participantSpaceView.participant?.permission == .owner } }