mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-01 09:42:39 +00:00
ba23153ab4
* feat: Render declined calls in DM timeline * Record preview snapshots * review: Use CallIntent constant * review: clean-up * Record preview snapshots * review: Move private field to the bottom with MARK: - Private * review: Male CallIntent a string enum to use rawValue --------- Co-authored-by: Element CI <ci@element.io>
157 lines
7.2 KiB
Swift
157 lines
7.2 KiB
Swift
//
|
|
// Copyright 2025 Element Creations Ltd.
|
|
// Copyright 2024-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 Foundation
|
|
import SwiftUI
|
|
|
|
struct CallNotificationRoomTimelineView: View {
|
|
@Environment(\.timelineContext) private var context
|
|
|
|
let timelineItem: CallNotificationRoomTimelineItem
|
|
|
|
var body: some View {
|
|
HStack(spacing: 12) {
|
|
CompoundIcon(iconKeyPath, size: .medium, relativeTo: .compound.headingMDBold)
|
|
.foregroundStyle(.compound.iconSecondary)
|
|
.accessibilityHidden(true)
|
|
|
|
Text(tileTitle)
|
|
.font(.compound.bodyMD)
|
|
.foregroundColor(.compound.textSecondary)
|
|
.labelStyle(.custom(spacing: 4))
|
|
|
|
Spacer()
|
|
|
|
Text(timelineItem.timestamp.formattedTime())
|
|
.font(.compound.bodyXS)
|
|
.foregroundColor(.compound.textSecondary)
|
|
}
|
|
.padding(12)
|
|
.overlay(RoundedRectangle(cornerRadius: 8)
|
|
.stroke(.compound.borderInteractiveSecondary, lineWidth: 1))
|
|
.padding(16)
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private var tileTitle: String {
|
|
if timelineItem.isDM {
|
|
// As per design only have declined variants in DM
|
|
if timelineItem.isDeclinedByMe {
|
|
L10n.commonCallYouDeclined
|
|
} else if timelineItem.isDeclined {
|
|
L10n.commonCallDeclined
|
|
} else {
|
|
L10n.commonCallStarted
|
|
}
|
|
} else {
|
|
L10n.commonCallStarted
|
|
}
|
|
}
|
|
|
|
private var iconKeyPath: KeyPath<CompoundIcons, Image> {
|
|
if timelineItem.isDM, timelineItem.isDeclined || timelineItem.isDeclinedByMe {
|
|
// As per design only have declined variants in DM
|
|
timelineItem.isVoiceCall ? \.voiceCallDeclinedSolid : \.videoCallDeclinedSolid
|
|
} else {
|
|
timelineItem.isVoiceCall ? \.voiceCallSolid : \.videoCallSolid
|
|
}
|
|
}
|
|
}
|
|
|
|
struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|
static let viewModel = TimelineViewModel.mock
|
|
|
|
static var previews: some View {
|
|
body.environmentObject(viewModel.context)
|
|
}
|
|
|
|
static var body: some View {
|
|
VStack(spacing: 0) {
|
|
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
|
|
timestamp: .mock,
|
|
isEditable: false,
|
|
canBeRepliedTo: false,
|
|
isDM: false,
|
|
isDeclinedByMe: false,
|
|
isDeclined: false,
|
|
isVoiceCall: false))
|
|
|
|
Divider()
|
|
|
|
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
|
|
timestamp: .mock,
|
|
isEditable: false,
|
|
canBeRepliedTo: false,
|
|
isDM: true,
|
|
isDeclinedByMe: false,
|
|
isDeclined: false,
|
|
isVoiceCall: true))
|
|
|
|
Divider()
|
|
|
|
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
|
|
timestamp: .mock,
|
|
isEditable: false,
|
|
canBeRepliedTo: false,
|
|
isDM: false,
|
|
isDeclinedByMe: true,
|
|
isDeclined: true,
|
|
isVoiceCall: false))
|
|
|
|
Divider()
|
|
|
|
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
|
|
timestamp: .mock,
|
|
isEditable: false,
|
|
canBeRepliedTo: false,
|
|
isDM: true,
|
|
isDeclinedByMe: false,
|
|
isDeclined: true,
|
|
isVoiceCall: true))
|
|
|
|
Divider()
|
|
|
|
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
|
|
timestamp: .mock,
|
|
isEditable: false,
|
|
canBeRepliedTo: false,
|
|
isDM: true,
|
|
isDeclinedByMe: true,
|
|
isDeclined: true,
|
|
isVoiceCall: true))
|
|
|
|
Divider()
|
|
|
|
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
|
|
timestamp: .mock,
|
|
isEditable: false,
|
|
canBeRepliedTo: false,
|
|
isDM: true,
|
|
isDeclinedByMe: false,
|
|
isDeclined: true,
|
|
isVoiceCall: false))
|
|
|
|
Divider()
|
|
|
|
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
|
|
timestamp: .mock,
|
|
isEditable: false,
|
|
canBeRepliedTo: false,
|
|
isDM: true,
|
|
isDeclinedByMe: true,
|
|
isDeclined: true,
|
|
isVoiceCall: false))
|
|
|
|
Divider()
|
|
}
|
|
.padding()
|
|
}
|
|
}
|