Content Scanning View (#5831)

* implement a MediaView to delegate at the view level the usage of the content scanner service, to determine how to render the media.

* fix for a small design mismatch

* fix for greedy error state

* updated naming

* just making some screenshot that have been affected by a string change on Localazy

* pr suggestions + updated strings
This commit is contained in:
Mauro
2026-07-06 16:15:27 +02:00
committed by GitHub
parent 0a77ba6c90
commit a2c1ca06dd
95 changed files with 786 additions and 219 deletions
@@ -30,12 +30,25 @@ struct VoiceMessageRoomTimelineContent: View {
let playerState: AudioPlayerState
var body: some View {
VoiceMessageRoomPlaybackView(playerState: playerState,
onPlayPause: onPlaybackPlayPause,
onSeek: { onPlaybackSeek($0) },
onScrubbing: { onPlaybackScrubbing($0) },
onPlaybackSpeedChange: onPlaybackSpeedChange)
.fixedSize(horizontal: false, vertical: true)
ContentScanningView(contentScannerService: context?.contentScannerService,
mediaSource: timelineItem.content.source) {
VoiceMessageRoomPlaybackView(playerState: playerState,
onPlayPause: onPlaybackPlayPause,
onSeek: { onPlaybackSeek($0) },
onScrubbing: { onPlaybackScrubbing($0) },
onPlaybackSpeedChange: onPlaybackSpeedChange)
.fixedSize(horizontal: false, vertical: true)
} scanningContent: {
VoiceMessageRoomPlaybackView(playerState: playerState,
isScanning: true,
onPlayPause: { },
onSeek: { _ in },
onScrubbing: { _ in },
onPlaybackSpeedChange: { })
.fixedSize(horizontal: false, vertical: true)
} unsafeContent: { failure in
ContentScanningFailureView(failure: failure)
}
}
private func onPlaybackPlayPause() {
@@ -67,6 +80,8 @@ struct VoiceMessageRoomTimelineContent: View {
struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
static let viewModel = TimelineViewModel.mock
static let scanningViewModel = TimelineViewModel.mock(contentScannerService: ContentScannerServiceMock(.init(scanResult: nil)))
static let unsafeViewModel = TimelineViewModel.mock(contentScannerService: ContentScannerServiceMock(.init(scanResult: false)))
static let timelineItemIdentifier = TimelineItemIdentifier.randomEvent
static let voiceRoomTimelineItem = VoiceMessageRoomTimelineItem(id: timelineItemIdentifier,
timestamp: .mock,
@@ -77,7 +92,7 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
content: .init(filename: "audio.ogg",
duration: 300,
waveform: EstimatedWaveform.mockWaveform,
source: nil,
source: try? MediaSourceProxy(url: .mockMXCAudio, mimeType: nil),
fileSize: nil,
contentType: nil))
@@ -89,6 +104,19 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
static var previews: some View {
body.environmentObject(viewModel.context)
VStack(spacing: 20) {
VoiceMessageRoomTimelineView(timelineItem: voiceRoomTimelineItem, playerState: playerState)
.environmentObject(scanningViewModel.context)
.environment(\.timelineContext, scanningViewModel.context)
VoiceMessageRoomTimelineView(timelineItem: voiceRoomTimelineItem, playerState: playerState)
.environmentObject(unsafeViewModel.context)
.environment(\.timelineContext, unsafeViewModel.context)
}
.fixedSize(horizontal: false, vertical: true)
.environmentObject(viewModel.context)
.previewDisplayName("Content Scanner")
}
static var body: some View {