mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-01 09:42:39 +00:00
f040964d3f
This will send the item to the rooms in order they were chosen and only deep link into the target room if single, otherwise it will just dismiss the forwarding screen after sending.
110 lines
4.2 KiB
Swift
110 lines
4.2 KiB
Swift
//
|
|
// Copyright 2025 Element Creations Ltd.
|
|
// Copyright 2022-2025 New Vector 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
|
|
|
|
struct MessageForwardingScreen: View {
|
|
@ObservedObject var context: MessageForwardingScreenViewModel.Context
|
|
|
|
var body: some View {
|
|
Form {
|
|
Section {
|
|
ForEach(context.viewState.rooms) { room in
|
|
MessageForwardingListRow(room: room,
|
|
isSelected: context.viewState.selectedRoomIDs.contains(room.id),
|
|
context: context)
|
|
}
|
|
// Replace these with ScrollView's `scrollPosition` when dropping iOS 16.
|
|
} header: {
|
|
emptyRectangle
|
|
.onAppear {
|
|
context.send(viewAction: .reachedTop)
|
|
}
|
|
} footer: {
|
|
emptyRectangle
|
|
.onAppear {
|
|
context.send(viewAction: .reachedBottom)
|
|
}
|
|
}
|
|
}
|
|
.compoundList()
|
|
.navigationTitle(L10n.commonForwardMessage)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .cancellationAction) {
|
|
Button(L10n.actionCancel) {
|
|
context.send(viewAction: .cancel)
|
|
}
|
|
}
|
|
ToolbarItem(placement: .confirmationAction) {
|
|
Button(L10n.actionSend) {
|
|
context.send(viewAction: .send)
|
|
}
|
|
.disabled(context.viewState.selectedRoomIDs.isEmpty)
|
|
}
|
|
}
|
|
.searchController(query: $context.searchQuery, showsCancelButton: false)
|
|
.compoundSearchField()
|
|
.disableAutocorrection(true)
|
|
}
|
|
|
|
/// The greedy size of Rectangle can create an issue with the navigation bar when the search is highlighted, so is best to use a fixed frame instead of hidden() or EmptyView()
|
|
private var emptyRectangle: some View {
|
|
Rectangle()
|
|
.frame(width: 0, height: 0)
|
|
.accessibilityHidden(true)
|
|
}
|
|
}
|
|
|
|
private struct MessageForwardingListRow: View {
|
|
@Environment(\.dynamicTypeSize) var dynamicTypeSize
|
|
|
|
let room: MessageForwardingRoom
|
|
let isSelected: Bool
|
|
let context: MessageForwardingScreenViewModel.Context
|
|
|
|
var body: some View {
|
|
ListRow(label: .avatar(title: room.title,
|
|
description: room.description,
|
|
icon: avatar),
|
|
kind: .selection(isSelected: isSelected) {
|
|
context.send(viewAction: .selectRoom(roomID: room.id))
|
|
})
|
|
}
|
|
|
|
@ViewBuilder @MainActor
|
|
var avatar: some View {
|
|
if dynamicTypeSize < .accessibility3 {
|
|
RoomAvatarImage(avatar: room.avatar,
|
|
avatarSize: .room(on: .messageForwarding),
|
|
mediaProvider: context.mediaProvider)
|
|
.dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1)
|
|
.accessibilityHidden(true)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Previews
|
|
|
|
struct MessageForwardingScreen_Previews: PreviewProvider, TestablePreview {
|
|
static var previews: some View {
|
|
let summaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let viewModel = MessageForwardingScreenViewModel(forwardingItem: .init(id: .randomEvent,
|
|
roomID: "",
|
|
content: .init(noHandle: .init())),
|
|
userSession: UserSessionMock(.init()),
|
|
roomSummaryProvider: summaryProvider,
|
|
userIndicatorController: UserIndicatorControllerMock())
|
|
|
|
ElementNavigationStack {
|
|
MessageForwardingScreen(context: viewModel.context)
|
|
}
|
|
}
|
|
}
|