automated screenshots with fastlane

This commit is contained in:
Stefan Lange-Hegermann
2025-10-07 22:38:11 +02:00
parent 16fd491af5
commit 296cf63176
41 changed files with 1440 additions and 73 deletions

View File

@@ -40,7 +40,7 @@
"value" : "dark"
}
],
"filename" : "boat-ob-inv.png",
"filename" : "boat-dark.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

View File

@@ -40,7 +40,7 @@
"value" : "dark"
}
],
"filename" : "cabin-ob-inv.png",
"filename" : "cabin-dark.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 KiB

View File

@@ -0,0 +1,52 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "charger-light.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "charger-dark.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -1,7 +1,16 @@
{
"images" : [
{
"filename" : "coffee-ob.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
@@ -10,6 +19,28 @@
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "coffee-light.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "coffee-dark.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 KiB

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"filename" : "fridge-ob.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"filename" : "light-ob.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

View File

@@ -0,0 +1,52 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "router-light.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "router-dark.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -40,7 +40,7 @@
"value" : "dark"
}
],
"filename" : "van-ob-inv.png",
"filename" : "bus-dark.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 KiB

View File

@@ -101,29 +101,55 @@ final class ComponentLibraryViewModel: ObservableObject {
}
private func fetchComponents() async throws -> [ComponentLibraryItem] {
var components = URLComponents(url: baseURL.appendingPathComponent("api/collections/components/records"), resolvingAgainstBaseURL: false)
components?.queryItems = [
URLQueryItem(name: "filter", value: "(type='load')"),
URLQueryItem(name: "sort", value: "+name"),
URLQueryItem(name: "fields", value: "id,collectionId,name,icon,voltage_in,voltage_out,watt")
]
let perPage = 200
var page = 1
var allRecords: [PocketBaseRecord] = []
guard let url = components?.url else {
throw URLError(.badURL)
while true {
var components = URLComponents(
url: baseURL.appendingPathComponent("api/collections/components/records"),
resolvingAgainstBaseURL: false
)
components?.queryItems = [
URLQueryItem(name: "filter", value: "(type='load')"),
URLQueryItem(name: "sort", value: "+name"),
URLQueryItem(name: "fields", value: "id,collectionId,name,icon,voltage_in,voltage_out,watt"),
URLQueryItem(name: "page", value: "\(page)"),
URLQueryItem(name: "perPage", value: "\(perPage)")
]
guard let url = components?.url else {
throw URLError(.badURL)
}
var request = URLRequest(url: url)
request.cachePolicy = .reloadIgnoringLocalCacheData
let (data, response) = try await urlSession.data(for: request)
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
let decoded = try JSONDecoder().decode(PocketBaseResponse.self, from: data)
allRecords.append(contentsOf: decoded.items)
let isLastPage: Bool
if let totalPages = decoded.totalPages, totalPages > 0 {
isLastPage = page >= totalPages
} else {
isLastPage = decoded.items.count < perPage
}
if isLastPage {
break
}
page += 1
}
var request = URLRequest(url: url)
request.cachePolicy = .reloadIgnoringLocalCacheData
let (data, response) = try await urlSession.data(for: request)
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
let decoded = try JSONDecoder().decode(PocketBaseResponse.self, from: data)
let affiliateLinksByComponent = try await fetchAffiliateLinks(for: decoded.items.map(\.id))
let mappedItems = decoded.items.map { record in
let affiliateLinksByComponent = try await fetchAffiliateLinks(for: allRecords.map(\.id))
let mappedItems = allRecords.map { record in
ComponentLibraryItem(
id: record.id,
name: record.name,
@@ -264,6 +290,9 @@ final class ComponentLibraryViewModel: ObservableObject {
}
private struct PocketBaseResponse: Decodable {
let page: Int?
let perPage: Int?
let totalPages: Int?
let items: [PocketBaseRecord]
}

View File

@@ -6,9 +6,9 @@ struct ComponentsOnboardingView: View {
let onBrowse: () -> Void
private let imageNames = [
"fridge-onboarding",
"router-onboarding",
"coffee-onboarding",
"light-onboarding"
"charger-onboarding"
]
private let timer = Timer.publish(every: 8, on: .main, in: .common).autoconnect()
@@ -57,6 +57,7 @@ struct ComponentsOnboardingView: View {
.background(Color.blue)
.cornerRadius(12)
}
.accessibilityIdentifier("create-component-button")
.buttonStyle(.plain)
Button(action: onBrowse) {

View File

@@ -81,6 +81,7 @@ struct SystemsOnboardingView: View {
.background(Color.blue)
.cornerRadius(12)
}
.accessibilityIdentifier("create-system-button")
.buttonStyle(.plain)
}
.padding(.horizontal, 24)