Simplify and fix implementation
This commit is contained in:
committed by
Stefan Ceriu
parent
cfd6703bf5
commit
635ebb720a
@@ -269,23 +269,16 @@ enum TimelineMediaPreviewItem: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
var hasCaption: Bool {
|
||||
timelineItem.hasMediaCaption
|
||||
}
|
||||
|
||||
var caption: String? {
|
||||
timelineItem.mediaCaption
|
||||
}
|
||||
|
||||
var formattedCaption: AttributedString? {
|
||||
switch timelineItem {
|
||||
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
|
||||
}
|
||||
timelineItem.formattedMediaCaption
|
||||
}
|
||||
|
||||
var contentType: String? {
|
||||
|
||||
@@ -317,51 +317,46 @@ private struct CaptionView: View {
|
||||
context.viewState.currentItem
|
||||
}
|
||||
|
||||
private let maxCaptionHeight: CGFloat = 120
|
||||
|
||||
var body: some View {
|
||||
if case let .media(mediaItem) = currentItem, mediaItem.caption != nil {
|
||||
CaptionScrollView(mediaItem: mediaItem, maxHeight: maxCaptionHeight)
|
||||
if case let .media(mediaItem) = currentItem, mediaItem.hasCaption {
|
||||
CaptionScrollView(mediaItem: mediaItem)
|
||||
.transition(.move(edge: .bottom).combined(with: .opacity))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct CaptionScrollView: View {
|
||||
private let maxHeight: CGFloat = 120
|
||||
|
||||
let mediaItem: TimelineMediaPreviewItem.Media
|
||||
let maxHeight: CGFloat
|
||||
|
||||
@State private var contentHeight: CGFloat = 0
|
||||
@State private var isScrollable: Bool = false
|
||||
|
||||
private var shouldShowFade: Bool {
|
||||
contentHeight > maxHeight
|
||||
}
|
||||
|
||||
|
||||
@State private var shouldShowFade = false
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
ZStack(alignment: .bottom) {
|
||||
ScrollView(.vertical) {
|
||||
captionContent
|
||||
.background(SizePreferenceKey())
|
||||
.background {
|
||||
GeometryReader { geometry in
|
||||
DispatchQueue.main.async {
|
||||
shouldShowFade = geometry.size.height > maxHeight
|
||||
}
|
||||
return Color.clear
|
||||
}
|
||||
}
|
||||
}
|
||||
.onPreferenceChange(SizePreferenceKey.self) { size in
|
||||
contentHeight = size.height
|
||||
isScrollable = size.height > maxHeight
|
||||
}
|
||||
.frame(height: maxHeight)
|
||||
.clipped()
|
||||
|
||||
.frame(maxHeight: maxHeight)
|
||||
.padding(16)
|
||||
|
||||
if shouldShowFade {
|
||||
LinearGradient(stops: [.init(color: .clear, location: 0.0),
|
||||
.init(color: .black.opacity(0.5), location: 1.0)],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom)
|
||||
.frame(height: 40)
|
||||
.allowsHitTesting(false)
|
||||
.init(color: .black.opacity(0.5), location: 1.0)],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom)
|
||||
.frame(height: 40)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(16)
|
||||
.background {
|
||||
BlurEffectView(style: .systemChromeMaterial)
|
||||
.ignoresSafeArea()
|
||||
@@ -373,20 +368,11 @@ private struct CaptionScrollView: View {
|
||||
if let formattedCaption = mediaItem.formattedCaption {
|
||||
FormattedBodyText(attributedString: formattedCaption)
|
||||
} else if let caption = mediaItem.caption {
|
||||
Text(caption)
|
||||
.font(.compound.bodyLG)
|
||||
.foregroundStyle(.compound.textPrimary)
|
||||
FormattedBodyText(text: caption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct SizePreferenceKey: PreferenceKey {
|
||||
static var defaultValue: CGSize = .zero
|
||||
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
|
||||
value = nextValue()
|
||||
}
|
||||
}
|
||||
|
||||
private struct DownloadIndicatorView: View {
|
||||
@ObservedObject var context: TimelineMediaPreviewViewModel.Context
|
||||
private var currentItem: TimelineMediaPreviewItem {
|
||||
|
||||
@@ -34,6 +34,10 @@ extension EventBasedMessageTimelineItemProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
var hasMediaCaption: Bool {
|
||||
mediaCaption != nil
|
||||
}
|
||||
|
||||
var mediaCaption: String? {
|
||||
switch contentType {
|
||||
case .audio(let content):
|
||||
@@ -49,7 +53,18 @@ extension EventBasedMessageTimelineItemProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
var hasMediaCaption: Bool {
|
||||
mediaCaption != nil
|
||||
var formattedMediaCaption: AttributedString? {
|
||||
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