mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Custom media gallery views for files and voice messages (#3610)
* Extract the timeline item background from the BubbledStyler. * Use different views for files and voices messages, reuse the timeline content but only keep the bubble background instead of the whole TimelineStyler. * Add back max voice message width and add missing accessibility label
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Copyright 2024 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
// Please see LICENSE in the repository root for full details.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
extension View {
|
||||
func bubbleBackground(timelineItem: EventBasedTimelineItemProtocol,
|
||||
insets: EdgeInsets,
|
||||
color: Color? = nil) -> some View {
|
||||
modifier(TimelineItemBubbleBackgroundModifier(timelineItem: timelineItem,
|
||||
insets: insets,
|
||||
color: color))
|
||||
}
|
||||
}
|
||||
|
||||
private struct TimelineItemBubbleBackgroundModifier: ViewModifier {
|
||||
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
|
||||
|
||||
let timelineItem: EventBasedTimelineItemProtocol
|
||||
let insets: EdgeInsets
|
||||
var color: Color?
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.padding(insets)
|
||||
.background(color)
|
||||
.cornerRadius(12, corners: roundedCorners)
|
||||
}
|
||||
|
||||
private var roundedCorners: UIRectCorner {
|
||||
switch timelineGroupStyle {
|
||||
case .single:
|
||||
return .allCorners
|
||||
case .first:
|
||||
if timelineItem.isOutgoing {
|
||||
return [.topLeft, .topRight, .bottomLeft]
|
||||
} else {
|
||||
return [.topLeft, .topRight, .bottomRight]
|
||||
}
|
||||
case .middle:
|
||||
return timelineItem.isOutgoing ? [.topLeft, .bottomLeft] : [.topRight, .bottomRight]
|
||||
case .last:
|
||||
if timelineItem.isOutgoing {
|
||||
return [.topLeft, .bottomLeft, .bottomRight]
|
||||
} else {
|
||||
return [.topRight, .bottomLeft, .bottomRight]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,9 +163,9 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
||||
var messageBubble: some View {
|
||||
contentWithReply
|
||||
.timelineItemSendInfo(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus, context: context)
|
||||
.bubbleStyle(insets: timelineItem.bubbleInsets,
|
||||
color: timelineItem.bubbleBackgroundColor,
|
||||
corners: roundedCorners)
|
||||
.bubbleBackground(timelineItem: timelineItem,
|
||||
insets: timelineItem.bubbleInsets,
|
||||
color: timelineItem.bubbleBackgroundColor)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
@@ -217,40 +217,11 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
||||
timelineItem.isOutgoing ? .trailing : .leading
|
||||
}
|
||||
|
||||
private var roundedCorners: UIRectCorner {
|
||||
switch timelineGroupStyle {
|
||||
case .single:
|
||||
return .allCorners
|
||||
case .first:
|
||||
if timelineItem.isOutgoing {
|
||||
return [.topLeft, .topRight, .bottomLeft]
|
||||
} else {
|
||||
return [.topLeft, .topRight, .bottomRight]
|
||||
}
|
||||
case .middle:
|
||||
return timelineItem.isOutgoing ? [.topLeft, .bottomLeft] : [.topRight, .bottomRight]
|
||||
case .last:
|
||||
if timelineItem.isOutgoing {
|
||||
return [.topLeft, .bottomLeft, .bottomRight]
|
||||
} else {
|
||||
return [.topRight, .bottomLeft, .bottomRight]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var shouldShowSenderDetails: Bool {
|
||||
timelineGroupStyle.shouldShowSenderDetails
|
||||
}
|
||||
}
|
||||
|
||||
private extension View {
|
||||
func bubbleStyle(insets: EdgeInsets, color: Color? = nil, cornerRadius: CGFloat = 12, corners: UIRectCorner) -> some View {
|
||||
padding(insets)
|
||||
.background(color)
|
||||
.cornerRadius(cornerRadius, corners: corners)
|
||||
}
|
||||
}
|
||||
|
||||
private extension EventBasedTimelineItemProtocol {
|
||||
var bubbleBackgroundColor: Color? {
|
||||
let defaultColor: Color = isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming
|
||||
|
||||
+21
-15
@@ -9,26 +9,33 @@ import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct VoiceMessageRoomTimelineView: View {
|
||||
@Environment(\.timelineContext) private var context
|
||||
private let timelineItem: VoiceMessageRoomTimelineItem
|
||||
private let playerState: AudioPlayerState
|
||||
@State private var resumePlaybackAfterScrubbing = false
|
||||
|
||||
init(timelineItem: VoiceMessageRoomTimelineItem, playerState: AudioPlayerState) {
|
||||
self.timelineItem = timelineItem
|
||||
self.playerState = playerState
|
||||
}
|
||||
let timelineItem: VoiceMessageRoomTimelineItem
|
||||
let playerState: AudioPlayerState
|
||||
|
||||
var body: some View {
|
||||
TimelineStyler(timelineItem: timelineItem) {
|
||||
VoiceMessageRoomPlaybackView(playerState: playerState,
|
||||
onPlayPause: onPlaybackPlayPause,
|
||||
onSeek: { onPlaybackSeek($0) },
|
||||
onScrubbing: { onPlaybackScrubbing($0) })
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
VoiceMessageRoomTimelineContent(timelineItem: timelineItem,
|
||||
playerState: playerState)
|
||||
.accessibilityLabel(L10n.commonVoiceMessage)
|
||||
.frame(maxWidth: 400)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct VoiceMessageRoomTimelineContent: View {
|
||||
@Environment(\.timelineContext) private var context
|
||||
@State private var resumePlaybackAfterScrubbing = false
|
||||
|
||||
let timelineItem: VoiceMessageRoomTimelineItem
|
||||
let playerState: AudioPlayerState
|
||||
|
||||
var body: some View {
|
||||
VoiceMessageRoomPlaybackView(playerState: playerState,
|
||||
onPlayPause: onPlaybackPlayPause,
|
||||
onSeek: { onPlaybackSeek($0) },
|
||||
onScrubbing: { onPlaybackScrubbing($0) })
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
|
||||
private func onPlaybackPlayPause() {
|
||||
context?.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id)))
|
||||
@@ -78,7 +85,6 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Bubble")
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
Reference in New Issue
Block a user