@@ -23,8 +23,7 @@ struct CapturePreviewStrip: View {
2323 }
2424 . padding ( . horizontal, 24 )
2525 . padding ( . vertical, 16 )
26- . background ( . ultraThinMaterial)
27- . clipShape ( RoundedRectangle ( cornerRadius: 28 , style: . continuous) )
26+ . background ( RoundedRectangle ( cornerRadius: 28 , style: . continuous) . fill ( . ultraThinMaterial) )
2827 . shadow ( color: Color . black. opacity ( 0.25 ) , radius: 10 , x: 0 , y: 6 )
2928 . padding ( . horizontal, 24 )
3029 . overlayPreferenceValue ( PreviewSelectionBoundsKey . self) { anchor in
@@ -47,9 +46,11 @@ private struct CapturePreviewThumbnail: View {
4746 var dragItemProvider : ( ) -> NSItemProvider
4847
4948 private let height : CGFloat = 80
49+ @StateObject private var imageLoader = ImageLoader ( )
50+ @State private var isHovered = false
5051
5152 var body : some View {
52- ZStack {
53+ let preview = ZStack {
5354 thumbnail
5455 . frame ( maxWidth: . infinity, maxHeight: . infinity)
5556 . background ( Color . black. opacity ( 0.6 ) )
@@ -60,13 +61,24 @@ private struct CapturePreviewThumbnail: View {
6061 . frame ( width: targetWidth, height: height)
6162 . clipShape ( RoundedRectangle ( cornerRadius: 4 , style: . continuous) )
6263 . anchorPreference ( key: PreviewSelectionBoundsKey . self, value: . bounds) { isSelected ? $0 : nil }
63- . onDrag { dragItemProvider ( ) }
64+
65+ return preview
66+ . onDrag { dragItemProvider ( ) }
67+ . onHover { isHovered = $0 }
68+ . overlay ( alignment: . bottom) {
69+ if isHovered {
70+ TextBubble ( text: capture. device. displayTitle)
71+ . fixedSize ( horizontal: true , vertical: true )
72+ . offset ( y: 32 )
73+ . allowsHitTesting ( false )
74+ }
75+ }
6476 }
6577
6678 @ViewBuilder private var thumbnail : some View {
6779 switch capture. media {
6880 case . image( let url, _) :
69- if let image = NSImage ( contentsOf : url) {
81+ if let image = imageLoader . image ( url : url) {
7082 Image ( nsImage: image)
7183 . resizable ( )
7284 . scaledToFill ( )
@@ -201,6 +213,22 @@ private struct VideoPreviewThumbnail: View {
201213 }
202214}
203215
216+ private struct TextBubble : View {
217+ let text : String
218+
219+ var body : some View {
220+ Text ( text)
221+ . multilineTextAlignment ( . center)
222+ . font ( . system( size: 13 , weight: . medium) )
223+ . padding ( . horizontal, 14 )
224+ . padding ( . vertical, 6 )
225+ . background (
226+ RoundedRectangle ( cornerRadius: 16 , style: . continuous)
227+ . fill ( . ultraThinMaterial)
228+ )
229+ }
230+ }
231+
204232final class VideoThumbnailCache {
205233 nonisolated ( unsafe) static let shared = VideoThumbnailCache ( )
206234
0 commit comments