Commit 396f29b
Unified CDN & Media Loading Architecture (v5) (#1399)
* Replace old ImageCDN/FileCDN/ImageLoading with unified CDN/ImageLoader/VideoLoader
Remove old protocols duplicated from StreamChatUI:
- ImageCDN, StreamImageCDN, FileCDN, DefaultFileCDN
- ImageLoading, NukeImageLoader, VideoPreviewLoader
Replace with unified types from StreamChatCommonUI:
- Utils.imageLoader now uses ImageLoader (StreamImageLoader)
- Utils.videoLoader now uses VideoLoader (StreamVideoLoader)
- CDN from StreamChat handles URL signing for files/images
- Update StreamAsyncImage, LazyImageExtensions, and Utils
* Update view models and views to use new CDN/loader APIs
- FileAttachmentPreview and MediaViewer use CDN.fileRequest instead of FileCDN
- MediaAttachment uses ImageLoader and VideoLoader directly
- MessageComposerViewModel uses simplified ImageLoader API
- MoreChannelActionsViewModel drops imageCDN dependency
* Update test mocks and tests for new loader protocols
- Replace ImageLoader_Mock to conform to ImageLoader
- Replace VideoPreviewLoader_Mock with VideoLoader_Mock
- Update test setup to use videoLoader instead of videoPreviewLoader
- Remove ImageCDN_Tests (replaced by StreamCDN_Tests in stream-chat-swift)
- Update VideoPreviewLoader_Tests for new VideoLoader protocol
* Use local stream-chat-swift dependency for development
Point Package.swift and xcodeproj to local ../stream-chat-swift path
for development and testing of the unified CDN refactoring.
* Add NukeImageDownloader and update Utils for ImageDownloading protocol
Provide NukeImageDownloader as the ImageDownloading backend for SwiftUI,
keeping Nuke vendored in this repo while sharing loader logic via CommonUI.
Update Utils to pass NukeImageDownloader to StreamImageLoader.
* Apply CDN transformations in LazyImage extensions
Restore CDN URL transformation (headers, signing, caching key) in the
LazyImage convenience initializers. The CDN completion is captured
synchronously -- for StreamCDN (which completes inline) the full
CDNRequest is used; async CDNs fall back to the raw URL gracefully.
* Add StreamLazyImage wrappers with CDN support
Replace direct LazyImage usage with StreamLazyImage and
StreamLazyContentImage wrappers that resolve CDN transformations
asynchronously via @injected dependencies before passing the
request to Nuke's LazyImage.
* Rename NukeImageDownloader and NukeImageProcessor to Stream prefix
Rename to StreamImageDownloader and StreamImageProcessor to decouple
public API naming from the Nuke dependency.
* Unify StreamAsyncImage as the single image-loading view
Merge StreamLazyContentImage, StreamLazyImage, and StreamAsyncImage
into a single StreamAsyncImage view that handles all image loading.
- CDN transformations resolved async via @injected dependencies
- StreamAsyncImageResult carries UIImage, isAnimated flag, and raw
animated data for GIF rendering without exposing Nuke types
- Nuke coupling isolated to a single private method (loadWithNuke)
for easy replacement when removing the Nuke dependency
- Delete LazyImageExtensions.swift (no longer needed)
- Update all call sites: avatars, link previews, giphy attachments
- AnimatedGifView now takes raw Data instead of Nuke ImageContainer
* Fix tests
* Remove maxAttachmentSize from CDNStorage protocol
* Introduce options parameters to the CDNStorage and CDNRequester
* Add remote dependency
* Fix CGSize
* Re-record snapshot for date overlay test on iOS 26.2
* Re-record voice recording snapshot tests for iOS 26.2
* Fix flaky date overlay snapshot test by using same-day timestamps
* Fix swiftformat
* Fix attachment downloads not using CDN requester for URL signing and custom headers
* Adopt unified MediaLoader protocol replacing separate ImageLoader and VideoLoader
- Replace imageLoader + videoLoader with single mediaLoader in Utils
- Update all views and view models to use utils.mediaLoader
- Rename loadPreview to loadVideoPreview for clarity
- Update test mocks and tests for MediaLoader conformance
- Update Package.resolved to latest LLC commit
* Adopt MediaLoader wrapper result types and async videoAsset
- Update call sites to use MediaLoaderImage, MediaLoaderVideoPreview
- Update all test mocks to conform to new MediaLoader signatures
- Update SPM dependency to latest LLC commit
* Access cdnRequester through config instead of ChatClient
Aligns with the removal of cdnRequester/cdnStorage from ChatClient.
All SwiftUI call sites now use chatClient.config.cdnRequester.
* Minor cleanups
* Use commit instead of branch
* Use better task identity in StreamAsyncImage
* Fix type mismatch in VideoPreviewLoader tests
Change receivedImage (UIImage?) to receivedPreview (MediaLoaderVideoPreview?)
to match the actual return type of result.get() from loadVideoPreview.
* Address PR review comments
- Merge ImageLoader_Mock and VideoLoader_Mock into a single
MediaLoader_Mock, consolidating all tracking properties
- Extract Nuke-specific image loading logic from StreamAsyncImage
into NukeImageLoader internal helper
- Update all test references to use MediaLoader_Mock
* Make sure cache is always used first
* Make initial phase success in StreamAsyncImage in case the image is available in cache
* Remove Image Processor from SwiftUI since it is not used now
* Fix MediaLoader tests naming
* Fix swiftformat
* Remove throwaway AVPlayer in StreamVideoPlayer
The code was creating and starting an AVPlayer before asking
avPlayerProvider for another player, doubling setup/network
work and briefly swapping the active player mid-playback.
Now only the provider-produced player is used.
* Pass CDN headers to AVPlayerProvider for authenticated playback
Add headers parameter to AVPlayerProvider.player(for:headers:completion:)
so CDN authentication headers from cdnRequester.fileRequest() are
propagated to the player. DefaultAVPlayerProvider uses AVURLAsset with
the headers when available. A default extension preserves backwards
compatibility for existing conformers.
* Add unit tests for NukeImageLoader
Cover the key paths: cachedResult returns nil when no key is stored,
loadImage calls CDN requester with correct URL, onCacheMiss fires on
cache miss, cache hit after CDN transform skips onCacheMiss, and
cachingKeyMap persists across load + cachedResult calls.
* Add unit tests for StreamImageDownloader
Verify error handling for invalid URLs, and that all
ImageDownloadingOptions combinations (headers, cachingKey,
resize, zero resize) are accepted without crash.
* Add fallback branch tests for maxAttachmentSize
Cover the cases where appSettings is nil, server limit is zero,
and server limit is negative — all should return the fallbackSize.
* Add loadImage and loadImages tests for StreamMediaLoader
Cover loadImage success, nil URL error, error propagation from
downloader, loadImages returning correct count, and loadImages
using placeholders on failure.
* Unify video loading via MediaLoader and simplify AVPlayerProvider
Replace manual CDN + AVPlayerProvider flow in StreamVideoPlayer with
MediaLoader.loadVideoAsset(). Simplify AVPlayerProvider to accept
MediaLoaderVideoAsset instead of raw URL + headers. Rename videoAsset
to loadVideoAsset for consistency with other MediaLoader methods.
* Make media loader mock the only mock
* Make StreamImageDownloader final Sendable
* Fix swiftformat
* Update LLC dependency to latest commit
* Rename LazyImageExtensions_Tests.swift to StreamAsyncImage_Tests.swift
Align file name with the test class StreamAsyncImage_Tests it contains.
Also rename test_mediaAttachment_generateThumbnail_callsImageLoader to
reference MediaLoader instead of the removed ImageLoader.
* Fix StreamAsyncImage doc comment referencing non-existent ImageLoader
Update the doc comment to reference MediaLoader and CDNRequester which
are the actual protocols used by this view.
* Update LLC commit
* Use attachment-based video preview loading
Update MediaAttachment and tests to use the attachment-based
loadVideoPreview(with:) instead of the removed URL variant,
enabling thumbnail URL optimization for remote video previews.
* Update LLC dependency and add loadVideoAsset to test conformers
Update to LLC commit that removes the default loadVideoAsset
implementation from MediaLoader, requiring all conformers to
provide explicit implementations.
* Use Utils.cdnRequester instead of ChatClientConfig
Move CDN requester access from chatClient.config.cdnRequester to
utils.cdnRequester, matching the UIKit pattern where it lives in
Components. The download attachment flow now resolves CDN URLs at the
UI layer before calling the core download function.
* Fix cdnrequester tests
* Remove unecessary stream image downloader tests
* Add NukeImageLoader_Tests to project file
* Minor fixes
* Minor review fixes
* Fix load preview mocks
* Update LLC dependency
* Remove unecessary test
* Fix media viewer tests
* [CI] Print verbose logs on old xcode job
* Revert "[CI] Print verbose logs on old xcode job"
This reverts commit 6ee5138.
* Bump Xcode version for old Xcode job
* Revert "Bump Xcode version for old Xcode job"
This reverts commit 286c240.
* Update dependency to develop
* Update dependency again
* [CI] Snapshots (#1420)
Co-authored-by: Stream Bot <ci@getstream.io>
---------
Co-authored-by: Alexey Alter-Pesotskiy <alex@testableapple.com>
Co-authored-by: Stream SDK Bot <60655709+Stream-SDK-Bot@users.noreply.github.com>
Co-authored-by: Stream Bot <ci@getstream.io>1 parent 67b592c commit 396f29b
File tree
63 files changed
+1227
-1541
lines changed- Sources/StreamChatSwiftUI
- ChatChannelList
- ChatChannel/ChannelInfo
- ChatComposer
- AttachmentPicker/AttachmentMediaPicker
- ChatMessageList
- Gallery
- CommonViews
- Avatars
- Utils
- Common
- StreamChatSwiftUI.xcodeproj
- StreamChatSwiftUITests
- Infrastructure
- Mocks
- TestTools
- Tests
- ChatChannel
- __Snapshots__
- ChatChannelViewDateOverlay_Tests
- LazyImageExtensions_Tests
- MessageView_Tests
- CommonViews
- Utils
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
63 files changed
+1227
-1541
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
| 19 | + | |
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| |||
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
129 | 129 | | |
130 | 130 | | |
131 | 131 | | |
132 | | - | |
| 132 | + | |
133 | 133 | | |
134 | | - | |
| 134 | + | |
135 | 135 | | |
136 | 136 | | |
137 | 137 | | |
| |||
Lines changed: 1 addition & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
21 | | - | |
| 20 | + | |
22 | 21 | | |
23 | 22 | | |
24 | 23 | | |
| |||
Lines changed: 2 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
57 | 58 | | |
58 | 59 | | |
59 | 60 | | |
60 | | - | |
| 61 | + | |
61 | 62 | | |
62 | 63 | | |
63 | 64 | | |
| |||
Lines changed: 7 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
26 | 30 | | |
27 | 31 | | |
28 | 32 | | |
| |||
33 | 37 | | |
34 | 38 | | |
35 | 39 | | |
36 | | - | |
| 40 | + | |
| 41 | + | |
37 | 42 | | |
38 | 43 | | |
39 | 44 | | |
| |||
45 | 50 | | |
46 | 51 | | |
47 | 52 | | |
| 53 | + | |
48 | 54 | | |
49 | 55 | | |
50 | 56 | | |
| |||
Lines changed: 5 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
944 | 944 | | |
945 | 945 | | |
946 | 946 | | |
947 | | - | |
| 947 | + | |
948 | 948 | | |
949 | 949 | | |
950 | 950 | | |
| |||
1019 | 1019 | | |
1020 | 1020 | | |
1021 | 1021 | | |
| 1022 | + | |
1022 | 1023 | | |
1023 | 1024 | | |
1024 | 1025 | | |
| |||
1200 | 1201 | | |
1201 | 1202 | | |
1202 | 1203 | | |
1203 | | - | |
| 1204 | + | |
1204 | 1205 | | |
1205 | | - | |
1206 | | - | |
1207 | | - | |
| 1206 | + | |
1208 | 1207 | | |
1209 | | - | |
| 1208 | + | |
1210 | 1209 | | |
1211 | 1210 | | |
1212 | 1211 | | |
| |||
Lines changed: 9 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
18 | | - | |
19 | | - | |
| 17 | + | |
20 | 18 | | |
21 | 19 | | |
22 | 20 | | |
| |||
62 | 60 | | |
63 | 61 | | |
64 | 62 | | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| |||
Lines changed: 15 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
232 | 232 | | |
233 | 233 | | |
234 | 234 | | |
235 | | - | |
| 235 | + | |
236 | 236 | | |
237 | 237 | | |
238 | 238 | | |
| |||
279 | 279 | | |
280 | 280 | | |
281 | 281 | | |
282 | | - | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
287 | | - | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
288 | 296 | | |
289 | 297 | | |
290 | 298 | | |
| |||
Lines changed: 13 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
316 | 317 | | |
317 | 318 | | |
318 | 319 | | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
| 320 | + | |
327 | 321 | | |
328 | 322 | | |
329 | 323 | | |
330 | 324 | | |
331 | 325 | | |
| 326 | + | |
332 | 327 | | |
333 | 328 | | |
334 | 329 | | |
| |||
342 | 337 | | |
343 | 338 | | |
344 | 339 | | |
| 340 | + | |
345 | 341 | | |
346 | 342 | | |
347 | 343 | | |
348 | 344 | | |
349 | | - | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
350 | 350 | | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | | - | |
355 | | - | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
356 | 354 | | |
357 | 355 | | |
358 | 356 | | |
| |||
368 | 366 | | |
369 | 367 | | |
370 | 368 | | |
| 369 | + | |
371 | 370 | | |
372 | 371 | | |
373 | 372 | | |
| |||
0 commit comments