@@ -8,41 +8,47 @@ import StreamChat
88import SwiftUI
99
1010public struct ImageAttachmentContainer : View {
11+ @Injected ( \. colors) var colors
12+
1113 let message : ChatMessage
1214 let width : CGFloat
1315 let isFirst : Bool
14- let isGiphy : Bool
1516
1617 public var body : some View {
1718 if message. text. isEmpty {
1819 ImageAttachmentView (
1920 message: message,
20- width: width,
21- isGiphy: isGiphy
21+ width: width
2222 )
2323 . messageBubble ( for: message, isFirst: isFirst)
2424 } else {
2525 VStack ( spacing: 0 ) {
26- if hasAttachments {
27- ImageAttachmentView (
28- message: message,
29- width: width,
30- isGiphy: isGiphy
31- )
32- }
33-
26+ ImageAttachmentView (
27+ message: message,
28+ width: width
29+ )
30+
3431 HStack {
3532 Text ( message. text)
3633 . standardPadding ( )
3734 Spacer ( )
3835 }
36+ . background ( Color ( backgroundColor) )
3937 }
4038 . messageBubble ( for: message, isFirst: isFirst)
4139 }
4240 }
4341
44- private var hasAttachments : Bool {
45- isGiphy ? !message. giphyAttachments. isEmpty : !message. imageAttachments. isEmpty
42+ private var backgroundColor : UIColor {
43+ if message. isSentByCurrentUser {
44+ if message. type == . ephemeral {
45+ return colors. background8
46+ } else {
47+ return colors. background6
48+ }
49+ } else {
50+ return colors. background8
51+ }
4652 }
4753}
4854
@@ -53,7 +59,6 @@ struct ImageAttachmentView: View {
5359
5460 let message : ChatMessage
5561 let width : CGFloat
56- let isGiphy : Bool
5762
5863 private let spacing : CGFloat = 2
5964 private let maxDisplayedImages = 4
@@ -63,26 +68,11 @@ struct ImageAttachmentView: View {
6368 }
6469
6570 private var sources : [ URL ] {
66- if isGiphy {
67- return message. giphyAttachments. map { attachment in
68- if let state = attachment. uploadingState {
69- return state. localFileURL
70- } else {
71- let url = imageCDN. thumbnailURL (
72- originalURL: attachment. previewURL,
73- preferredSize: CGSize ( width: width, height: width)
74- )
75-
76- return url
77- }
78- }
79- } else {
80- return message. imageAttachments. map { attachment in
81- if let state = attachment. uploadingState {
82- return state. localFileURL
83- } else {
84- return attachment. imagePreviewURL
85- }
71+ message. imageAttachments. map { attachment in
72+ if let state = attachment. uploadingState {
73+ return state. localFileURL
74+ } else {
75+ return attachment. imagePreviewURL
8676 }
8777 }
8878 }
@@ -99,13 +89,15 @@ struct ImageAttachmentView: View {
9989 HStack ( spacing: spacing) {
10090 MultiImageView (
10191 source: sources [ 0 ] ,
102- width: width / 2
92+ width: width / 2 ,
93+ height: width
10394 )
10495 . withUploadingStateIndicator ( for: uploadState ( for: 0 ) , url: sources [ 0 ] )
10596
10697 MultiImageView (
10798 source: sources [ 1 ] ,
108- width: width / 2
99+ width: width / 2 ,
100+ height: width
109101 )
110102 . withUploadingStateIndicator ( for: uploadState ( for: 1 ) , url: sources [ 1 ] )
111103 }
@@ -114,20 +106,23 @@ struct ImageAttachmentView: View {
114106 HStack ( spacing: spacing) {
115107 MultiImageView (
116108 source: sources [ 0 ] ,
117- width: width / 2
109+ width: width / 2 ,
110+ height: width
118111 )
119112 . withUploadingStateIndicator ( for: uploadState ( for: 0 ) , url: sources [ 0 ] )
120113
121114 VStack ( spacing: spacing) {
122115 MultiImageView (
123116 source: sources [ 1 ] ,
124- width: width / 2
117+ width: width / 2 ,
118+ height: width / 2
125119 )
126120 . withUploadingStateIndicator ( for: uploadState ( for: 1 ) , url: sources [ 1 ] )
127121
128122 MultiImageView (
129123 source: sources [ 2 ] ,
130- width: width / 2
124+ width: width / 2 ,
125+ height: width / 2
131126 )
132127 . withUploadingStateIndicator ( for: uploadState ( for: 2 ) , url: sources [ 2 ] )
133128 }
@@ -138,28 +133,32 @@ struct ImageAttachmentView: View {
138133 VStack ( spacing: spacing) {
139134 MultiImageView (
140135 source: sources [ 0 ] ,
141- width: width / 2
136+ width: width / 2 ,
137+ height: width / 2
142138 )
143139 . withUploadingStateIndicator ( for: uploadState ( for: 0 ) , url: sources [ 0 ] )
144140
145141 MultiImageView (
146142 source: sources [ 1 ] ,
147- width: width / 2
143+ width: width / 2 ,
144+ height: width / 2
148145 )
149146 . withUploadingStateIndicator ( for: uploadState ( for: 1 ) , url: sources [ 1 ] )
150147 }
151148
152149 VStack ( spacing: spacing) {
153150 MultiImageView (
154151 source: sources [ 2 ] ,
155- width: width / 2
152+ width: width / 2 ,
153+ height: width / 2
156154 )
157155 . withUploadingStateIndicator ( for: uploadState ( for: 2 ) , url: sources [ 2 ] )
158156
159157 ZStack {
160158 MultiImageView (
161159 source: sources [ 3 ] ,
162- width: width / 2
160+ width: width / 2 ,
161+ height: width / 2
163162 )
164163 . withUploadingStateIndicator ( for: uploadState ( for: 3 ) , url: sources [ 3 ] )
165164
@@ -171,6 +170,7 @@ struct ImageAttachmentView: View {
171170 . font ( fonts. title)
172171 }
173172 }
173+ . frame ( width: width / 2 , height: width / 2 )
174174 }
175175 }
176176 . aspectRatio ( 1 , contentMode: . fill)
@@ -184,11 +184,7 @@ struct ImageAttachmentView: View {
184184 }
185185
186186 private func uploadState( for index: Int ) -> AttachmentUploadingState ? {
187- if isGiphy {
188- return message. giphyAttachments [ index] . uploadingState
189- } else {
190- return message. imageAttachments [ index] . uploadingState
191- }
187+ message. imageAttachments [ index] . uploadingState
192188 }
193189}
194190
@@ -198,29 +194,40 @@ struct SingleImageView: View {
198194
199195 var body : some View {
200196 LazyLoadingImage ( source: source, width: width)
201- . aspectRatio ( contentMode : . fit )
197+ . frame ( width : width , height : 3 * width / 4 )
202198 }
203199}
204200
205201struct MultiImageView : View {
206202 let source : URL
207203 let width : CGFloat
204+ let height : CGFloat
208205
209206 var body : some View {
210207 LazyLoadingImage ( source: source, width: width)
211- . frame ( width: width)
208+ . frame ( width: width, height: height)
209+ . clipped ( )
212210 }
213211}
214212
215213struct LazyLoadingImage : View {
214+ @Injected ( \. utils) var utils
215+
216+ @State private var image : UIImage ?
217+ @State private var error : Error ?
218+
216219 let source : URL
217220 let width : CGFloat
218221
219222 var body : some View {
220- LazyImage ( source: source) { state in
221- if let imageContainer = state. imageContainer {
222- Image ( imageContainer)
223- } else if state. error != nil {
223+ ZStack {
224+ if let image = image {
225+ Image ( uiImage: image)
226+ . resizable ( )
227+ . scaledToFill ( )
228+ . aspectRatio ( contentMode: . fill)
229+ . clipped ( )
230+ } else if error != nil {
224231 Color ( . secondarySystemBackground)
225232 } else {
226233 ZStack {
@@ -229,8 +236,26 @@ struct LazyLoadingImage: View {
229236 }
230237 }
231238 }
232- . onDisappear ( . reset)
233- . processors ( [ ImageProcessors . Resize ( width: width) ] )
234- . priority ( . high)
239+ . onAppear {
240+ if image != nil {
241+ return
242+ }
243+
244+ utils. imageLoader. loadImage (
245+ url: source,
246+ imageCDN: utils. imageCDN,
247+ resize: true ,
248+ preferredSize: CGSize ( width: width, height: 3 * width / 4 ) ,
249+ completion: { result in
250+ switch result {
251+ case let . success( image) :
252+ self . image = image
253+ case let . failure( error) :
254+ self . error = error
255+ }
256+ }
257+ )
258+ }
259+ . clipped ( )
235260 }
236261}
0 commit comments