mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 19:44:05 +00:00
Simplify and fix implementation
This commit is contained in:
committed by
Stefan Ceriu
parent
f378e6e926
commit
30593909de
@@ -269,23 +269,16 @@ enum TimelineMediaPreviewItem: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasCaption: Bool {
|
||||||
|
timelineItem.hasMediaCaption
|
||||||
|
}
|
||||||
|
|
||||||
var caption: String? {
|
var caption: String? {
|
||||||
timelineItem.mediaCaption
|
timelineItem.mediaCaption
|
||||||
}
|
}
|
||||||
|
|
||||||
var formattedCaption: AttributedString? {
|
var formattedCaption: AttributedString? {
|
||||||
switch timelineItem {
|
timelineItem.formattedMediaCaption
|
||||||
case let audioItem as AudioRoomTimelineItem:
|
|
||||||
audioItem.content.formattedCaption
|
|
||||||
case let fileItem as FileRoomTimelineItem:
|
|
||||||
fileItem.content.formattedCaption
|
|
||||||
case let imageItem as ImageRoomTimelineItem:
|
|
||||||
imageItem.content.formattedCaption
|
|
||||||
case let videoItem as VideoRoomTimelineItem:
|
|
||||||
videoItem.content.formattedCaption
|
|
||||||
default:
|
|
||||||
nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentType: String? {
|
var contentType: String? {
|
||||||
|
|||||||
+25
-39
@@ -317,51 +317,46 @@ private struct CaptionView: View {
|
|||||||
context.viewState.currentItem
|
context.viewState.currentItem
|
||||||
}
|
}
|
||||||
|
|
||||||
private let maxCaptionHeight: CGFloat = 120
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if case let .media(mediaItem) = currentItem, mediaItem.caption != nil {
|
if case let .media(mediaItem) = currentItem, mediaItem.hasCaption {
|
||||||
CaptionScrollView(mediaItem: mediaItem, maxHeight: maxCaptionHeight)
|
CaptionScrollView(mediaItem: mediaItem)
|
||||||
.transition(.move(edge: .bottom).combined(with: .opacity))
|
.transition(.move(edge: .bottom).combined(with: .opacity))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct CaptionScrollView: View {
|
private struct CaptionScrollView: View {
|
||||||
|
private let maxHeight: CGFloat = 120
|
||||||
|
|
||||||
let mediaItem: TimelineMediaPreviewItem.Media
|
let mediaItem: TimelineMediaPreviewItem.Media
|
||||||
let maxHeight: CGFloat
|
|
||||||
|
@State private var shouldShowFade = false
|
||||||
@State private var contentHeight: CGFloat = 0
|
|
||||||
@State private var isScrollable: Bool = false
|
|
||||||
|
|
||||||
private var shouldShowFade: Bool {
|
|
||||||
contentHeight > maxHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
ZStack(alignment: .bottom) {
|
||||||
ScrollView(.vertical, showsIndicators: false) {
|
ScrollView(.vertical) {
|
||||||
captionContent
|
captionContent
|
||||||
.background(SizePreferenceKey())
|
.background {
|
||||||
|
GeometryReader { geometry in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
shouldShowFade = geometry.size.height > maxHeight
|
||||||
|
}
|
||||||
|
return Color.clear
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.onPreferenceChange(SizePreferenceKey.self) { size in
|
.frame(maxHeight: maxHeight)
|
||||||
contentHeight = size.height
|
.padding(16)
|
||||||
isScrollable = size.height > maxHeight
|
|
||||||
}
|
|
||||||
.frame(height: maxHeight)
|
|
||||||
.clipped()
|
|
||||||
|
|
||||||
if shouldShowFade {
|
if shouldShowFade {
|
||||||
LinearGradient(stops: [.init(color: .clear, location: 0.0),
|
LinearGradient(stops: [.init(color: .clear, location: 0.0),
|
||||||
.init(color: .black.opacity(0.5), location: 1.0)],
|
.init(color: .black.opacity(0.5), location: 1.0)],
|
||||||
startPoint: .top,
|
startPoint: .top,
|
||||||
endPoint: .bottom)
|
endPoint: .bottom)
|
||||||
.frame(height: 40)
|
.frame(height: 40)
|
||||||
.allowsHitTesting(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.padding(16)
|
|
||||||
.background {
|
.background {
|
||||||
BlurEffectView(style: .systemChromeMaterial)
|
BlurEffectView(style: .systemChromeMaterial)
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
@@ -373,20 +368,11 @@ private struct CaptionScrollView: View {
|
|||||||
if let formattedCaption = mediaItem.formattedCaption {
|
if let formattedCaption = mediaItem.formattedCaption {
|
||||||
FormattedBodyText(attributedString: formattedCaption)
|
FormattedBodyText(attributedString: formattedCaption)
|
||||||
} else if let caption = mediaItem.caption {
|
} else if let caption = mediaItem.caption {
|
||||||
Text(caption)
|
FormattedBodyText(text: caption)
|
||||||
.font(.compound.bodyLG)
|
|
||||||
.foregroundStyle(.compound.textPrimary)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct SizePreferenceKey: PreferenceKey {
|
|
||||||
static var defaultValue: CGSize = .zero
|
|
||||||
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
|
|
||||||
value = nextValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct DownloadIndicatorView: View {
|
private struct DownloadIndicatorView: View {
|
||||||
@ObservedObject var context: TimelineMediaPreviewViewModel.Context
|
@ObservedObject var context: TimelineMediaPreviewViewModel.Context
|
||||||
private var currentItem: TimelineMediaPreviewItem {
|
private var currentItem: TimelineMediaPreviewItem {
|
||||||
|
|||||||
+17
-2
@@ -34,6 +34,10 @@ extension EventBasedMessageTimelineItemProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasMediaCaption: Bool {
|
||||||
|
mediaCaption != nil
|
||||||
|
}
|
||||||
|
|
||||||
var mediaCaption: String? {
|
var mediaCaption: String? {
|
||||||
switch contentType {
|
switch contentType {
|
||||||
case .audio(let content):
|
case .audio(let content):
|
||||||
@@ -49,7 +53,18 @@ extension EventBasedMessageTimelineItemProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasMediaCaption: Bool {
|
var formattedMediaCaption: AttributedString? {
|
||||||
mediaCaption != nil
|
switch contentType {
|
||||||
|
case .audio(let content):
|
||||||
|
content.formattedCaption
|
||||||
|
case .file(let content):
|
||||||
|
content.formattedCaption
|
||||||
|
case .image(let content):
|
||||||
|
content.formattedCaption
|
||||||
|
case .video(let content):
|
||||||
|
content.formattedCaption
|
||||||
|
case .emote, .notice, .text, .location, .voice:
|
||||||
|
nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user