Transition Media View (#541)
This commit is contained in:
parent
98a5507b52
commit
d078d71393
|
@ -1,46 +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) 2022 Jellyfin & Jellyfin Contributors
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import Stinsen
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
final class LibraryListCoordinator: NavigationCoordinatable {
|
|
||||||
|
|
||||||
let stack = NavigationStack(initial: \LibraryListCoordinator.start)
|
|
||||||
|
|
||||||
@Root
|
|
||||||
var start = makeStart
|
|
||||||
@Route(.push)
|
|
||||||
var library = makeLibrary
|
|
||||||
#if os(iOS)
|
|
||||||
@Route(.push)
|
|
||||||
var liveTV = makeLiveTV
|
|
||||||
#endif
|
|
||||||
|
|
||||||
let viewModel: LibraryListViewModel
|
|
||||||
|
|
||||||
init(viewModel: LibraryListViewModel) {
|
|
||||||
self.viewModel = viewModel
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeLibrary(params: LibraryCoordinatorParams) -> LibraryCoordinator {
|
|
||||||
LibraryCoordinator(viewModel: params.viewModel, title: params.title)
|
|
||||||
}
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
func makeLiveTV() -> LiveTVCoordinator {
|
|
||||||
LiveTVCoordinator()
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
func makeStart() -> some View {
|
|
||||||
LibraryListView(viewModel: self.viewModel)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,15 +14,15 @@ final class MainTabCoordinator: TabCoordinatable {
|
||||||
var child = TabChild(startingItems: [
|
var child = TabChild(startingItems: [
|
||||||
\MainTabCoordinator.home,
|
\MainTabCoordinator.home,
|
||||||
\MainTabCoordinator.search,
|
\MainTabCoordinator.search,
|
||||||
\MainTabCoordinator.allMedia,
|
\MainTabCoordinator.media,
|
||||||
])
|
])
|
||||||
|
|
||||||
@Route(tabItem: makeHomeTab, onTapped: onHomeTapped)
|
@Route(tabItem: makeHomeTab, onTapped: onHomeTapped)
|
||||||
var home = makeHome
|
var home = makeHome
|
||||||
@Route(tabItem: makeSearchTab, onTapped: onSearchTapped)
|
@Route(tabItem: makeSearchTab, onTapped: onSearchTapped)
|
||||||
var search = makeSearch
|
var search = makeSearch
|
||||||
@Route(tabItem: makeAllMediaTab, onTapped: onMediaTapped)
|
@Route(tabItem: makeMediaTab, onTapped: onMediaTapped)
|
||||||
var allMedia = makeAllMedia
|
var media = makeMedia
|
||||||
|
|
||||||
func makeHome() -> NavigationViewCoordinator<HomeCoordinator> {
|
func makeHome() -> NavigationViewCoordinator<HomeCoordinator> {
|
||||||
NavigationViewCoordinator(HomeCoordinator())
|
NavigationViewCoordinator(HomeCoordinator())
|
||||||
|
@ -56,20 +56,20 @@ final class MainTabCoordinator: TabCoordinatable {
|
||||||
L10n.search.text
|
L10n.search.text
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeAllMedia() -> NavigationViewCoordinator<LibraryListCoordinator> {
|
func makeMedia() -> NavigationViewCoordinator<MediaCoordinator> {
|
||||||
NavigationViewCoordinator(LibraryListCoordinator(viewModel: LibraryListViewModel()))
|
NavigationViewCoordinator(MediaCoordinator())
|
||||||
}
|
}
|
||||||
|
|
||||||
func onMediaTapped(isRepeat: Bool, coordinator: NavigationViewCoordinator<LibraryListCoordinator>) {
|
func onMediaTapped(isRepeat: Bool, coordinator: NavigationViewCoordinator<MediaCoordinator>) {
|
||||||
if isRepeat {
|
if isRepeat {
|
||||||
coordinator.child.popToRoot()
|
coordinator.child.popToRoot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
func makeAllMediaTab(isActive: Bool) -> some View {
|
func makeMediaTab(isActive: Bool) -> some View {
|
||||||
Image(systemName: "folder")
|
Image(systemName: "rectangle.stack.fill")
|
||||||
L10n.allMedia.text
|
L10n.media.text
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
|
|
@ -16,7 +16,7 @@ final class MainTabCoordinator: TabCoordinatable {
|
||||||
\MainTabCoordinator.tv,
|
\MainTabCoordinator.tv,
|
||||||
\MainTabCoordinator.movies,
|
\MainTabCoordinator.movies,
|
||||||
\MainTabCoordinator.search,
|
\MainTabCoordinator.search,
|
||||||
\MainTabCoordinator.other,
|
\MainTabCoordinator.media,
|
||||||
\MainTabCoordinator.settings,
|
\MainTabCoordinator.settings,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ final class MainTabCoordinator: TabCoordinatable {
|
||||||
var movies = makeMovies
|
var movies = makeMovies
|
||||||
@Route(tabItem: makeSearchTab)
|
@Route(tabItem: makeSearchTab)
|
||||||
var search = makeSearch
|
var search = makeSearch
|
||||||
@Route(tabItem: makeOtherTab)
|
@Route(tabItem: makeMediaTab)
|
||||||
var other = makeOther
|
var media = makeMedia
|
||||||
@Route(tabItem: makeSettingsTab)
|
@Route(tabItem: makeSettingsTab)
|
||||||
var settings = makeSettings
|
var settings = makeSettings
|
||||||
|
|
||||||
|
@ -81,15 +81,15 @@ final class MainTabCoordinator: TabCoordinatable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeOther() -> NavigationViewCoordinator<LibraryListCoordinator> {
|
func makeMedia() -> NavigationViewCoordinator<MediaCoordinator> {
|
||||||
NavigationViewCoordinator(LibraryListCoordinator(viewModel: LibraryListViewModel()))
|
NavigationViewCoordinator(MediaCoordinator())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
func makeOtherTab(isActive: Bool) -> some View {
|
func makeMediaTab(isActive: Bool) -> some View {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "folder")
|
Image(systemName: "rectangle.stack")
|
||||||
L10n.other.text
|
L10n.media.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
//
|
||||||
|
// 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) 2022 Jellyfin & Jellyfin Contributors
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Stinsen
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
final class MediaCoordinator: NavigationCoordinatable {
|
||||||
|
|
||||||
|
let stack = NavigationStack(initial: \MediaCoordinator.start)
|
||||||
|
|
||||||
|
@Root
|
||||||
|
var start = makeStart
|
||||||
|
#if os(tvOS)
|
||||||
|
@Route(.modal)
|
||||||
|
var library = makeLibrary
|
||||||
|
#else
|
||||||
|
@Route(.push)
|
||||||
|
var library = makeLibrary
|
||||||
|
@Route(.push)
|
||||||
|
var liveTV = makeLiveTV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if os(tvOS)
|
||||||
|
func makeLibrary(params: LibraryCoordinatorParams) -> NavigationViewCoordinator<LibraryCoordinator> {
|
||||||
|
NavigationViewCoordinator(LibraryCoordinator(viewModel: params.viewModel, title: params.title))
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
func makeLibrary(params: LibraryCoordinatorParams) -> LibraryCoordinator {
|
||||||
|
LibraryCoordinator(viewModel: params.viewModel, title: params.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeLiveTV() -> LiveTVCoordinator {
|
||||||
|
LiveTVCoordinator()
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
func makeStart() -> some View {
|
||||||
|
MediaView(viewModel: .init())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// 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) 2022 Jellyfin & Jellyfin Contributors
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Array {
|
||||||
|
func appending(_ element: Element) -> [Element] {
|
||||||
|
self + [element]
|
||||||
|
}
|
||||||
|
|
||||||
|
func appending(_ element: Element, if condition: Bool) -> [Element] {
|
||||||
|
if condition {
|
||||||
|
return self + [element]
|
||||||
|
} else {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func appending(_ contents: [Element]) -> [Element] {
|
||||||
|
self + contents
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// 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) 2022 Jellyfin & Jellyfin Contributors
|
||||||
|
//
|
||||||
|
|
||||||
|
import JellyfinAPI
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct LibraryItem: Equatable, Poster {
|
||||||
|
|
||||||
|
var library: BaseItemDto
|
||||||
|
var viewModel: MediaViewModel
|
||||||
|
var title: String = ""
|
||||||
|
var subtitle: String?
|
||||||
|
var showTitle: Bool = false
|
||||||
|
|
||||||
|
func portraitPosterImageSource(maxWidth: CGFloat) -> ImageSource {
|
||||||
|
.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func landscapePosterImageSources(maxWidth: CGFloat, single: Bool) -> [ImageSource] {
|
||||||
|
viewModel.libraryImages[library.id ?? ""] ?? []
|
||||||
|
}
|
||||||
|
|
||||||
|
static func == (lhs: LibraryItem, rhs: LibraryItem) -> Bool {
|
||||||
|
lhs.library == rhs.library &&
|
||||||
|
lhs.viewModel.libraryImages[lhs.library.id ?? ""] == rhs.viewModel.libraryImages[rhs.library.id ?? ""]
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ struct LibraryFilters: Codable, Hashable {
|
||||||
var sortBy: [SortBy] = [.name]
|
var sortBy: [SortBy] = [.name]
|
||||||
|
|
||||||
static let `default` = LibraryFilters()
|
static let `default` = LibraryFilters()
|
||||||
|
static let favorites: LibraryFilters = .init(filters: [.isFavorite], sortOrder: [.ascending], sortBy: [.name])
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SortBy: String, Codable, CaseIterable {
|
public enum SortBy: String, Codable, CaseIterable {
|
||||||
|
|
|
@ -1,47 +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) 2022 Jellyfin & Jellyfin Contributors
|
|
||||||
//
|
|
||||||
|
|
||||||
import Defaults
|
|
||||||
import Foundation
|
|
||||||
import JellyfinAPI
|
|
||||||
|
|
||||||
final class LibraryListViewModel: ViewModel {
|
|
||||||
|
|
||||||
@Published
|
|
||||||
var libraries: [BaseItemDto] = []
|
|
||||||
|
|
||||||
var filteredLibraries: [BaseItemDto] {
|
|
||||||
var supportedLibraries = ["movies", "tvshows", "unknown"]
|
|
||||||
|
|
||||||
if Defaults[.Experimental.liveTVAlphaEnabled] {
|
|
||||||
supportedLibraries.append("livetv")
|
|
||||||
}
|
|
||||||
|
|
||||||
return libraries.filter { supportedLibraries.contains($0.collectionType ?? "unknown") }
|
|
||||||
}
|
|
||||||
|
|
||||||
// temp
|
|
||||||
let withFavorites = LibraryFilters(filters: [.isFavorite], sortOrder: [], withGenres: [], sortBy: [])
|
|
||||||
|
|
||||||
override init() {
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
requestLibraries()
|
|
||||||
}
|
|
||||||
|
|
||||||
func requestLibraries() {
|
|
||||||
UserViewsAPI.getUserViews(userId: SessionManager.main.currentLogin.user.id)
|
|
||||||
.trackActivity(loading)
|
|
||||||
.sink(receiveCompletion: { completion in
|
|
||||||
self.handleAPIRequestError(completion: completion)
|
|
||||||
}, receiveValue: { response in
|
|
||||||
self.libraries = response.items ?? []
|
|
||||||
})
|
|
||||||
.store(in: &cancellables)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// 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) 2022 Jellyfin & Jellyfin Contributors
|
||||||
|
//
|
||||||
|
|
||||||
|
import Defaults
|
||||||
|
import Foundation
|
||||||
|
import JellyfinAPI
|
||||||
|
|
||||||
|
final class MediaViewModel: ViewModel {
|
||||||
|
|
||||||
|
@Published
|
||||||
|
var libraries: [BaseItemDto] = []
|
||||||
|
@Published
|
||||||
|
var libraryImages: [String: [ImageSource]] = [:]
|
||||||
|
|
||||||
|
private var supportedLibraries: [String] {
|
||||||
|
["movies", "tvshows", "unknown"]
|
||||||
|
.appending("livetv", if: Defaults[.Experimental.liveTVAlphaEnabled])
|
||||||
|
}
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
requestLibraries()
|
||||||
|
getRandomItemImageSource(with: [.isFavorite], id: nil, key: "favorites")
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestLibraries() {
|
||||||
|
UserViewsAPI.getUserViews(userId: SessionManager.main.currentLogin.user.id)
|
||||||
|
.trackActivity(loading)
|
||||||
|
.sink(receiveCompletion: { completion in
|
||||||
|
self.handleAPIRequestError(completion: completion)
|
||||||
|
}, receiveValue: { response in
|
||||||
|
guard let items = response.items else { return }
|
||||||
|
self.libraries = items.filter { self.supportedLibraries.contains($0.collectionType ?? "unknown") }
|
||||||
|
self.libraries.forEach {
|
||||||
|
self.getRandomItemImageSource(with: nil, id: $0.id, key: $0.id ?? "")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getRandomItemImageSource(with filters: [ItemFilter]?, id: String?, key: String) {
|
||||||
|
ItemsAPI.getItemsByUserId(
|
||||||
|
userId: SessionManager.main.currentLogin.user.id,
|
||||||
|
limit: 3,
|
||||||
|
recursive: true,
|
||||||
|
parentId: id,
|
||||||
|
includeItemTypes: [.movie, .series],
|
||||||
|
filters: filters,
|
||||||
|
sortBy: ["Random"]
|
||||||
|
)
|
||||||
|
.sink(receiveCompletion: { [weak self] completion in
|
||||||
|
self?.handleAPIRequestError(completion: completion)
|
||||||
|
}, receiveValue: { [weak self] response in
|
||||||
|
guard let items = response.items else { return }
|
||||||
|
let imageSources = items.map { $0.imageSource(.backdrop, maxWidth: 500) }
|
||||||
|
self?.libraryImages[key] = imageSources
|
||||||
|
})
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,7 +53,6 @@ final class SearchViewModel: ViewModel {
|
||||||
|
|
||||||
private func cancelPreviousSearch() {
|
private func cancelPreviousSearch() {
|
||||||
searchCancellables.forEach { $0.cancel() }
|
searchCancellables.forEach { $0.cancel() }
|
||||||
print(searchCancellables.count)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func search(with query: String) {
|
func search(with query: String) {
|
||||||
|
|
|
@ -61,12 +61,18 @@ struct PosterButton<Item: Poster, Content: View, ImageOverlay: View, ContextMenu
|
||||||
Button {
|
Button {
|
||||||
onSelect(item)
|
onSelect(item)
|
||||||
} label: {
|
} label: {
|
||||||
switch type {
|
Group {
|
||||||
case .portrait:
|
switch type {
|
||||||
ImageView(item.portraitPosterImageSource(maxWidth: itemWidth))
|
case .portrait:
|
||||||
.posterStyle(type: type, width: itemWidth)
|
ImageView(item.portraitPosterImageSource(maxWidth: itemWidth))
|
||||||
case .landscape:
|
.posterStyle(type: type, width: itemWidth)
|
||||||
ImageView(item.landscapePosterImageSources(maxWidth: itemWidth, single: singleImage))
|
case .landscape:
|
||||||
|
ImageView(item.landscapePosterImageSources(maxWidth: itemWidth, single: singleImage))
|
||||||
|
.posterStyle(type: type, width: itemWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.overlay {
|
||||||
|
imageOverlay(item)
|
||||||
.posterStyle(type: type, width: itemWidth)
|
.posterStyle(type: type, width: itemWidth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,10 +80,6 @@ struct PosterButton<Item: Poster, Content: View, ImageOverlay: View, ContextMenu
|
||||||
.contextMenu(menuItems: {
|
.contextMenu(menuItems: {
|
||||||
contextMenu(item)
|
contextMenu(item)
|
||||||
})
|
})
|
||||||
.overlay {
|
|
||||||
imageOverlay(item)
|
|
||||||
.posterStyle(type: type, width: itemWidth)
|
|
||||||
}
|
|
||||||
.posterShadow()
|
.posterShadow()
|
||||||
|
|
||||||
content(item)
|
content(item)
|
||||||
|
|
|
@ -1,66 +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) 2022 Jellyfin & Jellyfin Contributors
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import JellyfinAPI
|
|
||||||
import Stinsen
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct LibraryListView: View {
|
|
||||||
@EnvironmentObject
|
|
||||||
var mainCoordinator: MainCoordinator.Router
|
|
||||||
@EnvironmentObject
|
|
||||||
private var libraryListRouter: LibraryListCoordinator.Router
|
|
||||||
@StateObject
|
|
||||||
var viewModel = LibraryListViewModel()
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ScrollView {
|
|
||||||
LazyVStack {
|
|
||||||
if !viewModel.isLoading {
|
|
||||||
|
|
||||||
ForEach(viewModel.filteredLibraries, id: \.id) { library in
|
|
||||||
Button {
|
|
||||||
if library.collectionType == "livetv" {
|
|
||||||
self.mainCoordinator.root(\.liveTV)
|
|
||||||
} else {
|
|
||||||
self.libraryListRouter.route(
|
|
||||||
to: \.library,
|
|
||||||
(viewModel: LibraryViewModel(parentID: library.id), title: library.name ?? "")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
label: {
|
|
||||||
ZStack {
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
VStack {
|
|
||||||
Text(library.name ?? "")
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.font(.title2)
|
|
||||||
.fontWeight(.semibold)
|
|
||||||
}
|
|
||||||
Spacer()
|
|
||||||
}.padding(32)
|
|
||||||
}
|
|
||||||
.frame(minWidth: 100, maxWidth: .infinity)
|
|
||||||
.frame(height: 100)
|
|
||||||
}
|
|
||||||
.cornerRadius(10)
|
|
||||||
.shadow(radius: 5)
|
|
||||||
.padding(.bottom, 5)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ProgressView()
|
|
||||||
}
|
|
||||||
}.padding(.leading, 16)
|
|
||||||
.padding(.trailing, 16)
|
|
||||||
.padding(.top, 8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
//
|
||||||
|
// 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) 2022 Jellyfin & Jellyfin Contributors
|
||||||
|
//
|
||||||
|
|
||||||
|
import CollectionView
|
||||||
|
import JellyfinAPI
|
||||||
|
import Stinsen
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct MediaView: View {
|
||||||
|
|
||||||
|
@EnvironmentObject
|
||||||
|
private var router: MediaCoordinator.Router
|
||||||
|
@ObservedObject
|
||||||
|
var viewModel: MediaViewModel
|
||||||
|
|
||||||
|
private var libraryItems: [LibraryItem] {
|
||||||
|
[LibraryItem(library: .init(name: L10n.favorites, id: "favorites"), viewModel: viewModel)] +
|
||||||
|
viewModel.libraries.map { LibraryItem(library: $0, viewModel: viewModel) }
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
CollectionView(items: libraryItems) { _, item, _ in
|
||||||
|
PosterButton(item: item, type: .landscape)
|
||||||
|
.scaleItem(0.8)
|
||||||
|
.onSelect { _ in
|
||||||
|
if item.library.id == "favorites" {
|
||||||
|
router.route(to: \.library, (viewModel: .init(filters: .favorites), title: ""))
|
||||||
|
} else {
|
||||||
|
router.route(to: \.library, (viewModel: .init(parentID: item.library.id), title: ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.imageOverlay { _ in
|
||||||
|
ZStack {
|
||||||
|
Color.black
|
||||||
|
.opacity(0.5)
|
||||||
|
|
||||||
|
Text(item.library.displayName)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.font(.title2)
|
||||||
|
.fontWeight(.semibold)
|
||||||
|
.lineLimit(2)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.frame(alignment: .center)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.layout { _, layoutEnvironment in
|
||||||
|
.grid(
|
||||||
|
layoutEnvironment: layoutEnvironment,
|
||||||
|
layoutMode: .adaptive(withMinItemSize: 400),
|
||||||
|
lineSpacing: 50,
|
||||||
|
itemSize: .estimated(400),
|
||||||
|
sectionInsets: .zero
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.ignoresSafeArea()
|
||||||
|
}
|
||||||
|
}
|
|
@ -75,7 +75,7 @@
|
||||||
539B2DA5263BA5B8007FF1A4 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539B2DA4263BA5B8007FF1A4 /* SettingsView.swift */; };
|
539B2DA5263BA5B8007FF1A4 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539B2DA4263BA5B8007FF1A4 /* SettingsView.swift */; };
|
||||||
53A83C33268A309300DF3D92 /* LibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A83C32268A309300DF3D92 /* LibraryView.swift */; };
|
53A83C33268A309300DF3D92 /* LibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A83C32268A309300DF3D92 /* LibraryView.swift */; };
|
||||||
53ABFDDC267972BF00886593 /* TVServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53ABFDDB267972BF00886593 /* TVServices.framework */; };
|
53ABFDDC267972BF00886593 /* TVServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53ABFDDB267972BF00886593 /* TVServices.framework */; };
|
||||||
53ABFDE4267974EF00886593 /* LibraryListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5742678C33500530A6E /* LibraryListViewModel.swift */; };
|
53ABFDE4267974EF00886593 /* MediaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5742678C33500530A6E /* MediaViewModel.swift */; };
|
||||||
53ABFDE5267974EF00886593 /* ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB57B2678CE1000530A6E /* ViewModel.swift */; };
|
53ABFDE5267974EF00886593 /* ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB57B2678CE1000530A6E /* ViewModel.swift */; };
|
||||||
53ABFDE6267974EF00886593 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5321753A2671BCFC005491E6 /* SettingsViewModel.swift */; };
|
53ABFDE6267974EF00886593 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5321753A2671BCFC005491E6 /* SettingsViewModel.swift */; };
|
||||||
53ABFDE7267974EF00886593 /* ConnectToServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */; };
|
53ABFDE7267974EF00886593 /* ConnectToServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */; };
|
||||||
|
@ -90,7 +90,7 @@
|
||||||
5D160403278A41FD00D22B99 /* VLCPlayer+subtitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D160402278A41FD00D22B99 /* VLCPlayer+subtitles.swift */; };
|
5D160403278A41FD00D22B99 /* VLCPlayer+subtitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D160402278A41FD00D22B99 /* VLCPlayer+subtitles.swift */; };
|
||||||
5D32EA12278C95E30020E292 /* VLCPlayer+subtitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D160402278A41FD00D22B99 /* VLCPlayer+subtitles.swift */; };
|
5D32EA12278C95E30020E292 /* VLCPlayer+subtitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D160402278A41FD00D22B99 /* VLCPlayer+subtitles.swift */; };
|
||||||
5D64683D277B1649009E09AE /* PreferenceUIHostingSwizzling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D64683C277B1649009E09AE /* PreferenceUIHostingSwizzling.swift */; };
|
5D64683D277B1649009E09AE /* PreferenceUIHostingSwizzling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D64683C277B1649009E09AE /* PreferenceUIHostingSwizzling.swift */; };
|
||||||
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213388F265F83A900A81A2A /* LibraryListView.swift */; };
|
62133890265F83A900A81A2A /* MediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213388F265F83A900A81A2A /* MediaView.swift */; };
|
||||||
621338932660107500A81A2A /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* StringExtensions.swift */; };
|
621338932660107500A81A2A /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* StringExtensions.swift */; };
|
||||||
6220D0AD26D5EABB00B8E046 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0AC26D5EABB00B8E046 /* ViewExtensions.swift */; };
|
6220D0AD26D5EABB00B8E046 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0AC26D5EABB00B8E046 /* ViewExtensions.swift */; };
|
||||||
6220D0AE26D5EABB00B8E046 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0AC26D5EABB00B8E046 /* ViewExtensions.swift */; };
|
6220D0AE26D5EABB00B8E046 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0AC26D5EABB00B8E046 /* ViewExtensions.swift */; };
|
||||||
|
@ -105,7 +105,7 @@
|
||||||
62400C4B287ED19600F6AD3D /* UDPBroadcast.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 637FCAF3287B5B2600C0A353 /* UDPBroadcast.xcframework */; };
|
62400C4B287ED19600F6AD3D /* UDPBroadcast.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 637FCAF3287B5B2600C0A353 /* UDPBroadcast.xcframework */; };
|
||||||
62400C4C287ED19600F6AD3D /* UDPBroadcast.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 637FCAF3287B5B2600C0A353 /* UDPBroadcast.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
62400C4C287ED19600F6AD3D /* UDPBroadcast.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 637FCAF3287B5B2600C0A353 /* UDPBroadcast.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5722678C32A00530A6E /* HomeViewModel.swift */; };
|
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5722678C32A00530A6E /* HomeViewModel.swift */; };
|
||||||
625CB5752678C33500530A6E /* LibraryListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5742678C33500530A6E /* LibraryListViewModel.swift */; };
|
625CB5752678C33500530A6E /* MediaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5742678C33500530A6E /* MediaViewModel.swift */; };
|
||||||
625CB5772678C34300530A6E /* ConnectToServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */; };
|
625CB5772678C34300530A6E /* ConnectToServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */; };
|
||||||
625CB57A2678C4A400530A6E /* ActivityIndicator in Frameworks */ = {isa = PBXBuildFile; productRef = 625CB5792678C4A400530A6E /* ActivityIndicator */; };
|
625CB57A2678C4A400530A6E /* ActivityIndicator in Frameworks */ = {isa = PBXBuildFile; productRef = 625CB5792678C4A400530A6E /* ActivityIndicator */; };
|
||||||
6264E88C273850380081A12A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6264E88B273850380081A12A /* Strings.swift */; };
|
6264E88C273850380081A12A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6264E88B273850380081A12A /* Strings.swift */; };
|
||||||
|
@ -152,7 +152,7 @@
|
||||||
62C29EA126D102A500C1D2E7 /* iOSMainTabCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA026D102A500C1D2E7 /* iOSMainTabCoordinator.swift */; };
|
62C29EA126D102A500C1D2E7 /* iOSMainTabCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA026D102A500C1D2E7 /* iOSMainTabCoordinator.swift */; };
|
||||||
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */; };
|
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */; };
|
||||||
62C29EA626D1036A00C1D2E7 /* HomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */; };
|
62C29EA626D1036A00C1D2E7 /* HomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */; };
|
||||||
62C29EA826D103D500C1D2E7 /* LibraryListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */; };
|
62C29EA826D103D500C1D2E7 /* MediaCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA726D103D500C1D2E7 /* MediaCoordinator.swift */; };
|
||||||
62C83B08288C6A630004ED0C /* FontPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C83B07288C6A630004ED0C /* FontPicker.swift */; };
|
62C83B08288C6A630004ED0C /* FontPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C83B07288C6A630004ED0C /* FontPicker.swift */; };
|
||||||
62E1DCC3273CE19800C9AE76 /* URLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */; };
|
62E1DCC3273CE19800C9AE76 /* URLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */; };
|
||||||
62E1DCC4273CE19800C9AE76 /* URLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */; };
|
62E1DCC4273CE19800C9AE76 /* URLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */; };
|
||||||
|
@ -220,7 +220,7 @@
|
||||||
C4BE07892728448B003F4AD1 /* LiveTVChannelsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */; };
|
C4BE07892728448B003F4AD1 /* LiveTVChannelsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */; };
|
||||||
C4BE078C272844AF003F4AD1 /* LiveTVChannelsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE078A272844AF003F4AD1 /* LiveTVChannelsView.swift */; };
|
C4BE078C272844AF003F4AD1 /* LiveTVChannelsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE078A272844AF003F4AD1 /* LiveTVChannelsView.swift */; };
|
||||||
C4BE078E27298818003F4AD1 /* LiveTVHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE078D27298817003F4AD1 /* LiveTVHomeView.swift */; };
|
C4BE078E27298818003F4AD1 /* LiveTVHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE078D27298817003F4AD1 /* LiveTVHomeView.swift */; };
|
||||||
C4E5081B2703F82A0045C9AB /* LibraryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E508172703E8190045C9AB /* LibraryListView.swift */; };
|
C4E5081B2703F82A0045C9AB /* MediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E508172703E8190045C9AB /* MediaView.swift */; };
|
||||||
C4E5598928124C10003DECA5 /* LiveTVChannelItemElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5598828124C10003DECA5 /* LiveTVChannelItemElement.swift */; };
|
C4E5598928124C10003DECA5 /* LiveTVChannelItemElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5598828124C10003DECA5 /* LiveTVChannelItemElement.swift */; };
|
||||||
E1002B5F2793C3BE00E47059 /* VLCPlayerChapterOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1002B5E2793C3BE00E47059 /* VLCPlayerChapterOverlayView.swift */; };
|
E1002B5F2793C3BE00E47059 /* VLCPlayerChapterOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1002B5E2793C3BE00E47059 /* VLCPlayerChapterOverlayView.swift */; };
|
||||||
E1002B642793CEE800E47059 /* ChapterInfoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1002B632793CEE700E47059 /* ChapterInfoExtensions.swift */; };
|
E1002B642793CEE800E47059 /* ChapterInfoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1002B632793CEE700E47059 /* ChapterInfoExtensions.swift */; };
|
||||||
|
@ -391,7 +391,7 @@
|
||||||
E193D53427193F7F00900D82 /* HomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */; };
|
E193D53427193F7F00900D82 /* HomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */; };
|
||||||
E193D53527193F8100900D82 /* ItemCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */; };
|
E193D53527193F8100900D82 /* ItemCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */; };
|
||||||
E193D53627193F8500900D82 /* LibraryCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0B326D5ED8000B8E046 /* LibraryCoordinator.swift */; };
|
E193D53627193F8500900D82 /* LibraryCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0B326D5ED8000B8E046 /* LibraryCoordinator.swift */; };
|
||||||
E193D53727193F8700900D82 /* LibraryListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */; };
|
E193D53727193F8700900D82 /* MediaCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA726D103D500C1D2E7 /* MediaCoordinator.swift */; };
|
||||||
E193D53927193F8E00900D82 /* SearchCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0B626D5EE1100B8E046 /* SearchCoordinator.swift */; };
|
E193D53927193F8E00900D82 /* SearchCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0B626D5EE1100B8E046 /* SearchCoordinator.swift */; };
|
||||||
E193D53A27193F9000900D82 /* ServerListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3E827177ED6009D4DAF /* ServerListCoordinator.swift */; };
|
E193D53A27193F9000900D82 /* ServerListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3E827177ED6009D4DAF /* ServerListCoordinator.swift */; };
|
||||||
E193D53B27193F9200900D82 /* SettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0B026D5EC9900B8E046 /* SettingsCoordinator.swift */; };
|
E193D53B27193F9200900D82 /* SettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0B026D5EC9900B8E046 /* SettingsCoordinator.swift */; };
|
||||||
|
@ -478,6 +478,10 @@
|
||||||
E1E1643A28BAC2EF00323B0A /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1643928BAC2EF00323B0A /* SearchView.swift */; };
|
E1E1643A28BAC2EF00323B0A /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1643928BAC2EF00323B0A /* SearchView.swift */; };
|
||||||
E1E1643E28BB074000323B0A /* MultiSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1643D28BB074000323B0A /* MultiSelectorView.swift */; };
|
E1E1643E28BB074000323B0A /* MultiSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1643D28BB074000323B0A /* MultiSelectorView.swift */; };
|
||||||
E1E1643F28BB075C00323B0A /* MultiSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1643D28BB074000323B0A /* MultiSelectorView.swift */; };
|
E1E1643F28BB075C00323B0A /* MultiSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1643D28BB074000323B0A /* MultiSelectorView.swift */; };
|
||||||
|
E1E1644128BB301900323B0A /* ArrayExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1644028BB301900323B0A /* ArrayExtensions.swift */; };
|
||||||
|
E1E1644228BB301900323B0A /* ArrayExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1644028BB301900323B0A /* ArrayExtensions.swift */; };
|
||||||
|
E1E1644428BC60C600323B0A /* LibraryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1644328BC60C600323B0A /* LibraryItem.swift */; };
|
||||||
|
E1E1644528BC60C600323B0A /* LibraryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E1644328BC60C600323B0A /* LibraryItem.swift */; };
|
||||||
E1E48CC9271E6D410021A2F9 /* RefreshHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E48CC8271E6D410021A2F9 /* RefreshHelper.swift */; };
|
E1E48CC9271E6D410021A2F9 /* RefreshHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E48CC8271E6D410021A2F9 /* RefreshHelper.swift */; };
|
||||||
E1E5D5442783BB5100692DFE /* ItemDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E5D5432783BB5100692DFE /* ItemDetailsView.swift */; };
|
E1E5D5442783BB5100692DFE /* ItemDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E5D5432783BB5100692DFE /* ItemDetailsView.swift */; };
|
||||||
E1E5D5492783CDD700692DFE /* OverlaySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E5D5472783CCF900692DFE /* OverlaySettingsView.swift */; };
|
E1E5D5492783CDD700692DFE /* OverlaySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E5D5472783CCF900692DFE /* OverlaySettingsView.swift */; };
|
||||||
|
@ -618,7 +622,7 @@
|
||||||
5D1603FB278A3D5700D22B99 /* SubtitleSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleSize.swift; sourceTree = "<group>"; };
|
5D1603FB278A3D5700D22B99 /* SubtitleSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleSize.swift; sourceTree = "<group>"; };
|
||||||
5D160402278A41FD00D22B99 /* VLCPlayer+subtitles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VLCPlayer+subtitles.swift"; sourceTree = "<group>"; };
|
5D160402278A41FD00D22B99 /* VLCPlayer+subtitles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VLCPlayer+subtitles.swift"; sourceTree = "<group>"; };
|
||||||
5D64683C277B1649009E09AE /* PreferenceUIHostingSwizzling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceUIHostingSwizzling.swift; sourceTree = "<group>"; };
|
5D64683C277B1649009E09AE /* PreferenceUIHostingSwizzling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceUIHostingSwizzling.swift; sourceTree = "<group>"; };
|
||||||
6213388F265F83A900A81A2A /* LibraryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListView.swift; sourceTree = "<group>"; };
|
6213388F265F83A900A81A2A /* MediaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaView.swift; sourceTree = "<group>"; };
|
||||||
621338922660107500A81A2A /* StringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = "<group>"; };
|
621338922660107500A81A2A /* StringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = "<group>"; };
|
||||||
6220D0AC26D5EABB00B8E046 /* ViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtensions.swift; sourceTree = "<group>"; };
|
6220D0AC26D5EABB00B8E046 /* ViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtensions.swift; sourceTree = "<group>"; };
|
||||||
6220D0B026D5EC9900B8E046 /* SettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCoordinator.swift; sourceTree = "<group>"; };
|
6220D0B026D5EC9900B8E046 /* SettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCoordinator.swift; sourceTree = "<group>"; };
|
||||||
|
@ -629,7 +633,7 @@
|
||||||
6220D0C526D62D8700B8E046 /* iOSVideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSVideoPlayerCoordinator.swift; sourceTree = "<group>"; };
|
6220D0C526D62D8700B8E046 /* iOSVideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSVideoPlayerCoordinator.swift; sourceTree = "<group>"; };
|
||||||
6220D0CB26D640C400B8E046 /* AppURLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppURLHandler.swift; sourceTree = "<group>"; };
|
6220D0CB26D640C400B8E046 /* AppURLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppURLHandler.swift; sourceTree = "<group>"; };
|
||||||
625CB5722678C32A00530A6E /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = "<group>"; };
|
625CB5722678C32A00530A6E /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = "<group>"; };
|
||||||
625CB5742678C33500530A6E /* LibraryListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListViewModel.swift; sourceTree = "<group>"; };
|
625CB5742678C33500530A6E /* MediaViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaViewModel.swift; sourceTree = "<group>"; };
|
||||||
625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerViewModel.swift; sourceTree = "<group>"; };
|
625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerViewModel.swift; sourceTree = "<group>"; };
|
||||||
625CB57B2678CE1000530A6E /* ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModel.swift; sourceTree = "<group>"; };
|
625CB57B2678CE1000530A6E /* ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModel.swift; sourceTree = "<group>"; };
|
||||||
625CB57D2678E81E00530A6E /* TVVLCKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = TVVLCKit.xcframework; path = Carthage/Build/TVVLCKit.xcframework; sourceTree = "<group>"; };
|
625CB57D2678E81E00530A6E /* TVVLCKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = TVVLCKit.xcframework; path = Carthage/Build/TVVLCKit.xcframework; sourceTree = "<group>"; };
|
||||||
|
@ -668,7 +672,7 @@
|
||||||
62C29EA026D102A500C1D2E7 /* iOSMainTabCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSMainTabCoordinator.swift; sourceTree = "<group>"; };
|
62C29EA026D102A500C1D2E7 /* iOSMainTabCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSMainTabCoordinator.swift; sourceTree = "<group>"; };
|
||||||
62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerCoodinator.swift; sourceTree = "<group>"; };
|
62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerCoodinator.swift; sourceTree = "<group>"; };
|
||||||
62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCoordinator.swift; sourceTree = "<group>"; };
|
62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCoordinator.swift; sourceTree = "<group>"; };
|
||||||
62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListCoordinator.swift; sourceTree = "<group>"; };
|
62C29EA726D103D500C1D2E7 /* MediaCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaCoordinator.swift; sourceTree = "<group>"; };
|
||||||
62C83B07288C6A630004ED0C /* FontPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontPicker.swift; sourceTree = "<group>"; };
|
62C83B07288C6A630004ED0C /* FontPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontPicker.swift; sourceTree = "<group>"; };
|
||||||
62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtensions.swift; sourceTree = "<group>"; };
|
62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtensions.swift; sourceTree = "<group>"; };
|
||||||
62E632D9267D2BC40063E547 /* LatestMediaViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestMediaViewModel.swift; sourceTree = "<group>"; };
|
62E632D9267D2BC40063E547 /* LatestMediaViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestMediaViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
@ -715,7 +719,7 @@
|
||||||
C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVChannelsCoordinator.swift; sourceTree = "<group>"; };
|
C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVChannelsCoordinator.swift; sourceTree = "<group>"; };
|
||||||
C4BE078A272844AF003F4AD1 /* LiveTVChannelsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVChannelsView.swift; sourceTree = "<group>"; };
|
C4BE078A272844AF003F4AD1 /* LiveTVChannelsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVChannelsView.swift; sourceTree = "<group>"; };
|
||||||
C4BE078D27298817003F4AD1 /* LiveTVHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVHomeView.swift; sourceTree = "<group>"; };
|
C4BE078D27298817003F4AD1 /* LiveTVHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVHomeView.swift; sourceTree = "<group>"; };
|
||||||
C4E508172703E8190045C9AB /* LibraryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListView.swift; sourceTree = "<group>"; };
|
C4E508172703E8190045C9AB /* MediaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaView.swift; sourceTree = "<group>"; };
|
||||||
C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVChannelItemElement.swift; sourceTree = "<group>"; };
|
C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVChannelItemElement.swift; sourceTree = "<group>"; };
|
||||||
C4E5598828124C10003DECA5 /* LiveTVChannelItemElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiveTVChannelItemElement.swift; sourceTree = "<group>"; };
|
C4E5598828124C10003DECA5 /* LiveTVChannelItemElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiveTVChannelItemElement.swift; sourceTree = "<group>"; };
|
||||||
E1002B5E2793C3BE00E47059 /* VLCPlayerChapterOverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCPlayerChapterOverlayView.swift; sourceTree = "<group>"; };
|
E1002B5E2793C3BE00E47059 /* VLCPlayerChapterOverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCPlayerChapterOverlayView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -891,6 +895,8 @@
|
||||||
E1E00A34278628A40022235B /* DoubleExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleExtensions.swift; sourceTree = "<group>"; };
|
E1E00A34278628A40022235B /* DoubleExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleExtensions.swift; sourceTree = "<group>"; };
|
||||||
E1E1643928BAC2EF00323B0A /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
|
E1E1643928BAC2EF00323B0A /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
|
||||||
E1E1643D28BB074000323B0A /* MultiSelectorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiSelectorView.swift; sourceTree = "<group>"; };
|
E1E1643D28BB074000323B0A /* MultiSelectorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiSelectorView.swift; sourceTree = "<group>"; };
|
||||||
|
E1E1644028BB301900323B0A /* ArrayExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayExtensions.swift; sourceTree = "<group>"; };
|
||||||
|
E1E1644328BC60C600323B0A /* LibraryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryItem.swift; sourceTree = "<group>"; };
|
||||||
E1E48CC8271E6D410021A2F9 /* RefreshHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshHelper.swift; sourceTree = "<group>"; };
|
E1E48CC8271E6D410021A2F9 /* RefreshHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshHelper.swift; sourceTree = "<group>"; };
|
||||||
E1E5D5432783BB5100692DFE /* ItemDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDetailsView.swift; sourceTree = "<group>"; };
|
E1E5D5432783BB5100692DFE /* ItemDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDetailsView.swift; sourceTree = "<group>"; };
|
||||||
E1E5D5472783CCF900692DFE /* OverlaySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlaySettingsView.swift; sourceTree = "<group>"; };
|
E1E5D5472783CCF900692DFE /* OverlaySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlaySettingsView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1028,10 +1034,10 @@
|
||||||
E107BB9127880A4000354E07 /* ItemViewModel */,
|
E107BB9127880A4000354E07 /* ItemViewModel */,
|
||||||
62E632D9267D2BC40063E547 /* LatestMediaViewModel.swift */,
|
62E632D9267D2BC40063E547 /* LatestMediaViewModel.swift */,
|
||||||
62E632EE267D43320063E547 /* LibraryFilterViewModel.swift */,
|
62E632EE267D43320063E547 /* LibraryFilterViewModel.swift */,
|
||||||
625CB5742678C33500530A6E /* LibraryListViewModel.swift */,
|
|
||||||
62E632DF267D30CA0063E547 /* LibraryViewModel.swift */,
|
62E632DF267D30CA0063E547 /* LibraryViewModel.swift */,
|
||||||
C4BE07842728446F003F4AD1 /* LiveTVChannelsViewModel.swift */,
|
C4BE07842728446F003F4AD1 /* LiveTVChannelsViewModel.swift */,
|
||||||
C4BE07752725EBEA003F4AD1 /* LiveTVProgramsViewModel.swift */,
|
C4BE07752725EBEA003F4AD1 /* LiveTVProgramsViewModel.swift */,
|
||||||
|
625CB5742678C33500530A6E /* MediaViewModel.swift */,
|
||||||
C40CD924271F8D1E000FB198 /* MovieLibrariesViewModel.swift */,
|
C40CD924271F8D1E000FB198 /* MovieLibrariesViewModel.swift */,
|
||||||
6334175C287DE0D0000603CE /* QuickConnectSettingsViewModel.swift */,
|
6334175C287DE0D0000603CE /* QuickConnectSettingsViewModel.swift */,
|
||||||
62E632DB267D2E130063E547 /* SearchViewModel.swift */,
|
62E632DB267D2E130063E547 /* SearchViewModel.swift */,
|
||||||
|
@ -1144,6 +1150,7 @@
|
||||||
62EC353326766B03000E9F2D /* DeviceRotationViewModifier.swift */,
|
62EC353326766B03000E9F2D /* DeviceRotationViewModifier.swift */,
|
||||||
E19169CD272514760085832A /* HTTPScheme.swift */,
|
E19169CD272514760085832A /* HTTPScheme.swift */,
|
||||||
E1C925F328875037002A7A66 /* ItemViewType.swift */,
|
E1C925F328875037002A7A66 /* ItemViewType.swift */,
|
||||||
|
E1E1644328BC60C600323B0A /* LibraryItem.swift */,
|
||||||
E1AA331E2782639D00F6439C /* OverlayType.swift */,
|
E1AA331E2782639D00F6439C /* OverlayType.swift */,
|
||||||
E1C925F62887504B002A7A66 /* PanDirectionGestureRecognizer.swift */,
|
E1C925F62887504B002A7A66 /* PanDirectionGestureRecognizer.swift */,
|
||||||
E193D4DA27193CCA00900D82 /* PillStackable.swift */,
|
E193D4DA27193CCA00900D82 /* PillStackable.swift */,
|
||||||
|
@ -1421,6 +1428,7 @@
|
||||||
621338912660106C00A81A2A /* Extensions */ = {
|
621338912660106C00A81A2A /* Extensions */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E1E1644028BB301900323B0A /* ArrayExtensions.swift */,
|
||||||
E1A2C157279A7D76005EC829 /* BundleExtensions.swift */,
|
E1A2C157279A7D76005EC829 /* BundleExtensions.swift */,
|
||||||
E10EAA4E277BBCC4000269ED /* CGSizeExtensions.swift */,
|
E10EAA4E277BBCC4000269ED /* CGSizeExtensions.swift */,
|
||||||
6267B3D526710B8900A7371D /* CollectionExtensions.swift */,
|
6267B3D526710B8900A7371D /* CollectionExtensions.swift */,
|
||||||
|
@ -1460,12 +1468,12 @@
|
||||||
6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */,
|
6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */,
|
||||||
E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */,
|
E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */,
|
||||||
6220D0B326D5ED8000B8E046 /* LibraryCoordinator.swift */,
|
6220D0B326D5ED8000B8E046 /* LibraryCoordinator.swift */,
|
||||||
62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */,
|
|
||||||
C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */,
|
C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */,
|
||||||
C45942C427F67DA400C54FE7 /* LiveTVCoordinator.swift */,
|
C45942C427F67DA400C54FE7 /* LiveTVCoordinator.swift */,
|
||||||
C4BE07702725EB06003F4AD1 /* LiveTVProgramsCoordinator.swift */,
|
C4BE07702725EB06003F4AD1 /* LiveTVProgramsCoordinator.swift */,
|
||||||
C4BE07782726EE82003F4AD1 /* LiveTVTabCoordinator.swift */,
|
C4BE07782726EE82003F4AD1 /* LiveTVTabCoordinator.swift */,
|
||||||
E193D5412719404B00900D82 /* MainCoordinator */,
|
E193D5412719404B00900D82 /* MainCoordinator */,
|
||||||
|
62C29EA726D103D500C1D2E7 /* MediaCoordinator.swift */,
|
||||||
C40CD921271F8CD8000FB198 /* MoviesLibrariesCoordinator.swift */,
|
C40CD921271F8CD8000FB198 /* MoviesLibrariesCoordinator.swift */,
|
||||||
E18CE0B828A2322D0092E7F1 /* QuickConnectCoordinator.swift */,
|
E18CE0B828A2322D0092E7F1 /* QuickConnectCoordinator.swift */,
|
||||||
6220D0B626D5EE1100B8E046 /* SearchCoordinator.swift */,
|
6220D0B626D5EE1100B8E046 /* SearchCoordinator.swift */,
|
||||||
|
@ -1615,12 +1623,12 @@
|
||||||
E193D54E271942C000900D82 /* ItemView */,
|
E193D54E271942C000900D82 /* ItemView */,
|
||||||
E1C925F828875647002A7A66 /* LatestInLibraryView.swift */,
|
E1C925F828875647002A7A66 /* LatestInLibraryView.swift */,
|
||||||
E193D54C2719426600900D82 /* LibraryFilterView.swift */,
|
E193D54C2719426600900D82 /* LibraryFilterView.swift */,
|
||||||
C4E508172703E8190045C9AB /* LibraryListView.swift */,
|
|
||||||
53A83C32268A309300DF3D92 /* LibraryView.swift */,
|
53A83C32268A309300DF3D92 /* LibraryView.swift */,
|
||||||
C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */,
|
C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */,
|
||||||
C4BE078A272844AF003F4AD1 /* LiveTVChannelsView.swift */,
|
C4BE078A272844AF003F4AD1 /* LiveTVChannelsView.swift */,
|
||||||
C4BE078D27298817003F4AD1 /* LiveTVHomeView.swift */,
|
C4BE078D27298817003F4AD1 /* LiveTVHomeView.swift */,
|
||||||
C4BE07732725EB66003F4AD1 /* LiveTVProgramsView.swift */,
|
C4BE07732725EB66003F4AD1 /* LiveTVProgramsView.swift */,
|
||||||
|
C4E508172703E8190045C9AB /* MediaView.swift */,
|
||||||
C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */,
|
C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */,
|
||||||
E1E1643928BAC2EF00323B0A /* SearchView.swift */,
|
E1E1643928BAC2EF00323B0A /* SearchView.swift */,
|
||||||
E193D54F2719430400900D82 /* ServerDetailView.swift */,
|
E193D54F2719430400900D82 /* ServerDetailView.swift */,
|
||||||
|
@ -1673,13 +1681,13 @@
|
||||||
E1EBCB45278BD595009FE6E9 /* ItemOverviewView.swift */,
|
E1EBCB45278BD595009FE6E9 /* ItemOverviewView.swift */,
|
||||||
E14F7D0A26DB3714007C3AE6 /* ItemView */,
|
E14F7D0A26DB3714007C3AE6 /* ItemView */,
|
||||||
53E4E646263F6CF100F67C6B /* LibraryFilterView.swift */,
|
53E4E646263F6CF100F67C6B /* LibraryFilterView.swift */,
|
||||||
6213388F265F83A900A81A2A /* LibraryListView.swift */,
|
|
||||||
53DF641D263D9C0600A7CD1A /* LibraryView.swift */,
|
53DF641D263D9C0600A7CD1A /* LibraryView.swift */,
|
||||||
C4E5598828124C10003DECA5 /* LiveTVChannelItemElement.swift */,
|
C4E5598828124C10003DECA5 /* LiveTVChannelItemElement.swift */,
|
||||||
C400DB6C27FE8E65007B65FE /* LiveTVChannelItemWideElement.swift */,
|
C400DB6C27FE8E65007B65FE /* LiveTVChannelItemWideElement.swift */,
|
||||||
C400DB6927FE894F007B65FE /* LiveTVChannelsView.swift */,
|
C400DB6927FE894F007B65FE /* LiveTVChannelsView.swift */,
|
||||||
C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */,
|
C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */,
|
||||||
C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */,
|
C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */,
|
||||||
|
6213388F265F83A900A81A2A /* MediaView.swift */,
|
||||||
E1171A1828A2212600FA1AF5 /* QuickConnectView.swift */,
|
E1171A1828A2212600FA1AF5 /* QuickConnectView.swift */,
|
||||||
53EE24E5265060780068F029 /* SearchView.swift */,
|
53EE24E5265060780068F029 /* SearchView.swift */,
|
||||||
E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */,
|
E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */,
|
||||||
|
@ -2433,7 +2441,7 @@
|
||||||
62E632E7267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */,
|
62E632E7267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */,
|
||||||
E1C926122887565C002A7A66 /* SeriesItemContentView.swift in Sources */,
|
E1C926122887565C002A7A66 /* SeriesItemContentView.swift in Sources */,
|
||||||
C4BE0767271FC109003F4AD1 /* TVLibrariesViewModel.swift in Sources */,
|
C4BE0767271FC109003F4AD1 /* TVLibrariesViewModel.swift in Sources */,
|
||||||
E193D53727193F8700900D82 /* LibraryListCoordinator.swift in Sources */,
|
E193D53727193F8700900D82 /* MediaCoordinator.swift in Sources */,
|
||||||
E18E023C288749540022598C /* UIScrollViewExtensions.swift in Sources */,
|
E18E023C288749540022598C /* UIScrollViewExtensions.swift in Sources */,
|
||||||
C4534983279A40990045F1E2 /* tvOSLiveTVVideoPlayerCoordinator.swift in Sources */,
|
C4534983279A40990045F1E2 /* tvOSLiveTVVideoPlayerCoordinator.swift in Sources */,
|
||||||
E1C9260F2887565C002A7A66 /* AttributeHStack.swift in Sources */,
|
E1C9260F2887565C002A7A66 /* AttributeHStack.swift in Sources */,
|
||||||
|
@ -2483,6 +2491,7 @@
|
||||||
53ABFDE5267974EF00886593 /* ViewModel.swift in Sources */,
|
53ABFDE5267974EF00886593 /* ViewModel.swift in Sources */,
|
||||||
E184C161288C5C08000B25BA /* RequestBuilderExtensions.swift in Sources */,
|
E184C161288C5C08000B25BA /* RequestBuilderExtensions.swift in Sources */,
|
||||||
E19169CF272514760085832A /* HTTPScheme.swift in Sources */,
|
E19169CF272514760085832A /* HTTPScheme.swift in Sources */,
|
||||||
|
E1E1644528BC60C600323B0A /* LibraryItem.swift in Sources */,
|
||||||
E13849452780370B0024FB48 /* PlaybackSpeed.swift in Sources */,
|
E13849452780370B0024FB48 /* PlaybackSpeed.swift in Sources */,
|
||||||
E1C812CD277AE40A00918266 /* VideoPlayerViewModel.swift in Sources */,
|
E1C812CD277AE40A00918266 /* VideoPlayerViewModel.swift in Sources */,
|
||||||
C45B29BB26FAC5B600CEF5E0 /* ColorExtension.swift in Sources */,
|
C45B29BB26FAC5B600CEF5E0 /* ColorExtension.swift in Sources */,
|
||||||
|
@ -2498,6 +2507,7 @@
|
||||||
E1E00A36278628A40022235B /* DoubleExtensions.swift in Sources */,
|
E1E00A36278628A40022235B /* DoubleExtensions.swift in Sources */,
|
||||||
E1E1643A28BAC2EF00323B0A /* SearchView.swift in Sources */,
|
E1E1643A28BAC2EF00323B0A /* SearchView.swift in Sources */,
|
||||||
E1FA2F7427818A8800B4C270 /* SmallMenuOverlay.swift in Sources */,
|
E1FA2F7427818A8800B4C270 /* SmallMenuOverlay.swift in Sources */,
|
||||||
|
E1E1644228BB301900323B0A /* ArrayExtensions.swift in Sources */,
|
||||||
E193D53C27193F9500900D82 /* UserListCoordinator.swift in Sources */,
|
E193D53C27193F9500900D82 /* UserListCoordinator.swift in Sources */,
|
||||||
E1CEFBF727914E6400F60429 /* CustomizeViewsSettings.swift in Sources */,
|
E1CEFBF727914E6400F60429 /* CustomizeViewsSettings.swift in Sources */,
|
||||||
E18CE0B528A22EDD0092E7F1 /* RepeatingTimer.swift in Sources */,
|
E18CE0B528A22EDD0092E7F1 /* RepeatingTimer.swift in Sources */,
|
||||||
|
@ -2515,7 +2525,7 @@
|
||||||
6264E88D273850380081A12A /* Strings.swift in Sources */,
|
6264E88D273850380081A12A /* Strings.swift in Sources */,
|
||||||
E1C926102887565C002A7A66 /* PlayButton.swift in Sources */,
|
E1C926102887565C002A7A66 /* PlayButton.swift in Sources */,
|
||||||
E193D5512719432400900D82 /* ServerDetailViewModel.swift in Sources */,
|
E193D5512719432400900D82 /* ServerDetailViewModel.swift in Sources */,
|
||||||
C4E5081B2703F82A0045C9AB /* LibraryListView.swift in Sources */,
|
C4E5081B2703F82A0045C9AB /* MediaView.swift in Sources */,
|
||||||
E193D53B27193F9200900D82 /* SettingsCoordinator.swift in Sources */,
|
E193D53B27193F9200900D82 /* SettingsCoordinator.swift in Sources */,
|
||||||
E18E021C2887492B0022598C /* BlurView.swift in Sources */,
|
E18E021C2887492B0022598C /* BlurView.swift in Sources */,
|
||||||
E1E5D5442783BB5100692DFE /* ItemDetailsView.swift in Sources */,
|
E1E5D5442783BB5100692DFE /* ItemDetailsView.swift in Sources */,
|
||||||
|
@ -2527,7 +2537,7 @@
|
||||||
E1D4BF7F2719D1DD00A11E64 /* BasicAppSettingsViewModel.swift in Sources */,
|
E1D4BF7F2719D1DD00A11E64 /* BasicAppSettingsViewModel.swift in Sources */,
|
||||||
E18E021D2887492B0022598C /* AttributeOutlineView.swift in Sources */,
|
E18E021D2887492B0022598C /* AttributeOutlineView.swift in Sources */,
|
||||||
E193D53227193F7B00900D82 /* ConnectToServerCoodinator.swift in Sources */,
|
E193D53227193F7B00900D82 /* ConnectToServerCoodinator.swift in Sources */,
|
||||||
53ABFDE4267974EF00886593 /* LibraryListViewModel.swift in Sources */,
|
53ABFDE4267974EF00886593 /* MediaViewModel.swift in Sources */,
|
||||||
5364F456266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */,
|
5364F456266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */,
|
||||||
E1937A62288F32DB00CB80AA /* Poster.swift in Sources */,
|
E1937A62288F32DB00CB80AA /* Poster.swift in Sources */,
|
||||||
C4BE0764271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift in Sources */,
|
C4BE0764271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift in Sources */,
|
||||||
|
@ -2563,7 +2573,7 @@
|
||||||
E1C925F428875037002A7A66 /* ItemViewType.swift in Sources */,
|
E1C925F428875037002A7A66 /* ItemViewType.swift in Sources */,
|
||||||
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
|
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
|
||||||
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */,
|
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */,
|
||||||
62C29EA826D103D500C1D2E7 /* LibraryListCoordinator.swift in Sources */,
|
62C29EA826D103D500C1D2E7 /* MediaCoordinator.swift in Sources */,
|
||||||
62E632DC267D2E130063E547 /* SearchViewModel.swift in Sources */,
|
62E632DC267D2E130063E547 /* SearchViewModel.swift in Sources */,
|
||||||
C400DB6D27FE8E65007B65FE /* LiveTVChannelItemWideElement.swift in Sources */,
|
C400DB6D27FE8E65007B65FE /* LiveTVChannelItemWideElement.swift in Sources */,
|
||||||
62C29E9F26D1016600C1D2E7 /* iOSMainCoordinator.swift in Sources */,
|
62C29E9F26D1016600C1D2E7 /* iOSMainCoordinator.swift in Sources */,
|
||||||
|
@ -2579,6 +2589,7 @@
|
||||||
62C29EA126D102A500C1D2E7 /* iOSMainTabCoordinator.swift in Sources */,
|
62C29EA126D102A500C1D2E7 /* iOSMainTabCoordinator.swift in Sources */,
|
||||||
E18E01E8288747230022598C /* SeriesItemContentView.swift in Sources */,
|
E18E01E8288747230022598C /* SeriesItemContentView.swift in Sources */,
|
||||||
E16AA60828A364A6009A983C /* PosterButton.swift in Sources */,
|
E16AA60828A364A6009A983C /* PosterButton.swift in Sources */,
|
||||||
|
E1E1644128BB301900323B0A /* ArrayExtensions.swift in Sources */,
|
||||||
E18CE0AF28A222240092E7F1 /* PublicUserSignInView.swift in Sources */,
|
E18CE0AF28A222240092E7F1 /* PublicUserSignInView.swift in Sources */,
|
||||||
E18E01E5288747230022598C /* CinematicScrollView.swift in Sources */,
|
E18E01E5288747230022598C /* CinematicScrollView.swift in Sources */,
|
||||||
E1C812C0277A8E5D00918266 /* VLCPlayerView.swift in Sources */,
|
E1C812C0277A8E5D00918266 /* VLCPlayerView.swift in Sources */,
|
||||||
|
@ -2608,7 +2619,7 @@
|
||||||
53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */,
|
53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */,
|
||||||
C4AE2C3027498D2300AE13CF /* LiveTVHomeView.swift in Sources */,
|
C4AE2C3027498D2300AE13CF /* LiveTVHomeView.swift in Sources */,
|
||||||
E1EBCB42278BD174009FE6E9 /* TruncatedTextView.swift in Sources */,
|
E1EBCB42278BD174009FE6E9 /* TruncatedTextView.swift in Sources */,
|
||||||
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */,
|
62133890265F83A900A81A2A /* MediaView.swift in Sources */,
|
||||||
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */,
|
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */,
|
||||||
E18E01E1288747230022598C /* EpisodeItemContentView.swift in Sources */,
|
E18E01E1288747230022598C /* EpisodeItemContentView.swift in Sources */,
|
||||||
62E632DA267D2BC40063E547 /* LatestMediaViewModel.swift in Sources */,
|
62E632DA267D2BC40063E547 /* LatestMediaViewModel.swift in Sources */,
|
||||||
|
@ -2694,6 +2705,7 @@
|
||||||
62E632E0267D30CA0063E547 /* LibraryViewModel.swift in Sources */,
|
62E632E0267D30CA0063E547 /* LibraryViewModel.swift in Sources */,
|
||||||
E11CEB8B28998552003E74C7 /* iOSViewExtensions.swift in Sources */,
|
E11CEB8B28998552003E74C7 /* iOSViewExtensions.swift in Sources */,
|
||||||
E193D4DB27193CCA00900D82 /* PillStackable.swift in Sources */,
|
E193D4DB27193CCA00900D82 /* PillStackable.swift in Sources */,
|
||||||
|
E1E1644428BC60C600323B0A /* LibraryItem.swift in Sources */,
|
||||||
E18E0206288749200022598C /* AttributeFillView.swift in Sources */,
|
E18E0206288749200022598C /* AttributeFillView.swift in Sources */,
|
||||||
E1AA331F2782639D00F6439C /* OverlayType.swift in Sources */,
|
E1AA331F2782639D00F6439C /* OverlayType.swift in Sources */,
|
||||||
E1A2C154279A7D5A005EC829 /* UIApplicationExtensions.swift in Sources */,
|
E1A2C154279A7D5A005EC829 /* UIApplicationExtensions.swift in Sources */,
|
||||||
|
@ -2746,7 +2758,7 @@
|
||||||
E13DD4022717EE79009D4DAF /* UserListCoordinator.swift in Sources */,
|
E13DD4022717EE79009D4DAF /* UserListCoordinator.swift in Sources */,
|
||||||
E1FCD09626C47118007C8DCF /* ErrorMessage.swift in Sources */,
|
E1FCD09626C47118007C8DCF /* ErrorMessage.swift in Sources */,
|
||||||
53EE24E6265060780068F029 /* SearchView.swift in Sources */,
|
53EE24E6265060780068F029 /* SearchView.swift in Sources */,
|
||||||
625CB5752678C33500530A6E /* LibraryListViewModel.swift in Sources */,
|
625CB5752678C33500530A6E /* MediaViewModel.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,21 +51,23 @@ struct PosterButton<Item: Poster, Content: View, ImageOverlay: View, ContextMenu
|
||||||
Button {
|
Button {
|
||||||
onSelect(item)
|
onSelect(item)
|
||||||
} label: {
|
} label: {
|
||||||
switch type {
|
Group {
|
||||||
case .portrait:
|
switch type {
|
||||||
ImageView(item.portraitPosterImageSource(maxWidth: itemWidth))
|
case .portrait:
|
||||||
case .landscape:
|
ImageView(item.portraitPosterImageSource(maxWidth: itemWidth))
|
||||||
ImageView(item.landscapePosterImageSources(maxWidth: itemWidth, single: singleImage))
|
case .landscape:
|
||||||
|
ImageView(item.landscapePosterImageSources(maxWidth: itemWidth, single: singleImage))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.overlay {
|
||||||
|
imageOverlay(item)
|
||||||
|
.posterStyle(type: type, width: itemWidth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.contextMenu(menuItems: {
|
.contextMenu(menuItems: {
|
||||||
contextMenu(item)
|
contextMenu(item)
|
||||||
})
|
})
|
||||||
.posterStyle(type: type, width: itemWidth)
|
.posterStyle(type: type, width: itemWidth)
|
||||||
.overlay {
|
|
||||||
imageOverlay(item)
|
|
||||||
.posterStyle(type: type, width: itemWidth)
|
|
||||||
}
|
|
||||||
.posterShadow()
|
.posterShadow()
|
||||||
|
|
||||||
content(item)
|
content(item)
|
||||||
|
|
|
@ -1,93 +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) 2022 Jellyfin & Jellyfin Contributors
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import JellyfinAPI
|
|
||||||
import Stinsen
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct LibraryListView: View {
|
|
||||||
@EnvironmentObject
|
|
||||||
private var libraryListRouter: LibraryListCoordinator.Router
|
|
||||||
@StateObject
|
|
||||||
var viewModel = LibraryListViewModel()
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ScrollView {
|
|
||||||
LazyVStack {
|
|
||||||
Button {
|
|
||||||
libraryListRouter.route(
|
|
||||||
to: \.library,
|
|
||||||
(viewModel: LibraryViewModel(filters: viewModel.withFavorites), title: L10n.favorites)
|
|
||||||
)
|
|
||||||
} label: {
|
|
||||||
ZStack {
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
L10n.yourFavorites.text
|
|
||||||
.foregroundColor(.black)
|
|
||||||
.font(.subheadline)
|
|
||||||
.fontWeight(.semibold)
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(16)
|
|
||||||
.background(Color.white)
|
|
||||||
.frame(minWidth: 100, maxWidth: .infinity)
|
|
||||||
}
|
|
||||||
.cornerRadius(10)
|
|
||||||
.shadow(radius: 5)
|
|
||||||
.padding(.bottom, 5)
|
|
||||||
|
|
||||||
if !viewModel.isLoading {
|
|
||||||
ForEach(viewModel.filteredLibraries, id: \.id) { library in
|
|
||||||
Button {
|
|
||||||
if library.collectionType == "livetv" {
|
|
||||||
libraryListRouter.route(to: \.liveTV)
|
|
||||||
} else {
|
|
||||||
libraryListRouter.route(
|
|
||||||
to: \.library,
|
|
||||||
(
|
|
||||||
viewModel: LibraryViewModel(parentID: library.id),
|
|
||||||
title: library.name ?? ""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
ZStack {
|
|
||||||
ImageView(library.imageSource(.primary, maxWidth: 500))
|
|
||||||
.opacity(0.4)
|
|
||||||
.accessibilityIgnoresInvertColors()
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
VStack {
|
|
||||||
Text(library.name ?? "")
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.font(.title2)
|
|
||||||
.fontWeight(.semibold)
|
|
||||||
}
|
|
||||||
Spacer()
|
|
||||||
}.padding(32)
|
|
||||||
}.background(Color.black)
|
|
||||||
.frame(minWidth: 100, maxWidth: .infinity)
|
|
||||||
.frame(height: 100)
|
|
||||||
}
|
|
||||||
.cornerRadius(10)
|
|
||||||
.shadow(radius: 5)
|
|
||||||
.padding(.bottom, 5)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ProgressView()
|
|
||||||
}
|
|
||||||
}.padding(.leading, 16)
|
|
||||||
.padding(.trailing, 16)
|
|
||||||
.padding(.top, 8)
|
|
||||||
}
|
|
||||||
.navigationTitle(L10n.allMedia)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
//
|
||||||
|
// 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) 2022 Jellyfin & Jellyfin Contributors
|
||||||
|
//
|
||||||
|
|
||||||
|
import CollectionView
|
||||||
|
import Defaults
|
||||||
|
import JellyfinAPI
|
||||||
|
import Stinsen
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct MediaView: View {
|
||||||
|
|
||||||
|
@EnvironmentObject
|
||||||
|
private var router: MediaCoordinator.Router
|
||||||
|
@ObservedObject
|
||||||
|
var viewModel: MediaViewModel
|
||||||
|
@Default(.Experimental.liveTVAlphaEnabled)
|
||||||
|
var liveTVEnabled
|
||||||
|
|
||||||
|
private var libraryItems: [LibraryItem] {
|
||||||
|
[LibraryItem(library: .init(name: L10n.favorites, id: "favorites"), viewModel: viewModel)]
|
||||||
|
.appending(.init(library: .init(name: "LiveTV", id: "liveTV"), viewModel: viewModel), if: liveTVEnabled)
|
||||||
|
.appending(viewModel.libraries.map { LibraryItem(library: $0, viewModel: viewModel) })
|
||||||
|
}
|
||||||
|
|
||||||
|
private var gridLayout: NSCollectionLayoutSection.GridLayoutMode {
|
||||||
|
if UIDevice.isPhone {
|
||||||
|
return .fixedNumberOfColumns(2)
|
||||||
|
} else {
|
||||||
|
return .adaptive(withMinItemSize: PosterType.landscape.width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
CollectionView(items: libraryItems) { _, item, _ in
|
||||||
|
PosterButton(item: item, type: .landscape)
|
||||||
|
.scaleItem(UIDevice.isPhone ? 0.9 : 1)
|
||||||
|
.onSelect { _ in
|
||||||
|
if item.library.id == "favorites" {
|
||||||
|
router.route(to: \.library, (viewModel: .init(filters: .favorites), title: ""))
|
||||||
|
} else if item.library.id == "liveTV" {
|
||||||
|
router.route(to: \.liveTV)
|
||||||
|
} else {
|
||||||
|
router.route(to: \.library, (viewModel: .init(parentID: item.library.id), title: ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.imageOverlay { _ in
|
||||||
|
ZStack {
|
||||||
|
Color.black
|
||||||
|
.opacity(0.5)
|
||||||
|
|
||||||
|
Text(item.library.displayName)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.font(.title2)
|
||||||
|
.fontWeight(.semibold)
|
||||||
|
.lineLimit(2)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.frame(alignment: .center)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.layout { _, layoutEnvironment in
|
||||||
|
.grid(
|
||||||
|
layoutEnvironment: layoutEnvironment,
|
||||||
|
layoutMode: gridLayout,
|
||||||
|
sectionInsets: .init(top: 0, leading: 10, bottom: 0, trailing: 10)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.configure { configuration in
|
||||||
|
configuration.showsVerticalScrollIndicator = false
|
||||||
|
}
|
||||||
|
.ignoresSafeArea()
|
||||||
|
.navigationTitle(L10n.allMedia)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue