From 5843c8a2465fc85be33bded180b786f61bff13ca Mon Sep 17 00:00:00 2001 From: Vova Ignatov Date: Wed, 15 Oct 2025 18:15:10 +0100 Subject: [PATCH] IOS-5160 Remove newSpaceMembersFlow toggle and keep only new flow --- .../ChatCoordinator/ChatCoordinatorView.swift | 3 - .../ChatCoordinatorViewModel.swift | 9 +- .../SpaceShareCoordinatorView.swift | 27 +- .../InviteLinkCoordinatorView.swift | 23 -- .../InviteLinkCoordinatorViewModel.swift | 24 -- .../Modules/InviteLink/InviteLinkView.swift | 110 -------- .../InviteLink/InviteLinkViewModel.swift | 137 --------- .../NewSpaceShare/Models/SpaceShareData.swift | 7 + .../Modules/SpaceShare/SpaceShareView.swift | 89 ------ .../SpaceShare/SpaceShareViewModel.swift | 267 ------------------ .../Generated/FeatureFlags+Flags.swift | 5 - .../FeatureDescription+Flags.swift | 8 +- 12 files changed, 18 insertions(+), 691 deletions(-) delete mode 100644 Anytype/Sources/PresentationLayer/Modules/InviteLink/Coordinator/InviteLinkCoordinatorView.swift delete mode 100644 Anytype/Sources/PresentationLayer/Modules/InviteLink/Coordinator/InviteLinkCoordinatorViewModel.swift delete mode 100644 Anytype/Sources/PresentationLayer/Modules/InviteLink/InviteLinkView.swift delete mode 100644 Anytype/Sources/PresentationLayer/Modules/InviteLink/InviteLinkViewModel.swift create mode 100644 Anytype/Sources/PresentationLayer/Modules/NewSpaceShare/Models/SpaceShareData.swift delete mode 100644 Anytype/Sources/PresentationLayer/Modules/SpaceShare/SpaceShareView.swift delete mode 100644 Anytype/Sources/PresentationLayer/Modules/SpaceShare/SpaceShareViewModel.swift diff --git a/Anytype/Sources/PresentationLayer/Flows/ChatCoordinator/ChatCoordinatorView.swift b/Anytype/Sources/PresentationLayer/Flows/ChatCoordinator/ChatCoordinatorView.swift index 801b9a7314..6a8ca994ed 100644 --- a/Anytype/Sources/PresentationLayer/Flows/ChatCoordinator/ChatCoordinatorView.swift +++ b/Anytype/Sources/PresentationLayer/Flows/ChatCoordinator/ChatCoordinatorView.swift @@ -60,9 +60,6 @@ struct ChatCoordinatorView: View { .anytypeSheet(isPresented: $model.showDisabledPushNotificationsAlert){ DisabledPushNotificationsAlertView() } - .anytypeSheet(item: $model.inviteLinkData) { data in - InviteLinkCoordinatorView(data: data) - } .sheet(item: $model.spaceShareData) { data in SpaceShareCoordinatorView(data: data) } diff --git a/Anytype/Sources/PresentationLayer/Flows/ChatCoordinator/ChatCoordinatorViewModel.swift b/Anytype/Sources/PresentationLayer/Flows/ChatCoordinator/ChatCoordinatorViewModel.swift index 9b7c7ae131..8e11be67e2 100644 --- a/Anytype/Sources/PresentationLayer/Flows/ChatCoordinator/ChatCoordinatorViewModel.swift +++ b/Anytype/Sources/PresentationLayer/Flows/ChatCoordinator/ChatCoordinatorViewModel.swift @@ -2,7 +2,6 @@ import Foundation import PhotosUI import SwiftUI import Services -import AnytypeCore struct ChatCoordinatorData: Hashable, Codable { let chatId: String @@ -30,7 +29,6 @@ final class ChatCoordinatorViewModel: ObservableObject, ChatModuleOutput { @Published var cameraData: SimpleCameraData? @Published var showSpaceSettingsData: AccountInfo? @Published var newLinkedObject: EditorScreenData? - @Published var inviteLinkData: SpaceShareData? @Published var spaceShareData: SpaceShareData? @Published var qrCodeInviteLink: URL? @@ -100,12 +98,7 @@ final class ChatCoordinatorViewModel: ObservableObject, ChatModuleOutput { } func onInviteLinkSelected() { - let data = SpaceShareData(spaceId: spaceId, route: .chat) - if FeatureFlags.newSpaceMembersFlow { - spaceShareData = data - } else { - inviteLinkData = data - } + spaceShareData = SpaceShareData(spaceId: spaceId, route: .chat) } func onShowQrCodeSelected(url: URL) { diff --git a/Anytype/Sources/PresentationLayer/Flows/SpaceShareCoordinator/SpaceShareCoordinatorView.swift b/Anytype/Sources/PresentationLayer/Flows/SpaceShareCoordinator/SpaceShareCoordinatorView.swift index 708ea8c723..5281994565 100644 --- a/Anytype/Sources/PresentationLayer/Flows/SpaceShareCoordinator/SpaceShareCoordinatorView.swift +++ b/Anytype/Sources/PresentationLayer/Flows/SpaceShareCoordinator/SpaceShareCoordinatorView.swift @@ -1,7 +1,6 @@ import Foundation import SwiftUI import Services -import AnytypeCore struct SpaceShareCoordinatorView: View { @@ -12,23 +11,15 @@ struct SpaceShareCoordinatorView: View { } var body: some View { - Group { - if FeatureFlags.newSpaceMembersFlow { - NewSpaceShareView(data: model.data, output: model) - } else { - SpaceShareView(data: model.data) { - model.onMoreInfoSelected() - } + NewSpaceShareView(data: model.data, output: model) + .sheet(isPresented: $model.showMoreInfo) { + SpaceMoreInfoView() + } + .sheet(item: $model.shareInviteLink) { link in + ActivityView(activityItems: [link]) + } + .anytypeSheet(item: $model.qrCodeInviteLink) { + QrCodeView(title: Loc.joinSpace, data: $0.absoluteString, analyticsType: .inviteSpace, route: .inviteLink) } - } - .sheet(isPresented: $model.showMoreInfo) { - SpaceMoreInfoView() - } - .sheet(item: $model.shareInviteLink) { link in - ActivityView(activityItems: [link]) - } - .anytypeSheet(item: $model.qrCodeInviteLink) { - QrCodeView(title: Loc.joinSpace, data: $0.absoluteString, analyticsType: .inviteSpace, route: .inviteLink) - } } } diff --git a/Anytype/Sources/PresentationLayer/Modules/InviteLink/Coordinator/InviteLinkCoordinatorView.swift b/Anytype/Sources/PresentationLayer/Modules/InviteLink/Coordinator/InviteLinkCoordinatorView.swift deleted file mode 100644 index f1f3889b7f..0000000000 --- a/Anytype/Sources/PresentationLayer/Modules/InviteLink/Coordinator/InviteLinkCoordinatorView.swift +++ /dev/null @@ -1,23 +0,0 @@ -import SwiftUI - -struct InviteLinkCoordinatorView: View { - - @StateObject private var model: InviteLinkCoordinatorViewModel - - init(data: SpaceShareData) { - self._model = StateObject(wrappedValue: InviteLinkCoordinatorViewModel(data: data)) - } - - var body: some View { - InviteLinkView( - data: model.data, - output: model - ) - .sheet(item: $model.shareInviteLink) { link in - ActivityView(activityItems: [link]) - } - .anytypeSheet(item: $model.qrCodeInviteLink) { - QrCodeView(title: Loc.SpaceShare.Qr.title, data: $0.absoluteString, analyticsType: .inviteSpace, route: .inviteLink) - } - } -} diff --git a/Anytype/Sources/PresentationLayer/Modules/InviteLink/Coordinator/InviteLinkCoordinatorViewModel.swift b/Anytype/Sources/PresentationLayer/Modules/InviteLink/Coordinator/InviteLinkCoordinatorViewModel.swift deleted file mode 100644 index be0481a2b8..0000000000 --- a/Anytype/Sources/PresentationLayer/Modules/InviteLink/Coordinator/InviteLinkCoordinatorViewModel.swift +++ /dev/null @@ -1,24 +0,0 @@ -import SwiftUI - -@MainActor -final class InviteLinkCoordinatorViewModel: ObservableObject, InviteLinkModuleOutput { - - let data: SpaceShareData - - @Published var shareInviteLink: URL? = nil - @Published var qrCodeInviteLink: URL? = nil - - init(data: SpaceShareData) { - self.data = data - } - - // MARK: - InviteLinkModuleOutput - - func shareInvite(url: URL) { - shareInviteLink = url - } - - func showQrCode(url: URL) { - qrCodeInviteLink = url - } -} diff --git a/Anytype/Sources/PresentationLayer/Modules/InviteLink/InviteLinkView.swift b/Anytype/Sources/PresentationLayer/Modules/InviteLink/InviteLinkView.swift deleted file mode 100644 index 86556cf88c..0000000000 --- a/Anytype/Sources/PresentationLayer/Modules/InviteLink/InviteLinkView.swift +++ /dev/null @@ -1,110 +0,0 @@ -import Foundation -import SwiftUI - -struct InviteLinkView: View { - - @StateObject private var model: InviteLinkViewModel - - init(data: SpaceShareData, output: (any InviteLinkModuleOutput)?) { - self._model = StateObject(wrappedValue: InviteLinkViewModel(data: data, output: output)) - } - - var body: some View { - Group { - if model.firstOpen { - loadingView - } else if model.shareLink.isNotNil { - linkContent - } else { - emptyLinkContent - } - } - .padding(20) - .background(Color.Background.secondary) - .cornerRadius(16, style: .continuous) - .shadow(radius: 16) - .task { - await model.startSubscription() - } - .anytypeSheet(item: $model.deleteLinkSpaceId) { - DeleteSharingLinkAlert(spaceId: $0.value) { - model.onDeleteLinkCompleted() - } - } - .snackbar(toastBarData: $model.toastBarData) - - } - - private var loadingView: some View { - VStack { - CircleLoadingView() - .frame(width: 32, height: 32) - } - .padding(30) - .frame(maxWidth: .infinity) - } - - private var linkContent: some View { - VStack(alignment: .leading, spacing: 0) { - HStack { - AnytypeText(Loc.SpaceShare.Invite.title, style: .uxTitle1Semibold) - .foregroundColor(.Text.primary) - Spacer() - Menu { - if model.canCopyInviteLink { - Button() { - model.onCopyInviteLink() - } label: { - Text(Loc.SpaceShare.CopyInviteLink.title) - } - } - Button(role: .destructive) { - model.onDeleteSharingLink() - } label: { - Text(Loc.SpaceShare.DeleteSharingLink.title) - } - .disabled(!model.canDeleteLink) - } label: { - IconView(icon: .asset(.X24.more)) - .frame(width: 24, height: 24) - } - .menuOrder(.fixed) - } - Spacer.fixedHeight(4) - Button { - model.onCopyLink() - } label: { - AnytypeText(model.shareLink?.absoluteString ?? "", style: .uxCalloutRegular) - .foregroundColor(.Text.secondary) - .lineLimit(1) - .frame(height: 48) - .newDivider() - } - Spacer.fixedHeight(10) - AnytypeText(model.description, style: .relation3Regular) - .foregroundColor(.Text.secondary) - Spacer.fixedHeight(20) - StandardButton(model.isStream ? Loc.SpaceShare.Share.link : Loc.SpaceShare.Invite.share, style: .primaryLarge) { - model.onShareInvite() - } - Spacer.fixedHeight(10) - StandardButton(Loc.SpaceShare.Qr.button, style: .secondaryLarge) { - model.onShowQrCode() - } - } - } - - private var emptyLinkContent: some View { - VStack(alignment: .leading, spacing: 0) { - AnytypeText(Loc.SpaceShare.Invite.title, style: .uxTitle1Semibold) - .foregroundColor(.Text.primary) - Spacer.fixedHeight(8) - AnytypeText(Loc.SpaceShare.Invite.empty, style: .calloutRegular) - .foregroundColor(.Text.primary) - Spacer.fixedHeight(12) - AsyncStandardButton(Loc.SpaceShare.Invite.generate, style: .primaryLarge) { - try await model.onGenerateInvite() - } - } - } -} diff --git a/Anytype/Sources/PresentationLayer/Modules/InviteLink/InviteLinkViewModel.swift b/Anytype/Sources/PresentationLayer/Modules/InviteLink/InviteLinkViewModel.swift deleted file mode 100644 index e2064057c0..0000000000 --- a/Anytype/Sources/PresentationLayer/Modules/InviteLink/InviteLinkViewModel.swift +++ /dev/null @@ -1,137 +0,0 @@ -import SwiftUI -import Services - -@MainActor -protocol InviteLinkModuleOutput: AnyObject { - func showQrCode(url: URL) - func shareInvite(url: URL) -} - -@MainActor -final class InviteLinkViewModel: ObservableObject { - - @Published var shareLink: URL? = nil - @Published var inviteLink: URL? = nil - @Published var canDeleteLink = false - @Published var canCopyInviteLink = false - @Published var deleteLinkSpaceId: StringIdentifiable? = nil - @Published var toastBarData: ToastBarData? - @Published var description = "" - - @Injected(\.participantSpacesStorage) - private var participantSpacesStorage: any ParticipantSpacesStorageProtocol - @Injected(\.workspaceStorage) - private var workspaceStorage: any WorkspacesStorageProtocol - @Injected(\.workspaceService) - private var workspaceService: any WorkspaceServiceProtocol - @Injected(\.universalLinkParser) - private var universalLinkParser: any UniversalLinkParserProtocol - - private let data: SpaceShareData - var spaceId: String { data.spaceId } - private var participantSpaceView: ParticipantSpaceViewData? - private weak var output: (any InviteLinkModuleOutput)? - - var isStream: Bool { participantSpaceView?.spaceView.uxType.isStream ?? false } - var firstOpen = true - - init(data: SpaceShareData, output: (any InviteLinkModuleOutput)?) { - self.data = data - self.output = output - } - - func startSubscription() async { - async let spaceViewSubscription: () = startSpaceViewTask() - (_) = await (spaceViewSubscription) - } - - private func getInvite() async { - defer { firstOpen = false } - AnytypeAnalytics.instance().logScreenSettingsSpaceShare(route: data.route) - do { - let invite = isStream ? try await workspaceService.getGuestInvite(spaceId: spaceId) : try await workspaceService.getCurrentInvite(spaceId: spaceId) - if isStream { - description = Loc.SpaceShare.Invite.Stream.description - } else { - description = Loc.SpaceShare.Invite.Description.part1 - if let withoutApprove = invite.inviteType?.withoutApprove, !withoutApprove { - description += ". " + Loc.SpaceShare.Invite.Description.part2 - } - } - shareLink = universalLinkParser.createUrl(link: .invite(cid: invite.cid, key: invite.fileKey)) - } catch {} - } - - private func startSpaceViewTask() async { - for await participantSpaceView in participantSpacesStorage.participantSpaceViewPublisher(spaceId: spaceId).values { - self.participantSpaceView = participantSpaceView - await updateView() - } - } - - func onGenerateInvite() async throws { - guard let spaceView = participantSpaceView?.spaceView else { return } - - AnytypeAnalytics.instance().logShareSpace() - - if !spaceView.isShared { - try await workspaceService.makeSharable(spaceId: spaceId) - } - - let invite = try await workspaceService.generateInvite(spaceId: spaceId) - shareLink = universalLinkParser.createUrl(link: .invite(cid: invite.cid, key: invite.fileKey)) - } - - func onDeleteSharingLink() { - AnytypeAnalytics.instance().logClickSettingsSpaceShare(type: .revoke) - deleteLinkSpaceId = spaceId.identifiable - } - - func onDeleteLinkCompleted() { - shareLink = nil - } - - func onCopyInviteLink() { - Task { - if inviteLink.isNil { - let invite = try await workspaceService.generateInvite(spaceId: spaceId) - inviteLink = universalLinkParser.createUrl(link: .invite(cid: invite.cid, key: invite.fileKey)) - } else { - let invite = try await workspaceService.getCurrentInvite(spaceId: spaceId) - inviteLink = universalLinkParser.createUrl(link: .invite(cid: invite.cid, key: invite.fileKey)) - } - AnytypeAnalytics.instance().logClickShareSpaceCopyLink(route: .menu) - UIPasteboard.general.string = inviteLink?.absoluteString - toastBarData = ToastBarData(Loc.copied) - } - } - - func onCopyLink() { - AnytypeAnalytics.instance().logClickShareSpaceCopyLink(route: .button) - UIPasteboard.general.string = shareLink?.absoluteString - toastBarData = ToastBarData(Loc.copied) - } - - func onShareInvite() { - AnytypeAnalytics.instance().logClickSettingsSpaceShare(type: .shareLink) - AnytypeAnalytics.instance().logClickShareSpaceShareLink(route: .membersScreen) - guard let shareLink else { return } - output?.shareInvite(url: shareLink) - } - - func onShowQrCode() { - AnytypeAnalytics.instance().logClickSettingsSpaceShare(type: .qr) - guard let shareLink else { return } - output?.showQrCode(url: shareLink) - } - - private func updateView() async { - guard let participantSpaceView else { return } - await getInvite() - canDeleteLink = participantSpaceView.permissions.canDeleteLink - canCopyInviteLink = participantSpaceView.spaceView.uxType.isStream - if !participantSpaceView.spaceView.isShared { - shareLink = nil - } - } -} diff --git a/Anytype/Sources/PresentationLayer/Modules/NewSpaceShare/Models/SpaceShareData.swift b/Anytype/Sources/PresentationLayer/Modules/NewSpaceShare/Models/SpaceShareData.swift new file mode 100644 index 0000000000..65f458dd30 --- /dev/null +++ b/Anytype/Sources/PresentationLayer/Modules/NewSpaceShare/Models/SpaceShareData.swift @@ -0,0 +1,7 @@ +import Foundation + +struct SpaceShareData: Identifiable, Hashable { + let spaceId: String + let route: SettingsSpaceShareRoute + var id: Int { hashValue } +} diff --git a/Anytype/Sources/PresentationLayer/Modules/SpaceShare/SpaceShareView.swift b/Anytype/Sources/PresentationLayer/Modules/SpaceShare/SpaceShareView.swift deleted file mode 100644 index f5915bf924..0000000000 --- a/Anytype/Sources/PresentationLayer/Modules/SpaceShare/SpaceShareView.swift +++ /dev/null @@ -1,89 +0,0 @@ -import Foundation -import SwiftUI -import Services - -struct SpaceShareView: View { - - @StateObject private var model: SpaceShareViewModel - - init(data: SpaceShareData, onMoreInfo: @escaping () -> Void) { - self._model = StateObject(wrappedValue: SpaceShareViewModel(data: data, onMoreInfo: onMoreInfo)) - } - - var body: some View { - content - .task { - await model.startParticipantsTask() - } - .task { - await model.startSpaceViewTask() - } - .snackbar(toastBarData: $model.toastBarData) - .anytypeSheet(item: $model.requestAlertModel) { alertModel in - SpaceRequestAlert(data: alertModel) { reason in - model.onUpgradeTap(reason: reason, route: .confirmInvite) - } - } - .anytypeSheet(item: $model.changeAccessAlertModel) { model in - SpaceChangeAccessView(model: model) - } - .anytypeSheet(item: $model.removeParticipantAlertModel) { model in - SpaceParticipantRemoveView(model: model) - } - .anytypeSheet(isPresented: $model.showStopSharingAlert) { - StopSharingAlert(spaceId: model.spaceId) {} - } - .anytypeSheet(item: $model.participantInfo) { - ProfileView(info: $0) - } - .membershipUpgrade(reason: $model.membershipUpgradeReason) - .ignoresSafeArea() - } - - private var content: some View { - VStack(spacing: 0) { - DragIndicator() - TitleView(title: Loc.SpaceShare.title) { - rightNavigationButton - } - - ZStack(alignment: .bottom) { - ScrollView { - VStack(spacing: 0) { - SectionHeaderView(title: Loc.SpaceShare.members) - if let reason = model.upgradeTooltipData { - SpaceShareUpgradeView(reason: reason) { - model.onUpgradeTap(reason: reason, route: .spaceSettings) - } - } - ForEach(model.rows) { participant in - SpaceShareParticipantView(participant: participant) - } - } - .padding(.horizontal, 16) - } - .safeAreaInset(edge: .bottom) { - InviteLinkCoordinatorView(data: model.data) - .padding(.horizontal, 16) - .padding(.vertical, 36) - } - } - } - .animation(.default, value: model.upgradeTooltipData) - } - - private var rightNavigationButton: some View { - Menu { - Button(Loc.moreInfo) { - model.onMoreInfoTap() - } - Button(Loc.SpaceShare.StopSharing.action, role: .destructive) { - model.onStopSharing() - } - .disabled(!model.canStopShare) - } label: { - IconView(icon: .asset(.X24.more)) - .frame(width: 24, height: 24) - } - } -} diff --git a/Anytype/Sources/PresentationLayer/Modules/SpaceShare/SpaceShareViewModel.swift b/Anytype/Sources/PresentationLayer/Modules/SpaceShare/SpaceShareViewModel.swift deleted file mode 100644 index 995c1d746d..0000000000 --- a/Anytype/Sources/PresentationLayer/Modules/SpaceShare/SpaceShareViewModel.swift +++ /dev/null @@ -1,267 +0,0 @@ -import Foundation -import Services -import UIKit -import DeepLinks -import Combine -import AnytypeCore - -struct SpaceShareData: Identifiable, Hashable { - let spaceId: String - let route: SettingsSpaceShareRoute - var id: Int { hashValue } -} - -@MainActor -final class SpaceShareViewModel: ObservableObject { - - @Injected(\.workspaceService) - private var workspaceService: any WorkspaceServiceProtocol - @Injected(\.universalLinkParser) - private var universalLinkParser: any UniversalLinkParserProtocol - @Injected(\.participantSpacesStorage) - private var participantSpacesStorage: any ParticipantSpacesStorageProtocol - @Injected(\.membershipStatusStorage) - private var membershipStatusStorage: any MembershipStatusStorageProtocol - @Injected(\.mailUrlBuilder) - private var mailUrlBuilder: any MailUrlBuilderProtocol - @Injected(\.workspaceStorage) - private var workspacesStorage: any WorkspacesStorageProtocol - - private lazy var participantsSubscription: any ParticipantsSubscriptionProtocol = Container.shared.participantSubscription(spaceId) - - private var onMoreInfo: () -> Void - private var participants: [Participant] = [] - private var participantSpaceView: ParticipantSpaceViewData? - private var canChangeWriterToReader = false - private var canChangeReaderToWriter = false - - let data: SpaceShareData - var spaceId: String { data.spaceId } - - @Published var rows: [SpaceShareParticipantViewModel] = [] - @Published var toastBarData: ToastBarData? - @Published var requestAlertModel: SpaceRequestAlertData? - @Published var changeAccessAlertModel: SpaceChangeAccessViewModel? - @Published var removeParticipantAlertModel: SpaceParticipantRemoveViewModel? - @Published var showStopSharingAlert = false - @Published var showUpgradeBadge = false - @Published var canStopShare = false - @Published var canDeleteLink = false - @Published var canRemoveMember = false - @Published var canApproveRequests = false - @Published var upgradeTooltipData: MembershipParticipantUpgradeReason? - @Published var membershipUpgradeReason: MembershipUpgradeReason? - @Published var participantInfo: ObjectInfo? - - init(data: SpaceShareData, onMoreInfo: @escaping () -> Void) { - self.data = data - self.onMoreInfo = onMoreInfo - } - - func startParticipantsTask() async { - for await items in participantsSubscription.withoutRemovingParticipantsPublisher.values { - participants = items.sorted { $0.sortingWeight > $1.sortingWeight } - updateView() - } - } - - func startSpaceViewTask() async { - for await participantSpaceView in participantSpacesStorage.participantSpaceViewPublisher(spaceId: spaceId).values { - self.participantSpaceView = participantSpaceView - updateView() - } - } - - func onStopSharing() { - showStopSharingAlert = true - } - - func onMoreInfoTap() { - AnytypeAnalytics.instance().logClickSettingsSpaceShare(type: .moreInfo) - onMoreInfo() - } - - func onUpgradeTap(reason: MembershipParticipantUpgradeReason, route: ClickUpgradePlanTooltipRoute) { - onUpgradeTap(reason: MembershipUpgradeReason(participantReason: reason), route: route) - } - - func onUpgradeTap(reason: MembershipUpgradeReason, route: ClickUpgradePlanTooltipRoute) { - AnytypeAnalytics.instance().logClickUpgradePlanTooltip(type: reason.analyticsType, route: route) - membershipUpgradeReason = reason - } - - // MARK: - Private - - private func updateView() { - let workspaceInfo = workspacesStorage.workspaceInfo(spaceId: spaceId) - guard let participantSpaceView, let workspaceInfo else { return } - - canStopShare = participantSpaceView.canStopSharing - canChangeReaderToWriter = participantSpaceView.permissions.canEditPermissions - && participantSpaceView.spaceView.canChangeReaderToWriter(participants: participants) - canChangeWriterToReader = participantSpaceView.permissions.canEditPermissions - && participantSpaceView.spaceView.canChangeWriterToReader(participants: participants) - canRemoveMember = participantSpaceView.permissions.canEditPermissions - canDeleteLink = participantSpaceView.permissions.canDeleteLink - canApproveRequests = participantSpaceView.permissions.canApproveRequests - - updateUpgradeViewState() - - rows = participants.map { participant in - let isYou = workspaceInfo.profileObjectID == participant.identityProfileLink - return SpaceShareParticipantViewModel( - id: participant.id, - icon: participant.icon?.icon, - name: isYou ? Loc.SpaceShare.youSuffix(participant.title) : participant.title, - globalName: participant.displayGlobalName, - status: participantStatus(participant), - action: participantAction(participant), - contextActions: participantContextActions(participant) - ) - } - } - - private func updateUpgradeViewState() { - guard let participantSpaceView else { return } - - let canAddReaders = participantSpaceView.spaceView.canAddReaders(participants: participants) - let canAddWriters = participantSpaceView.spaceView.canAddWriters(participants: participants) - let haveJoiningParticipants = participants.contains { $0.status == .joining } - - - if !canAddReaders && haveJoiningParticipants { - upgradeTooltipData = .numberOfSpaceReaders - } else if !canAddWriters { - upgradeTooltipData = .numberOfSpaceEditors - } else { - upgradeTooltipData = nil - } - } - - private func participantStatus(_ participant: Participant) -> SpaceShareParticipantViewModel.Status? { - switch participant.status { - case .active: - return .active(permission: participant.permission.title) - case .joining: - return .pending(message: Loc.SpaceShare.joinRequest) - case .removing: - return .pending(message: Loc.SpaceShare.leaveRequest) - case .declined, .canceled, .removed, .UNRECOGNIZED: - return nil - } - } - - private func participantAction(_ participant: Participant) -> SpaceShareParticipantViewModel.Action? { - switch participant.status { - case .joining: - guard canApproveRequests else { return nil } - return SpaceShareParticipantViewModel.Action(title: Loc.SpaceShare.Action.viewRequest, action: { [weak self] in - self?.showRequestAlert(participant: participant) - }) - case .removing: - guard canApproveRequests else { return nil } - return SpaceShareParticipantViewModel.Action(title: Loc.SpaceShare.Action.approve, action: { [weak self] in - AnytypeAnalytics.instance().logApproveLeaveRequest() - try await self?.workspaceService.leaveApprove(spaceId: participant.spaceId, identity: participant.identity) - self?.toastBarData = ToastBarData(Loc.SpaceShare.Approve.toast(participant.title)) - }) - case .active: - return SpaceShareParticipantViewModel.Action(title: nil, action: { [weak self] in - self?.showParticipantInfo(participant) - }) - case .canceled, .declined, .removed, .UNRECOGNIZED: - return nil - } - } - - private func participantContextActions(_ participant: Participant) -> [SpaceShareParticipantViewModel.ContextAction] { - guard participant.permission != .owner, participant.status == .active else { return [] } - return [ - SpaceShareParticipantViewModel.ContextAction( - title: Loc.SpaceShare.Permissions.reader, - isSelected: participant.permission == .reader, - destructive: false, - enabled: canChangeWriterToReader || participant.permission == .reader, - action: { [weak self] in - self?.showPermissionAlert(participant: participant, newPermission: .reader) - } - ), - SpaceShareParticipantViewModel.ContextAction( - title: Loc.SpaceShare.Permissions.writer, - isSelected: participant.permission == .writer, - destructive: false, - enabled: canChangeReaderToWriter || participant.permission == .writer, - action: { [weak self] in - self?.showPermissionAlert(participant: participant, newPermission: .writer) - } - ), - SpaceShareParticipantViewModel.ContextAction( - title: Loc.SpaceShare.RemoveMember.title, - isSelected: false, - destructive: true, - enabled: canRemoveMember, - action: { [weak self] in - self?.showRemoveAlert(participant: participant) - } - ) - ] - } - - private func showRequestAlert(participant: Participant) { - guard let spaceView = participantSpaceView?.spaceView else { return } - - requestAlertModel = SpaceRequestAlertData( - spaceId: spaceView.targetSpaceId, - spaceName: spaceView.title, - participantIdentity: participant.identity, - participantName: participant.title, - participantIcon: participant.icon, - route: .settings - ) - } - - private func showPermissionAlert(participant: Participant, newPermission: ParticipantPermissions) { - guard participant.permission != newPermission else { return } - changeAccessAlertModel = SpaceChangeAccessViewModel( - participantName: participant.title, - permissions: newPermission.title, - onConfirm: { [weak self] in - AnytypeAnalytics.instance().logChangeSpaceMemberPermissions(type: newPermission.analyticsType) - try await self?.workspaceService.participantPermissionsChange( - spaceId: participant.spaceId, - identity: participant.identity, - permissions: newPermission - ) - self?.toastBarData = ToastBarData(Loc.SpaceShare.accessChanged, type: .success) - } - ) - } - - private func showRemoveAlert(participant: Participant) { - removeParticipantAlertModel = SpaceParticipantRemoveViewModel( - participantName: participant.title, - onConfirm: { [weak self] in - AnytypeAnalytics.instance().logRemoveSpaceMember() - try await self?.workspaceService.participantRemove(spaceId: participant.spaceId, identity: participant.identity) - } - ) - } - - private func showParticipantInfo(_ participant: Participant) { - participantInfo = ObjectInfo(objectId: participant.id, spaceId: participant.spaceId) - } -} - -private extension Participant { - var sortingWeight: Int { - if status == .joining { - return 3 - } - - if status == .removing { - return 2 - } - - return 1 - } -} diff --git a/Modules/AnytypeCore/AnytypeCore/Generated/FeatureFlags+Flags.swift b/Modules/AnytypeCore/AnytypeCore/Generated/FeatureFlags+Flags.swift index 63ae3cbebf..fffa4157f2 100644 --- a/Modules/AnytypeCore/AnytypeCore/Generated/FeatureFlags+Flags.swift +++ b/Modules/AnytypeCore/AnytypeCore/Generated/FeatureFlags+Flags.swift @@ -18,10 +18,6 @@ public extension FeatureFlags { value(for: .swipeToReply) } - static var newSpaceMembersFlow: Bool { - value(for: .newSpaceMembersFlow) - } - static var removeMessagesFromNotificationsCenter: Bool { value(for: .removeMessagesFromNotificationsCenter) } @@ -139,7 +135,6 @@ public extension FeatureFlags { .muteSpacePossibility, .addNotificationsSettings, .swipeToReply, - .newSpaceMembersFlow, .removeMessagesFromNotificationsCenter, .mediaCarouselForWidgets, .fixCollectionViewReuseCrashInEditor, diff --git a/Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift b/Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift index 7f9600d166..623e51fe93 100644 --- a/Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift +++ b/Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift @@ -21,13 +21,7 @@ public extension FeatureDescription { type: .feature(author: "joe_pusya@anytype.io", releaseVersion: "13"), defaultValue: true ) - - static let newSpaceMembersFlow = FeatureDescription( - title: "New Space Members Flow", - type: .feature(author: "vova@anytype.io", releaseVersion: "13"), - defaultValue: true - ) - + static let removeMessagesFromNotificationsCenter = FeatureDescription( title: "Remove messages from NotificationsCenter", type: .feature(author: "joe_pusya@anytype.io", releaseVersion: "13"),