Files
element-x-ios/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineMessageSelectionActionBar.swift
Mauro Romito 8ddd161625 Keep message selection active when every message is unselected
Unselecting the last message used to end the selection, closing it
without the user asking. Selection mode is now its own state: Forward
starts it and it only ends with the close button, once the messages are
forwarded, when the timeline changes or the feature is turned off. With
nothing selected the forward button stays visible but disabled.
2026-10-01 17:43:42 +02:00

51 lines
1.9 KiB
Swift

//
// Copyright 2026 Element Creations Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import Compound
import SwiftUI
/// Replaces the composer while messages are being selected, offering the action to take on them.
struct TimelineMessageSelectionActionBar: View {
@ObservedObject var context: TimelineViewModelType.Context
var body: some View {
Button {
context.send(viewAction: .forwardMessageSelection)
} label: {
Label(L10n.actionForwardMessages(context.viewState.messageSelection.count), icon: \.forward)
}
.buttonStyle(.compound(.primary))
.disabled(context.viewState.messageSelection.selectedEventIDs.isEmpty)
.padding(16)
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
}
}
// MARK: - Previews
struct TimelineMessageSelectionActionBar_Previews: PreviewProvider, TestablePreview {
static let viewModel = makeViewModel(selectedEventIDs: ["$1", "$2", "$3"])
static let emptyViewModel = makeViewModel(selectedEventIDs: [])
static var previews: some View {
TimelineMessageSelectionActionBar(context: viewModel.context)
.previewLayout(.sizeThatFits)
.previewDisplayName("Selected")
TimelineMessageSelectionActionBar(context: emptyViewModel.context)
.previewLayout(.sizeThatFits)
.previewDisplayName("Nothing selected")
}
static func makeViewModel(selectedEventIDs: Set<String>) -> TimelineViewModel {
let viewModel = TimelineViewModel.mock() // A fresh instance so the shared mock isn't left selecting.
viewModel.state.messageSelection.isActive = true
viewModel.state.messageSelection.selectedEventIDs = selectedEventIDs
return viewModel
}
}