Temporarily process deep link from HomeView

This commit is contained in:
PangMo5 2021-08-25 20:15:57 +09:00
parent b544bd66cc
commit 5d96de329f
9 changed files with 222 additions and 81 deletions

View File

@ -189,6 +189,7 @@
6220D0C726D62D8700B8E046 /* VideoPlayerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0C526D62D8700B8E046 /* VideoPlayerCoordinator.swift */; }; 6220D0C726D62D8700B8E046 /* VideoPlayerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0C526D62D8700B8E046 /* VideoPlayerCoordinator.swift */; };
6220D0C926D63F3700B8E046 /* Stinsen in Frameworks */ = {isa = PBXBuildFile; productRef = 6220D0C826D63F3700B8E046 /* Stinsen */; }; 6220D0C926D63F3700B8E046 /* Stinsen in Frameworks */ = {isa = PBXBuildFile; productRef = 6220D0C826D63F3700B8E046 /* Stinsen */; };
6220D0CA26D63F4D00B8E046 /* MainCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29E9E26D1016600C1D2E7 /* MainCoordinator.swift */; }; 6220D0CA26D63F4D00B8E046 /* MainCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29E9E26D1016600C1D2E7 /* MainCoordinator.swift */; };
6220D0CC26D640C400B8E046 /* AppURLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0CB26D640C400B8E046 /* AppURLHandler.swift */; };
6225FCCB2663841E00E067F6 /* ParallaxHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */; }; 6225FCCB2663841E00E067F6 /* ParallaxHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */; };
6228B1C22670EB010067FD35 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5377CBFD263B596B003A4E83 /* PersistenceController.swift */; }; 6228B1C22670EB010067FD35 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5377CBFD263B596B003A4E83 /* PersistenceController.swift */; };
624C21752685CF60007F1390 /* SearchablePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 624C21742685CF60007F1390 /* SearchablePickerView.swift */; }; 624C21752685CF60007F1390 /* SearchablePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 624C21742685CF60007F1390 /* SearchablePickerView.swift */; };
@ -430,6 +431,7 @@
6220D0BC26D60D6600B8E046 /* ItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemViewModel.swift; sourceTree = "<group>"; }; 6220D0BC26D60D6600B8E046 /* ItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemViewModel.swift; sourceTree = "<group>"; };
6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemCoordinator.swift; sourceTree = "<group>"; }; 6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemCoordinator.swift; sourceTree = "<group>"; };
6220D0C526D62D8700B8E046 /* VideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerCoordinator.swift; sourceTree = "<group>"; }; 6220D0C526D62D8700B8E046 /* VideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerCoordinator.swift; sourceTree = "<group>"; };
6220D0CB26D640C400B8E046 /* AppURLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppURLHandler.swift; sourceTree = "<group>"; };
6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParallaxHeader.swift; sourceTree = "<group>"; }; 6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParallaxHeader.swift; sourceTree = "<group>"; };
624C21742685CF60007F1390 /* SearchablePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchablePickerView.swift; sourceTree = "<group>"; }; 624C21742685CF60007F1390 /* SearchablePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchablePickerView.swift; sourceTree = "<group>"; };
625CB5672678B6FB00530A6E /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = "<group>"; }; 625CB5672678B6FB00530A6E /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = "<group>"; };
@ -997,6 +999,7 @@
62EC352E267666A5000E9F2D /* SessionManager.swift */, 62EC352E267666A5000E9F2D /* SessionManager.swift */,
536D3D73267BA8170004248C /* BackgroundManager.swift */, 536D3D73267BA8170004248C /* BackgroundManager.swift */,
53649AB0269CFB1900A2D8B7 /* LogManager.swift */, 53649AB0269CFB1900A2D8B7 /* LogManager.swift */,
6220D0CB26D640C400B8E046 /* AppURLHandler.swift */,
); );
path = Singleton; path = Singleton;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1513,6 +1516,7 @@
53649AB1269CFB1900A2D8B7 /* LogManager.swift in Sources */, 53649AB1269CFB1900A2D8B7 /* LogManager.swift in Sources */,
62E632E9267D3FF50063E547 /* SeasonItemViewModel.swift in Sources */, 62E632E9267D3FF50063E547 /* SeasonItemViewModel.swift in Sources */,
625CB56A2678B71200530A6E /* SplashViewModel.swift in Sources */, 625CB56A2678B71200530A6E /* SplashViewModel.swift in Sources */,
6220D0CC26D640C400B8E046 /* AppURLHandler.swift in Sources */,
62E632F3267D54030063E547 /* DetailItemViewModel.swift in Sources */, 62E632F3267D54030063E547 /* DetailItemViewModel.swift in Sources */,
53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */, 53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */,
53E4E649263F725B00F67C6B /* MultiSelectorView.swift in Sources */, 53E4E649263F725B00F67C6B /* MultiSelectorView.swift in Sources */,

View File

@ -177,5 +177,8 @@ struct ConnectToServerView: View {
dismissButton: .cancel()) dismissButton: .cancel())
} }
.navigationTitle(NSLocalizedString("Connect to Server", comment: "")) .navigationTitle(NSLocalizedString("Connect to Server", comment: ""))
.onAppear {
AppURLHandler.shared.appURLState = .allowedInLogin
}
} }
} }

View File

@ -8,8 +8,8 @@
*/ */
import Foundation import Foundation
import SwiftUI
import Stinsen import Stinsen
import SwiftUI
struct HomeView: View { struct HomeView: View {
@EnvironmentObject var homeRouter: NavigationRouter<HomeCoordinator.Route> @EnvironmentObject var homeRouter: NavigationRouter<HomeCoordinator.Route>
@ -37,7 +37,9 @@ struct HomeView: View {
.fontWeight(.bold) .fontWeight(.bold)
Spacer() Spacer()
Button { Button {
homeRouter.route(to: .library(viewModel: .init(parentID: libraryID, filters: viewModel.recentFilterSet), title: library?.name ?? "")) homeRouter
.route(to: .library(viewModel: .init(parentID: libraryID, filters: viewModel.recentFilterSet),
title: library?.name ?? ""))
} label: { } label: {
HStack { HStack {
Text("See All").font(.subheadline).fontWeight(.bold) Text("See All").font(.subheadline).fontWeight(.bold)
@ -45,7 +47,7 @@ struct HomeView: View {
} }
} }
}.padding(.leading, 16) }.padding(.leading, 16)
.padding(.trailing, 16) .padding(.trailing, 16)
LatestMediaView(viewModel: .init(libraryID: libraryID)) LatestMediaView(viewModel: .init(libraryID: libraryID))
} }
} }
@ -67,5 +69,11 @@ struct HomeView: View {
} }
} }
} }
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
AppURLHandler.shared.appURLState = .allowed
AppURLHandler.shared.processLaunchedURLIfNeeded()
}
}
} }
} }

View File

@ -18,6 +18,17 @@
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string> <string>$(MARKETING_VERSION)</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>jellyfin</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>

View File

@ -234,6 +234,9 @@ struct JellyfinPlayerApp: App {
.onShake { .onShake {
EmailHelper.shared.sendLogs(logURL: LogManager.shared.logFileURL()) EmailHelper.shared.sendLogs(logURL: LogManager.shared.logFileURL())
} }
.onOpenURL { url in
AppURLHandler.shared.processDeepLink(url: url)
}
} }
} }

View File

@ -0,0 +1,102 @@
//
/*
* SwiftFin is subject to the terms of the Mozilla Public
* License, v2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
*/
import Foundation
import Stinsen
import URLNavigator
final class AppURLHandler {
static let deepLinkScheme = "jellyfin"
@RouterObject
var router: NavigationRouter<HomeCoordinator.Route>?
enum AppURLState {
case launched
case allowedInLogin
case allowed
func allowedScheme(with url: URL) -> Bool {
switch self {
case .launched:
return false
case .allowed:
return true
case .allowedInLogin:
return false
}
}
}
static let shared = AppURLHandler()
var appURLState: AppURLState = .launched
var launchURL: URL?
}
extension AppURLHandler {
@discardableResult
func processDeepLink(url: URL) -> Bool {
guard url.scheme == Self.deepLinkScheme || url.scheme == "widget-extension" else {
return false
}
print(AppURLHandler.shared.appURLState.allowedScheme(with: url))
if AppURLHandler.shared.appURLState.allowedScheme(with: url) {
if launchURL == nil {
return processURL(url)
}
} else {
launchURL = url
}
return true
}
func processLaunchedURLIfNeeded() {
print("!@#!@#!@#!@#!@#!@")
print(launchURL)
guard let launchURL = launchURL else { return }
if processDeepLink(url: launchURL) {
self.launchURL = nil
}
}
private func processURL(_ url: URL) -> Bool {
print("processURL(_ url: URL) -> Bool")
if processURLForUser(url: url) {
return true
}
return false
}
private func processURLForUser(url: URL) -> Bool {
print("processURLForUser(_ url: URL) -> Bool")
print(url)
print(url.host)
print(url.path)
print(url.pathComponents)
print(url.pathComponents[safe: 0])
print(url.pathComponents[safe: 1])
print(url.pathComponents[safe: 2])
print(url.pathComponents[safe: 3])
guard url.host?.lowercased() == "users",
url.pathComponents[safe: 1]?.isEmpty == false else { return false }
// /Users/{UserID}/Items/{ItemID}
if url.pathComponents[safe: 2]?.lowercased() == "items",
let itemID = url.pathComponents[safe: 3]
{
print("Passed!@#")
router?.route(to: .item(viewModel: .init(id: itemID)))
return true
}
return false
}
}

View File

@ -30,6 +30,10 @@ final class ConnectToServerViewModel: ViewModel {
@Published var servers: [ServerDiscovery.ServerLookupResponse] = [] @Published var servers: [ServerDiscovery.ServerLookupResponse] = []
@Published var searching = false @Published var searching = false
override init() {
super.init()
}
func getPublicUsers() { func getPublicUsers() {
if ServerEnvironment.current.server != nil { if ServerEnvironment.current.server != nil {
LogManager.shared.log.debug("Attempting to read public users from \(ServerEnvironment.current.server.baseURI!)", LogManager.shared.log.debug("Attempting to read public users from \(ServerEnvironment.current.server.baseURI!)",

View File

@ -24,7 +24,6 @@ final class HomeViewModel: ViewModel {
override init() { override init() {
super.init() super.init()
refresh() refresh()
} }

View File

@ -142,14 +142,14 @@ struct NextUpEntryView: View {
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity) .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
} else { } else {
switch family { switch family {
case .systemSmall: case .systemSmall:
small(item: entry.items.first) small(item: entry.items.first)
case .systemMedium: case .systemMedium:
medium(items: entry.items) medium(items: entry.items)
case .systemLarge: case .systemLarge:
large(items: entry.items) large(items: entry.items)
default: default:
EmptyView() EmptyView()
} }
} }
} }
@ -198,51 +198,55 @@ extension NextUpEntryView {
} }
func smallVideoView(item: (BaseItemDto, UIImage?)) -> some View { func smallVideoView(item: (BaseItemDto, UIImage?)) -> some View {
VStack(alignment: .leading) { Link(destination: URL(string: "widget-extension://Users/\(SessionManager.current.user.user_id!)/Items/\(item.0.id!)")!, label: {
if let image = item.1 { VStack(alignment: .leading) {
Image(uiImage: image) if let image = item.1 {
.resizable() Image(uiImage: image)
.aspectRatio(.init(width: 1, height: 0.5625), contentMode: .fill) .resizable()
.clipped() .aspectRatio(.init(width: 1, height: 0.5625), contentMode: .fill)
.cornerRadius(8) .clipped()
.shadow(radius: 8) .cornerRadius(8)
} .shadow(radius: 8)
Text(item.0.seriesName ?? "") }
.font(.caption)
.fontWeight(.semibold)
.foregroundColor(.primary)
.lineLimit(1)
Text("\(item.0.name ?? "") · S\(item.0.parentIndexNumber ?? 0):E\(item.0.indexNumber ?? 0)")
.font(.caption)
.fontWeight(.semibold)
.foregroundColor(.secondary)
.lineLimit(1)
}
}
func largeVideoView(item: (BaseItemDto, UIImage?)) -> some View {
HStack(spacing: 20) {
if let image = item.1 {
Image(uiImage: image)
.resizable()
.aspectRatio(.init(width: 1, height: 0.5625), contentMode: .fill)
.clipped()
.cornerRadius(8)
.shadow(radius: 8)
}
VStack(alignment: .leading, spacing: 8) {
Text(item.0.seriesName ?? "") Text(item.0.seriesName ?? "")
.font(.caption) .font(.caption)
.fontWeight(.semibold) .fontWeight(.semibold)
.foregroundColor(.primary) .foregroundColor(.primary)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .lineLimit(1)
Text("\(item.0.name ?? "") · S\(item.0.parentIndexNumber ?? 0):E\(item.0.indexNumber ?? 0)") Text("\(item.0.name ?? "") · S\(item.0.parentIndexNumber ?? 0):E\(item.0.indexNumber ?? 0)")
.font(.caption) .font(.caption)
.fontWeight(.semibold) .fontWeight(.semibold)
.foregroundColor(.secondary) .foregroundColor(.secondary)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .lineLimit(1)
} }
} })
}
func largeVideoView(item: (BaseItemDto, UIImage?)) -> some View {
Link(destination: URL(string: "widget-extension://Users/\(SessionManager.current.user.user_id!)/Items/\(item.0.id!)")!, label: {
HStack(spacing: 20) {
if let image = item.1 {
Image(uiImage: image)
.resizable()
.aspectRatio(.init(width: 1, height: 0.5625), contentMode: .fill)
.clipped()
.cornerRadius(8)
.shadow(radius: 8)
}
VStack(alignment: .leading, spacing: 8) {
Text(item.0.seriesName ?? "")
.font(.caption)
.fontWeight(.semibold)
.foregroundColor(.primary)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
Text("\(item.0.name ?? "") · S\(item.0.parentIndexNumber ?? 0):E\(item.0.indexNumber ?? 0)")
.font(.caption)
.fontWeight(.semibold)
.foregroundColor(.secondary)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}
}
})
} }
} }
@ -281,33 +285,36 @@ extension NextUpEntryView {
func large(items: [(BaseItemDto, UIImage?)]) -> some View { func large(items: [(BaseItemDto, UIImage?)]) -> some View {
VStack(spacing: 0) { VStack(spacing: 0) {
if let firstItem = items[safe: 0] { if let firstItem = items[safe: 0] {
ZStack(alignment: .topTrailing) { Link(destination: URL(string: "widget-extension://Users/\(SessionManager.current.user.user_id!)/Items/\(firstItem.0.id!)")!,
ZStack(alignment: .bottomLeading) { label: {
if let image = firstItem.1 { ZStack(alignment: .topTrailing) {
Image(uiImage: image) ZStack(alignment: .bottomLeading) {
.centerCropped() if let image = firstItem.1 {
.innerShadow(color: Color.black.opacity(0.5), radius: 0.5) Image(uiImage: image)
} .centerCropped()
VStack(alignment: .leading, spacing: 8) { .innerShadow(color: Color.black.opacity(0.5), radius: 0.5)
Text(firstItem.0.seriesName ?? "") }
.font(.caption) VStack(alignment: .leading, spacing: 8) {
.fontWeight(.semibold) Text(firstItem.0.seriesName ?? "")
.foregroundColor(.white) .font(.caption)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .fontWeight(.semibold)
Text("\(firstItem.0.name ?? "") · S\(firstItem.0.parentIndexNumber ?? 0):E\(firstItem.0.indexNumber ?? 0)") .foregroundColor(.white)
.font(.caption) .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.fontWeight(.semibold) Text("\(firstItem.0.name ?? "") · S\(firstItem.0.parentIndexNumber ?? 0):E\(firstItem.0.indexNumber ?? 0)")
.foregroundColor(.gray) .font(.caption)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .fontWeight(.semibold)
} .foregroundColor(.gray)
.shadow(radius: 8) .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(12) }
} .shadow(radius: 8)
headerSymbol .padding(12)
.padding(12) }
} headerSymbol
.clipped() .padding(12)
.shadow(radius: 8) }
.clipped()
.shadow(radius: 8)
})
} }
VStack(spacing: 8) { VStack(spacing: 8) {
if let secondItem = items[safe: 1] { if let secondItem = items[safe: 1] {
@ -354,7 +361,7 @@ struct NextUpWidget_Previews: PreviewProvider {
(.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"), (.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"),
UIImage(named: "WidgetHeaderSymbol")), UIImage(named: "WidgetHeaderSymbol")),
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"), (.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
UIImage(named: "WidgetHeaderSymbol")) UIImage(named: "WidgetHeaderSymbol")),
], ],
error: nil)) error: nil))
.previewContext(WidgetPreviewContext(family: .systemMedium)) .previewContext(WidgetPreviewContext(family: .systemMedium))
@ -365,7 +372,7 @@ struct NextUpWidget_Previews: PreviewProvider {
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"), (.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
UIImage(named: "WidgetHeaderSymbol")), UIImage(named: "WidgetHeaderSymbol")),
(.init(name: "Name2", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series2"), (.init(name: "Name2", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series2"),
UIImage(named: "WidgetHeaderSymbol")) UIImage(named: "WidgetHeaderSymbol")),
], ],
error: nil)) error: nil))
.previewContext(WidgetPreviewContext(family: .systemLarge)) .previewContext(WidgetPreviewContext(family: .systemLarge))
@ -380,7 +387,7 @@ struct NextUpWidget_Previews: PreviewProvider {
(.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"), (.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"),
UIImage(named: "WidgetHeaderSymbol")), UIImage(named: "WidgetHeaderSymbol")),
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"), (.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
UIImage(named: "WidgetHeaderSymbol")) UIImage(named: "WidgetHeaderSymbol")),
], ],
error: nil)) error: nil))
.previewContext(WidgetPreviewContext(family: .systemMedium)) .previewContext(WidgetPreviewContext(family: .systemMedium))
@ -392,7 +399,7 @@ struct NextUpWidget_Previews: PreviewProvider {
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"), (.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
UIImage(named: "WidgetHeaderSymbol")), UIImage(named: "WidgetHeaderSymbol")),
(.init(name: "Name2", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series2"), (.init(name: "Name2", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series2"),
UIImage(named: "WidgetHeaderSymbol")) UIImage(named: "WidgetHeaderSymbol")),
], ],
error: nil)) error: nil))
.previewContext(WidgetPreviewContext(family: .systemLarge)) .previewContext(WidgetPreviewContext(family: .systemLarge))
@ -405,7 +412,7 @@ struct NextUpWidget_Previews: PreviewProvider {
NextUpEntryView(entry: .init(date: Date(), NextUpEntryView(entry: .init(date: Date(),
items: [ items: [
(.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"), (.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"),
UIImage(named: "WidgetHeaderSymbol")) UIImage(named: "WidgetHeaderSymbol")),
], ],
error: nil)) error: nil))
.previewContext(WidgetPreviewContext(family: .systemMedium)) .previewContext(WidgetPreviewContext(family: .systemMedium))
@ -415,7 +422,7 @@ struct NextUpWidget_Previews: PreviewProvider {
(.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"), (.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"),
UIImage(named: "WidgetHeaderSymbol")), UIImage(named: "WidgetHeaderSymbol")),
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"), (.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
UIImage(named: "WidgetHeaderSymbol")) UIImage(named: "WidgetHeaderSymbol")),
], ],
error: nil)) error: nil))
.previewContext(WidgetPreviewContext(family: .systemLarge)) .previewContext(WidgetPreviewContext(family: .systemLarge))