@@ -13,14 +13,14 @@ public struct PokitLinkPreview: View {
1313 @Environment ( \. openURL)
1414 private var openURL
1515
16- private let title : String
17- private let url : String
18- private let imageURL : String
16+ private let title : String ?
17+ private let url : String ?
18+ private let imageURL : String ?
1919
2020 public init (
21- title: String ,
22- url: String ,
23- imageURL: String
21+ title: String ? ,
22+ url: String ? ,
23+ imageURL: String ?
2424 ) {
2525 self . title = title
2626 self . url = url
@@ -36,19 +36,12 @@ public struct PokitLinkPreview: View {
3636 @MainActor
3737 private var buttonLabel : some View {
3838 HStack ( spacing: 16 ) {
39- LazyImage ( url: URL ( string: imageURL) ) { phase in
40- Group {
41- if let image = phase. image {
42- image
43- . resizable ( )
44- . aspectRatio ( contentMode: . fill)
45- } else {
46- PokitSpinner ( )
47- . foregroundStyle ( . pokit( . icon( . brand) ) )
48- . frame ( width: 48 , height: 48 )
49- }
39+ Group {
40+ if let url = imageURL {
41+ thumbnail ( url: url)
42+ } else {
43+ Color . pokit ( . bg( . secondary) )
5044 }
51- . animation ( . pokitDissolve, value: phase. image)
5245 }
5346 . frame ( width: 124 , height: 108 )
5447 . clipped ( )
@@ -76,26 +69,73 @@ public struct PokitLinkPreview: View {
7669 }
7770
7871 @ViewBuilder
79- private func info( title: String ) -> some View {
72+ private func thumbnail( url: String ) -> some View {
73+ LazyImage ( url: URL ( string: url) ) { phase in
74+ Group {
75+ if let image = phase. image {
76+ image
77+ . resizable ( )
78+ . aspectRatio ( contentMode: . fill)
79+ } else {
80+ PokitSpinner ( )
81+ . foregroundStyle ( . pokit( . icon( . brand) ) )
82+ . frame ( width: 48 , height: 48 )
83+ }
84+ }
85+ . animation ( . pokitDissolve, value: phase. image)
86+ }
87+ }
88+
89+ @ViewBuilder
90+ private func info( title: String ? ) -> some View {
8091 VStack ( alignment: . leading, spacing: 8 ) {
81- Text ( title)
82- . pokitFont ( . b3( . b) )
83- . foregroundStyle ( . pokit( . text( . secondary) ) )
84- . multilineTextAlignment ( . leading)
85- . lineLimit ( 2 )
92+ if let title {
93+ Text ( title)
94+ . pokitFont ( . b3( . b) )
95+ . foregroundStyle ( . pokit( . text( . secondary) ) )
96+ . multilineTextAlignment ( . leading)
97+ . lineLimit ( 2 )
98+ } else {
99+ placeholder ( 23 )
100+ }
86101
87- Text ( url)
88- . pokitFont ( . detail2)
89- . foregroundStyle ( . pokit( . text( . tertiary) ) )
90- . multilineTextAlignment ( . leading)
91- . lineLimit ( 2 )
102+ if let url {
103+ Text ( url)
104+ . pokitFont ( . detail2)
105+ . foregroundStyle ( . pokit( . text( . tertiary) ) )
106+ . multilineTextAlignment ( . leading)
107+ . lineLimit ( 2 )
108+ } else {
109+ placeholder ( 55 )
110+ }
92111 }
93112 . padding ( . vertical, 16 )
94113 . padding ( . trailing, 20 )
95114 }
96115
116+ @ViewBuilder
117+ private func placeholder( _ tLength: CGFloat ) -> some View {
118+ VStack ( alignment: . leading, spacing: 2 ) {
119+ RoundedRectangle ( cornerRadius: 2 , style: . continuous)
120+ . fill ( . pokit( . bg( . secondary) ) )
121+ . frame ( height: 16 )
122+
123+ RoundedRectangle ( cornerRadius: 2 , style: . continuous)
124+ . fill ( . pokit( . bg( . secondary) ) )
125+ . padding ( . trailing, tLength)
126+ . frame ( height: 16 )
127+ }
128+ }
129+
97130 private func buttonTapped( ) {
98- guard let url = URL ( string: url) else { return }
131+ guard
132+ let urlString = url,
133+ let url = URL ( string: urlString)
134+ else { return }
99135 openURL ( url)
100136 }
101137}
138+
139+ #Preview {
140+ PokitLinkPreview ( title: nil , url: nil , imageURL: nil )
141+ }
0 commit comments