Skip to content
This repository was archived by the owner on Mar 6, 2024. It is now read-only.

Commit b488d9a

Browse files
committed
Add image
1 parent 8653cf3 commit b488d9a

File tree

7 files changed

+138
-2
lines changed

7 files changed

+138
-2
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "placeholder.png",
5+
"idiom" : "universal",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"scale" : "2x"
11+
},
12+
{
13+
"idiom" : "universal",
14+
"scale" : "3x"
15+
}
16+
],
17+
"info" : {
18+
"author" : "xcode",
19+
"version" : 1
20+
}
21+
}
12.4 KB
Loading

samples/discovery/ios/ios/ComponentBoxUI/Sources/ComponentBoxUI/ComponentBoxUI.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ enum ComponentBoxUI {
1818
action: String?
1919
)
2020

21+
case Button(id: String, components: [componentbox.Component]?, modifier: componentbox.Modifier?, isEnabled: Bool?, action: String?, variant: String?)
22+
2123
case Column(
2224
id: String,
2325
components: [componentbox.Component]?,
@@ -28,7 +30,15 @@ enum ComponentBoxUI {
2830
isLazy: Bool?
2931
)
3032

31-
case Button(id: String, components: [componentbox.Component]?, modifier: componentbox.Modifier?, isEnabled: Bool?, action: String?, variant: String?)
33+
case Image(
34+
id: String,
35+
name: String?,
36+
url: String?,
37+
contentDescription: String?,
38+
modifier: componentbox.Modifier?,
39+
alignment: componentbox.Alignment?,
40+
contentScale: componentbox.ContentScale?
41+
)
3242

3343
case Row(
3444
id: String,
@@ -55,6 +65,9 @@ enum ComponentBoxUI {
5565
case let .Column(id, components, modifier, verticalArrangement, horizontalAlignment, action, isLazy):
5666
return AnyView(ComponentBoxUIColumn(id: id, components: components, modifier: modifier, verticalArrangement: verticalArrangement, horizontalAlignment: horizontalAlignment, action: action, isLazy: isLazy))
5767

68+
case let .Image(id, name, url, contentDescription, modifier, alignment, contentScale):
69+
return AnyView(ComponentBoxUIImage(id: id, name: name, url: url, contentDescription: contentDescription, modifier: modifier, alignment: alignment, contentScale: contentScale))
70+
5871
case let .Row(id, components, modifier, horizontalArrangement, verticalAlignment, action, isLazy):
5972
return AnyView(ComponentBoxUIRow(id: id, components: components, modifier: modifier, horizontalArrangement: horizontalArrangement, verticalAlignment: verticalAlignment, action: action, isLazy: isLazy))
6073

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//
2+
// Created by Matt Ramotar on 3/27/22.
3+
// Copyright (c) 2022 Dropbox, Inc. All rights reserved.
4+
//
5+
6+
import Foundation
7+
import SwiftUI
8+
import componentbox
9+
import Combine
10+
11+
@available(iOS 14.0, *)
12+
struct ComponentBoxUIImage: View, Identifiable {
13+
let id: String
14+
let name: String?
15+
let url: String?
16+
let contentDescription: String?
17+
let modifier: componentbox.Modifier?
18+
let alignment: componentbox.Alignment?
19+
let contentScale: componentbox.ContentScale?
20+
21+
22+
var fallbackImage : some View {
23+
SwiftUI.Image("placeholder").resizable().scaledToFit().frame(height: 200).clipped()
24+
}
25+
26+
var body: some View {
27+
28+
if (url != nil) {
29+
ComponentBoxAsyncImage(url: URL(string: url!)!, placeholder: {fallbackImage} )
30+
} else {
31+
fallbackImage
32+
}
33+
}
34+
}
35+
36+
37+
@available(iOS 14.0, *)
38+
class ImageLoader: ObservableObject {
39+
@Published var image: UIImage?
40+
private let url: URL
41+
private var cancellable: AnyCancellable?
42+
43+
init(url: URL) {
44+
self.url = url
45+
}
46+
47+
deinit {
48+
cancel()
49+
}
50+
51+
52+
func load() {
53+
cancellable = URLSession.shared.dataTaskPublisher(for: url)
54+
.map { UIImage(data: $0.data) }
55+
.replaceError(with: nil)
56+
.receive(on: DispatchQueue.main)
57+
.sink { [weak self] in self?.image = $0 }
58+
}
59+
60+
func cancel() {
61+
cancellable?.cancel()
62+
}
63+
}
64+
65+
@available(iOS 14.0, *)
66+
struct ComponentBoxAsyncImage<Placeholder: View> : View {
67+
68+
@StateObject private var loader: ImageLoader
69+
private let placeholder: Placeholder
70+
71+
init(url: URL, @ViewBuilder placeholder: () -> Placeholder) {
72+
self.placeholder = placeholder()
73+
_loader = StateObject(wrappedValue: ImageLoader(url: url))
74+
}
75+
76+
var body: some View {
77+
content
78+
.onAppear(perform: loader.load)
79+
}
80+
81+
private var content: some View {
82+
Group {
83+
if loader.image != nil {
84+
Image(uiImage: loader.image!)
85+
.resizable()
86+
} else {
87+
placeholder
88+
}
89+
}
90+
}
91+
}

samples/discovery/ios/ios/ComponentBoxUI/Sources/ComponentBoxUI/extensions/inflate.swift renamed to samples/discovery/ios/ios/ComponentBoxUI/Sources/ComponentBoxUI/extensions/component.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ public extension Component {
4242

4343
return AnyView(ui.inflate())
4444

45+
case let image as Component.Drawable:
46+
let ui = ComponentBoxUI.Image(id: image.id, name: image.name, url: image.url, contentDescription: image.contentDescription, modifier: image.modifier, alignment: image.alignment, contentScale: image.contentScale)
47+
return AnyView(ui.inflate())
48+
4549
case let row as Component.Row:
4650
let ui = ComponentBoxUI.Row(
4751
id: row.id,

samples/discovery/ios/ios/plans/PlansScreen.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,14 @@ private struct Content: View {
3636

3737
var body: some View {
3838
VStack {
39-
button.inflate()
39+
40+
if (screen?.components != nil) {
41+
ForEach(screen!.components, id: \.self) { component in
42+
component.inflate()
43+
}
44+
}
45+
46+
4047
Text(screen?.title ?? "No title")
4148

4249
}

0 commit comments

Comments
 (0)