[tvOS] ErrorViews - Creation (#1414)
* Button cleanup & errorViews * Change the Sign Out button to be `ListRowButton`. Sets a better height value using `maxHeight` to ensure that it doesn't exceed the `ListRow` sizing. * deleteUsersButton needs to be manually set back to 75 * wip --------- Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com>
This commit is contained in:
parent
6ee2b71cab
commit
846aabc868
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// 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 (c) 2025 Jellyfin & Jellyfin Contributors
|
||||
//
|
||||
|
||||
import Defaults
|
||||
import SwiftUI
|
||||
|
||||
// TODO: should use environment refresh instead?
|
||||
struct ErrorView<ErrorType: Error>: View {
|
||||
|
||||
@Default(.accentColor)
|
||||
private var accentColor
|
||||
|
||||
private let error: ErrorType
|
||||
private var onRetry: (() -> Void)?
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
.font(.system(size: 150))
|
||||
.foregroundColor(Color.red)
|
||||
|
||||
Text(error.localizedDescription)
|
||||
.frame(minWidth: 250, maxWidth: 750)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
if let onRetry {
|
||||
ListRowButton(L10n.retry, action: onRetry)
|
||||
.foregroundStyle(accentColor.overlayColor, accentColor)
|
||||
.frame(maxWidth: 750)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ErrorView {
|
||||
|
||||
init(error: ErrorType) {
|
||||
self.init(
|
||||
error: error,
|
||||
onRetry: nil
|
||||
)
|
||||
}
|
||||
|
||||
func onRetry(_ action: @escaping () -> Void) -> Self {
|
||||
copy(modifying: \.onRetry, with: action)
|
||||
}
|
||||
}
|
|
@ -8,25 +8,42 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
// TODO: on focus, make the cancel and destructive style
|
||||
// match style like in an `alert`
|
||||
struct ListRowButton: View {
|
||||
|
||||
// MARK: - Environment
|
||||
|
||||
@Environment(\.isEnabled)
|
||||
private var isEnabled
|
||||
|
||||
// MARK: - Focus State
|
||||
|
||||
@FocusState
|
||||
private var isFocused: Bool
|
||||
|
||||
// MARK: - Button Variables
|
||||
|
||||
let title: String
|
||||
let role: ButtonRole?
|
||||
let action: () -> Void
|
||||
|
||||
// MARK: - Initializer
|
||||
|
||||
init(_ title: String, role: ButtonRole? = nil, action: @escaping () -> Void) {
|
||||
self.title = title
|
||||
self.role = role
|
||||
self.action = action
|
||||
}
|
||||
|
||||
// MARK: - Body
|
||||
|
||||
var body: some View {
|
||||
Button {
|
||||
action()
|
||||
} label: {
|
||||
Button(action: action) {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.fill(secondaryStyle)
|
||||
.brightness(isFocused ? 0.25 : 0)
|
||||
|
||||
Text(title)
|
||||
.foregroundStyle(primaryStyle)
|
||||
|
@ -34,24 +51,27 @@ struct ListRowButton: View {
|
|||
}
|
||||
}
|
||||
.buttonStyle(.card)
|
||||
.frame(height: 75)
|
||||
.frame(maxHeight: 75)
|
||||
.focused($isFocused)
|
||||
}
|
||||
|
||||
// MARK: - Styles
|
||||
// MARK: - Primary Style
|
||||
|
||||
private var primaryStyle: some ShapeStyle {
|
||||
if role == .destructive {
|
||||
if role == .destructive || role == .cancel {
|
||||
return AnyShapeStyle(Color.red)
|
||||
} else {
|
||||
return AnyShapeStyle(.primary)
|
||||
return AnyShapeStyle(HierarchicalShapeStyle.primary)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Secondary Style
|
||||
|
||||
private var secondaryStyle: some ShapeStyle {
|
||||
if role == .destructive {
|
||||
if role == .destructive || role == .cancel {
|
||||
return AnyShapeStyle(Color.red.opacity(0.2))
|
||||
} else {
|
||||
return AnyShapeStyle(.secondary)
|
||||
return AnyShapeStyle(HierarchicalShapeStyle.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,19 @@ struct AppLoadingView: View {
|
|||
ZStack {
|
||||
Color.clear
|
||||
|
||||
if didFailMigration {
|
||||
Text("An internal error occurred.")
|
||||
if !didFailMigration {
|
||||
ProgressView()
|
||||
}
|
||||
|
||||
if didFailMigration {
|
||||
ErrorView(error: JellyfinAPIError("An internal error occurred."))
|
||||
}
|
||||
}
|
||||
.topBarTrailing {
|
||||
Button(L10n.advanced, systemImage: "gearshape.fill") {}
|
||||
.foregroundStyle(.secondary)
|
||||
.disabled(true)
|
||||
.opacity(didFailMigration ? 0 : 1)
|
||||
}
|
||||
.onNotification(.didFailMigration) { _ in
|
||||
didFailMigration = true
|
||||
|
|
|
@ -40,7 +40,7 @@ struct ChannelLibraryView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
WrappedView {
|
||||
ZStack {
|
||||
switch viewModel.state {
|
||||
case .content:
|
||||
if viewModel.elements.isEmpty {
|
||||
|
@ -49,11 +49,15 @@ struct ChannelLibraryView: View {
|
|||
contentView
|
||||
}
|
||||
case let .error(error):
|
||||
Text(error.localizedDescription)
|
||||
ErrorView(error: error)
|
||||
.onRetry {
|
||||
viewModel.send(.refresh)
|
||||
}
|
||||
case .initial, .refreshing:
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.animation(.linear(duration: 0.1), value: viewModel.state)
|
||||
.ignoresSafeArea()
|
||||
.onFirstAppear {
|
||||
if viewModel.state == .initial {
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
//
|
||||
// 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 (c) 2025 Jellyfin & Jellyfin Contributors
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// TODO: make general `ErrorView` like iOS
|
||||
|
||||
#warning("TODO: implement")
|
||||
|
||||
extension HomeView {
|
||||
|
||||
struct ErrorView: View {
|
||||
|
||||
@ObservedObject
|
||||
var viewModel: HomeViewModel
|
||||
|
||||
var body: some View {
|
||||
Text("TODO")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extension HomeView {
|
||||
//
|
||||
// struct ErrorView: View {
|
||||
//
|
||||
// @ObservedObject
|
||||
// var viewModel: HomeViewModel
|
||||
//
|
||||
// let errorMessage: ErrorMessage
|
||||
//
|
||||
// var body: some View {
|
||||
// VStack {
|
||||
// if viewModel.isLoading {
|
||||
// ProgressView()
|
||||
// .frame(width: 100, height: 100)
|
||||
// .scaleEffect(2)
|
||||
// } else {
|
||||
// Image(systemName: "xmark.circle.fill")
|
||||
// .font(.system(size: 72))
|
||||
// .foregroundColor(Color.red)
|
||||
// .frame(width: 100, height: 100)
|
||||
// }
|
||||
//
|
||||
//// Text("\(errorMessage.code)")
|
||||
//
|
||||
// Text(errorMessage.message)
|
||||
// .frame(minWidth: 50, maxWidth: 240)
|
||||
// .multilineTextAlignment(.center)
|
||||
//
|
||||
// Button {
|
||||
//// viewModel.refresh()
|
||||
// } label: {
|
||||
// L10n.retry.text
|
||||
// .bold()
|
||||
// .font(.callout)
|
||||
// .frame(width: 400, height: 75)
|
||||
// .background(Color.jellyfinPurple)
|
||||
// }
|
||||
// .buttonStyle(.card)
|
||||
// }
|
||||
// .offset(y: -50)
|
||||
// }
|
||||
// }
|
||||
// }
|
|
@ -50,19 +50,23 @@ struct HomeView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
WrappedView {
|
||||
Group {
|
||||
ZStack {
|
||||
// This keeps the ErrorView vertically aligned with the PagingLibraryView
|
||||
Color.clear
|
||||
|
||||
switch viewModel.state {
|
||||
case .content:
|
||||
contentView
|
||||
case let .error(error):
|
||||
Text(error.localizedDescription)
|
||||
ErrorView(error: error)
|
||||
.onRetry {
|
||||
viewModel.send(.refresh)
|
||||
}
|
||||
case .initial, .refreshing:
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.transition(.opacity.animation(.linear(duration: 0.2)))
|
||||
}
|
||||
.animation(.linear(duration: 0.1), value: viewModel.state)
|
||||
.onFirstAppear {
|
||||
viewModel.send(.refresh)
|
||||
}
|
||||
|
|
|
@ -52,17 +52,20 @@ struct ItemView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
WrappedView {
|
||||
ZStack {
|
||||
switch viewModel.state {
|
||||
case .content:
|
||||
contentView
|
||||
case let .error(error):
|
||||
Text(error.localizedDescription)
|
||||
ErrorView(error: error)
|
||||
.onRetry {
|
||||
viewModel.send(.refresh)
|
||||
}
|
||||
case .initial, .refreshing:
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.transition(.opacity.animation(.linear(duration: 0.2)))
|
||||
.animation(.linear(duration: 0.1), value: viewModel.state)
|
||||
.onFirstAppear {
|
||||
viewModel.send(.refresh)
|
||||
}
|
||||
|
|
|
@ -52,19 +52,23 @@ struct MediaView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
WrappedView {
|
||||
Group {
|
||||
ZStack {
|
||||
// This keeps the ErrorView vertically aligned with the PagingLibraryView
|
||||
Color.clear
|
||||
|
||||
switch viewModel.state {
|
||||
case .content:
|
||||
contentView
|
||||
case let .error(error):
|
||||
Text(error.localizedDescription)
|
||||
ErrorView(error: error)
|
||||
.onRetry {
|
||||
viewModel.send(.refresh)
|
||||
}
|
||||
case .initial, .refreshing:
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.transition(.opacity.animation(.linear(duration: 0.2)))
|
||||
}
|
||||
.animation(.linear(duration: 0.1), value: viewModel.state)
|
||||
.ignoresSafeArea()
|
||||
.onFirstAppear {
|
||||
viewModel.send(.refresh)
|
||||
|
|
|
@ -247,11 +247,10 @@ struct PagingLibraryView<Element: Poster & Identifiable>: View {
|
|||
|
||||
@ViewBuilder
|
||||
private func errorView(with error: some Error) -> some View {
|
||||
Text(error.localizedDescription)
|
||||
/* ErrorView(error: error)
|
||||
ErrorView(error: error)
|
||||
.onRetry {
|
||||
viewModel.send(.refresh)
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Grid View
|
||||
|
|
|
@ -78,7 +78,7 @@ struct ProgramsView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
WrappedView {
|
||||
ZStack {
|
||||
switch programsViewModel.state {
|
||||
case .content:
|
||||
if programsViewModel.hasNoResults {
|
||||
|
@ -87,11 +87,15 @@ struct ProgramsView: View {
|
|||
contentView
|
||||
}
|
||||
case let .error(error):
|
||||
Text(error.localizedDescription)
|
||||
ErrorView(error: error)
|
||||
.onRetry {
|
||||
programsViewModel.send(.refresh)
|
||||
}
|
||||
case .initial, .refreshing:
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.animation(.linear(duration: 0.1), value: programsViewModel.state)
|
||||
.ignoresSafeArea(edges: [.bottom, .horizontal])
|
||||
.onFirstAppear {
|
||||
if programsViewModel.state == .initial {
|
||||
|
|
|
@ -47,7 +47,7 @@ struct QuickConnectView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
WrappedView {
|
||||
ZStack {
|
||||
switch viewModel.state {
|
||||
case .idle, .authenticated:
|
||||
Color.clear
|
||||
|
@ -56,10 +56,13 @@ struct QuickConnectView: View {
|
|||
case let .polling(code):
|
||||
pollingView(code: code)
|
||||
case let .error(error):
|
||||
Text(error.localizedDescription)
|
||||
// ErrorView(error: error)
|
||||
ErrorView(error: error)
|
||||
.onRetry {
|
||||
viewModel.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
.animation(.linear(duration: 0.1), value: viewModel.state)
|
||||
.edgePadding()
|
||||
.navigationTitle(L10n.quickConnect)
|
||||
.onFirstAppear {
|
||||
|
|
|
@ -110,11 +110,8 @@ struct SearchView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
WrappedView {
|
||||
Group {
|
||||
ZStack {
|
||||
switch viewModel.state {
|
||||
case let .error(error):
|
||||
Text(error.localizedDescription)
|
||||
case .initial:
|
||||
suggestionsView
|
||||
case .content:
|
||||
|
@ -123,12 +120,16 @@ struct SearchView: View {
|
|||
} else {
|
||||
resultsView
|
||||
}
|
||||
case let .error(error):
|
||||
ErrorView(error: error)
|
||||
.onRetry {
|
||||
viewModel.send(.search(query: searchQuery))
|
||||
}
|
||||
case .searching:
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.transition(.opacity.animation(.linear(duration: 0.2)))
|
||||
}
|
||||
.animation(.linear(duration: 0.1), value: viewModel.state)
|
||||
.ignoresSafeArea(edges: [.bottom, .horizontal])
|
||||
.onFirstAppear {
|
||||
viewModel.send(.getSuggestions)
|
||||
|
|
|
@ -78,7 +78,7 @@ extension SelectUserView {
|
|||
ListRowButton(L10n.delete, role: .destructive) {
|
||||
onDelete()
|
||||
}
|
||||
.frame(width: 400, height: 50)
|
||||
.frame(width: 400, height: 75)
|
||||
.disabled(!areUsersSelected)
|
||||
}
|
||||
|
||||
|
|
|
@ -44,22 +44,14 @@ struct SettingsView: View {
|
|||
.onSelect {
|
||||
router.route(to: \.serverDetail, viewModel.userSession.server)
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
Section {
|
||||
ListRowButton(L10n.switchUser) {
|
||||
viewModel.signOut()
|
||||
} label: {
|
||||
HStack {
|
||||
|
||||
Text(L10n.switchUser)
|
||||
.foregroundColor(.jellyfinPurple)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "chevron.right")
|
||||
.font(.body.weight(.regular))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
.foregroundStyle(Color.jellyfinPurple.overlayColor, Color.jellyfinPurple)
|
||||
.listRowInsets(.zero)
|
||||
}
|
||||
|
||||
Section(L10n.videoPlayer) {
|
||||
|
|
|
@ -85,10 +85,9 @@ struct UserSignInView: View {
|
|||
}
|
||||
|
||||
if case .signingIn = viewModel.state {
|
||||
ListRowButton(L10n.cancel) {
|
||||
ListRowButton(L10n.cancel, role: .cancel) {
|
||||
viewModel.send(.cancel)
|
||||
}
|
||||
.foregroundStyle(.red, accentColor)
|
||||
.padding(.vertical)
|
||||
} else {
|
||||
ListRowButton(L10n.signIn) {
|
||||
|
|
|
@ -244,6 +244,7 @@
|
|||
4EED874B2CBF824B002354D2 /* DevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EED87482CBF824B002354D2 /* DevicesView.swift */; };
|
||||
4EED87512CBF84AD002354D2 /* DevicesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EED874F2CBF84AD002354D2 /* DevicesViewModel.swift */; };
|
||||
4EEEEA242CFA8E1500527D79 /* NavigationBarMenuButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EEEEA232CFA8E1500527D79 /* NavigationBarMenuButton.swift */; };
|
||||
4EF0DCA92D49751B005A5194 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EF0DCA82D49751B005A5194 /* ErrorView.swift */; };
|
||||
4EF18B262CB9934C00343666 /* LibraryRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EF18B252CB9934700343666 /* LibraryRow.swift */; };
|
||||
4EF18B282CB9936D00343666 /* ListColumnsPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EF18B272CB9936400343666 /* ListColumnsPickerView.swift */; };
|
||||
4EF18B2A2CB993BD00343666 /* ListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EF18B292CB993AD00343666 /* ListRow.swift */; };
|
||||
|
@ -1015,7 +1016,6 @@
|
|||
E1A3E4CF2BB7E02B005C59F8 /* DelayedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A3E4CE2BB7E02B005C59F8 /* DelayedProgressView.swift */; };
|
||||
E1A3E4D12BB7F5BF005C59F8 /* ErrorCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A3E4D02BB7F5BF005C59F8 /* ErrorCard.swift */; };
|
||||
E1A42E4A28CA6CCD00A14DCB /* CinematicItemSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A42E4928CA6CCD00A14DCB /* CinematicItemSelector.swift */; };
|
||||
E1A42E4F28CBD3E100A14DCB /* HomeErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A42E4E28CBD3E100A14DCB /* HomeErrorView.swift */; };
|
||||
E1A42E5128CBE44500A14DCB /* LandscapePosterProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A42E5028CBE44500A14DCB /* LandscapePosterProgressBar.swift */; };
|
||||
E1A5056A2D0B733F007EE305 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A505692D0B733F007EE305 /* Optional.swift */; };
|
||||
E1A5056B2D0B733F007EE305 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A505692D0B733F007EE305 /* Optional.swift */; };
|
||||
|
@ -1456,6 +1456,7 @@
|
|||
4EED87482CBF824B002354D2 /* DevicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicesView.swift; sourceTree = "<group>"; };
|
||||
4EED874F2CBF84AD002354D2 /* DevicesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicesViewModel.swift; sourceTree = "<group>"; };
|
||||
4EEEEA232CFA8E1500527D79 /* NavigationBarMenuButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarMenuButton.swift; sourceTree = "<group>"; };
|
||||
4EF0DCA82D49751B005A5194 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; };
|
||||
4EF18B252CB9934700343666 /* LibraryRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryRow.swift; sourceTree = "<group>"; };
|
||||
4EF18B272CB9936400343666 /* ListColumnsPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListColumnsPickerView.swift; sourceTree = "<group>"; };
|
||||
4EF18B292CB993AD00343666 /* ListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRow.swift; sourceTree = "<group>"; };
|
||||
|
@ -1953,7 +1954,6 @@
|
|||
E1A3E4CE2BB7E02B005C59F8 /* DelayedProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelayedProgressView.swift; sourceTree = "<group>"; };
|
||||
E1A3E4D02BB7F5BF005C59F8 /* ErrorCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorCard.swift; sourceTree = "<group>"; };
|
||||
E1A42E4928CA6CCD00A14DCB /* CinematicItemSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicItemSelector.swift; sourceTree = "<group>"; };
|
||||
E1A42E4E28CBD3E100A14DCB /* HomeErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeErrorView.swift; sourceTree = "<group>"; };
|
||||
E1A42E5028CBE44500A14DCB /* LandscapePosterProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LandscapePosterProgressBar.swift; sourceTree = "<group>"; };
|
||||
E1A505692D0B733F007EE305 /* Optional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Optional.swift; sourceTree = "<group>"; };
|
||||
E1A7F0DE2BD4EC7400620DDD /* Dictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = "<group>"; };
|
||||
|
@ -3361,6 +3361,7 @@
|
|||
E1A42E4928CA6CCD00A14DCB /* CinematicItemSelector.swift */,
|
||||
E1C92618288756BD002A7A66 /* DotHStack.swift */,
|
||||
E12E30F4296392EC0022FAC9 /* EnumPickerView.swift */,
|
||||
4EF0DCA82D49751B005A5194 /* ErrorView.swift */,
|
||||
E1549677296CB22B00C4EF88 /* InlineEnumToggle.swift */,
|
||||
E1A42E5028CBE44500A14DCB /* LandscapePosterProgressBar.swift */,
|
||||
E1763A632BF3C9AA004DF6AB /* ListRowButton.swift */,
|
||||
|
@ -4968,7 +4969,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
E12CC1C328D12D6300678D5D /* Components */,
|
||||
E1A42E4E28CBD3E100A14DCB /* HomeErrorView.swift */,
|
||||
531690E6267ABD79005D8AB9 /* HomeView.swift */,
|
||||
);
|
||||
path = HomeView;
|
||||
|
@ -5931,7 +5931,6 @@
|
|||
4E2AC4C32C6C491200DD600D /* AudoCodec.swift in Sources */,
|
||||
E1575EA6293E7D40001665B1 /* VideoPlayer.swift in Sources */,
|
||||
E185920628CDAA6400326F80 /* CastAndCrewHStack.swift in Sources */,
|
||||
E1A42E4F28CBD3E100A14DCB /* HomeErrorView.swift in Sources */,
|
||||
4E8F74AB2CE03DD300CC8969 /* DeleteItemViewModel.swift in Sources */,
|
||||
53CD2A40268A49C2002ABD4E /* ItemView.swift in Sources */,
|
||||
E122A9142788EAAD0060FA63 /* MediaStream.swift in Sources */,
|
||||
|
@ -6107,6 +6106,7 @@
|
|||
E1575E84293E7A00001665B1 /* PrimaryAppIcon.swift in Sources */,
|
||||
E1153DCD2BBB633B00424D36 /* FastSVGView.swift in Sources */,
|
||||
E1ED7FE22CAA6BAF00ACB6E3 /* ServerLogsViewModel.swift in Sources */,
|
||||
4EF0DCA92D49751B005A5194 /* ErrorView.swift in Sources */,
|
||||
E1CB75762C80EAFA00217C76 /* ArrayBuilder.swift in Sources */,
|
||||
E102315B2BCF8AF8009D71FC /* ProgramProgressOverlay.swift in Sources */,
|
||||
E1E6C45129B104850064123F /* Button.swift in Sources */,
|
||||
|
|
Loading…
Reference in New Issue