Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Shared/Coordinators/DownloadListCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
//

#if os(iOS)
import Factory
import Foundation
import Stinsen
import SwiftUI

final class DownloadListCoordinator: NavigationCoordinatable {
@Injected(Container.downloadManager)
private var downloadManager

let stack = NavigationStack(initial: \DownloadListCoordinator.start)

Expand All @@ -20,13 +23,13 @@ final class DownloadListCoordinator: NavigationCoordinatable {
@Route(.modal)
var downloadTask = makeDownloadTask

func makeDownloadTask(downloadTask: DownloadTask) -> NavigationViewCoordinator<DownloadTaskCoordinator> {
func makeDownloadTask(downloadTask: DownloadEntity) -> NavigationViewCoordinator<DownloadTaskCoordinator> {
NavigationViewCoordinator(DownloadTaskCoordinator(downloadTask: downloadTask))
}

@ViewBuilder
private func makeStart() -> DownloadListView {
DownloadListView(viewModel: .init())
DownloadListView(viewModel: .init(), downloadManager: downloadManager)
}
}
#endif
4 changes: 2 additions & 2 deletions Shared/Coordinators/DownloadTaskCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ final class DownloadTaskCoordinator: NavigationCoordinatable {
@Root
var start = makeStart

let downloadTask: DownloadTask
let downloadTask: DownloadEntity

init(downloadTask: DownloadTask) {
init(downloadTask: DownloadEntity) {
self.downloadTask = downloadTask
}

Expand Down
9 changes: 9 additions & 0 deletions Shared/Coordinators/File.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//
// 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) 2024 Jellyfin & Jellyfin Contributors
//

import Foundation
2 changes: 1 addition & 1 deletion Shared/Coordinators/ItemCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ final class ItemCoordinator: NavigationCoordinatable {
}

#if os(iOS)
func makeDownloadTask(downloadTask: DownloadTask) -> NavigationViewCoordinator<DownloadTaskCoordinator> {
func makeDownloadTask(downloadTask: DownloadEntity) -> NavigationViewCoordinator<DownloadTaskCoordinator> {
NavigationViewCoordinator(DownloadTaskCoordinator(downloadTask: downloadTask))
}
#endif
Expand Down
17 changes: 17 additions & 0 deletions Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import SwiftUI

final class MainCoordinator: NavigationCoordinatable {

@Default(.Experimental.offlineMode)
private var offlineMode

@Injected(LogManager.service)
private var logger

Expand All @@ -31,6 +34,8 @@ final class MainCoordinator: NavigationCoordinatable {
@Root
var mainTab = makeMainTab
@Root
var offlineView = makeOffline
@Root
var selectUser = makeSelectUser
@Root
var serverCheck = makeServerCheck
Expand All @@ -50,6 +55,14 @@ final class MainCoordinator: NavigationCoordinatable {
do {
try await SwiftfinStore.setupDataStack()

if offlineMode {
await MainActor.run {
withAnimation(.linear(duration: 0.1)) {
let _ = root(\.offlineView)
}
}
return
}
if UserSession.current() != nil, !Defaults[.signOutOnClose] {
await MainActor.run {
withAnimation(.linear(duration: 0.1)) {
Expand Down Expand Up @@ -138,6 +151,10 @@ final class MainCoordinator: NavigationCoordinatable {
MainTabCoordinator()
}

func makeOffline() -> NavigationViewCoordinator<OfflineCoordinator> {
NavigationViewCoordinator(OfflineCoordinator())
}

func makeSelectUser() -> NavigationViewCoordinator<SelectUserCoordinator> {
NavigationViewCoordinator(SelectUserCoordinator())
}
Expand Down
41 changes: 36 additions & 5 deletions Shared/Coordinators/MainCoordinator/iOSMainTabCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,35 @@
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//

import Defaults
import Foundation
import Stinsen
import SwiftUI

final class MainTabCoordinator: TabCoordinatable {

var child = TabChild(startingItems: [
\MainTabCoordinator.home,
\MainTabCoordinator.search,
\MainTabCoordinator.media,
])
var child: TabChild

init() {
self.child = TabChild(startingItems: [
\MainTabCoordinator.home,
\MainTabCoordinator.search,
\MainTabCoordinator.media,
])
if Defaults[.Experimental.downloads] {
self.child = TabChild(startingItems: [
\MainTabCoordinator.home,
\MainTabCoordinator.search,
\MainTabCoordinator.media,
\MainTabCoordinator.downloads,
])
}
}

@Route(tabItem: makeHomeTab, onTapped: onHomeTapped)
var home = makeHome
@Route(tabItem: makeDownloadsTab, onTapped: onDownloadsTapped)
var downloads = makeDownloads
@Route(tabItem: makeSearchTab, onTapped: onSearchTapped)
var search = makeSearch
@Route(tabItem: makeMediaTab, onTapped: onMediaTapped)
Expand All @@ -41,6 +56,22 @@ final class MainTabCoordinator: TabCoordinatable {
L10n.home.text
}

@ViewBuilder
func makeDownloadsTab(isActive: Bool) -> some View {
Image(systemName: "square.and.arrow.down.fill")
L10n.downloads.text
}

func makeDownloads() -> NavigationViewCoordinator<OfflineCoordinator> {
NavigationViewCoordinator(OfflineCoordinator())
}

func onDownloadsTapped(isRepeat: Bool, coordinator: NavigationViewCoordinator<OfflineCoordinator>) {
if isRepeat {
coordinator.child.popToRoot()
}
}

func makeSearch() -> NavigationViewCoordinator<SearchCoordinator> {
NavigationViewCoordinator(SearchCoordinator())
}
Expand Down
40 changes: 40 additions & 0 deletions Shared/Coordinators/OfflineCoordinator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// 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) 2024 Jellyfin & Jellyfin Contributors
//

import Foundation
import JellyfinAPI
import Stinsen
import SwiftUI

final class OfflineCoordinator: NavigationCoordinatable {

let stack = NavigationStack(initial: \OfflineCoordinator.start)

@Root
var start = makeStart

@Route(.push)
var item = makeItem
@Route(.push)
var library = makeLibrary

var viewModel = OfflineViewModel()

func makeItem(item: BaseItemDto) -> OfflineItemCoordinator {
OfflineItemCoordinator(item: item, viewModel: viewModel)
}

func makeLibrary(viewModel: PagingLibraryViewModel<BaseItemDto>) -> LibraryCoordinator<BaseItemDto> {
LibraryCoordinator(viewModel: viewModel)
}

@ViewBuilder
func makeStart() -> some View {
OfflineView(viewModel: viewModel)
}
}
66 changes: 66 additions & 0 deletions Shared/Coordinators/OfflineItemCoordinator.swift
Original file line number Diff line number Diff line change
@@ -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) 2024 Jellyfin & Jellyfin Contributors
//

import Foundation
import JellyfinAPI
import Stinsen
import SwiftUI

final class OfflineItemCoordinator: NavigationCoordinatable {

let stack = NavigationStack(initial: \OfflineItemCoordinator.start)

@Root
var start = makeStart
@Route(.push)
var item = makeItem
@Route(.push)
var library = makeLibrary

@Route(.modal)
var itemOverview = makeItemOverview
@Route(.modal)
var mediaSourceInfo = makeMediaSourceInfo
@Route(.modal)
var downloadTask = makeDownloadTask

private let itemDto: BaseItemDto
private let viewModel: OfflineViewModel

init(item: BaseItemDto, viewModel: OfflineViewModel) {
self.itemDto = item
self.viewModel = viewModel
}

func makeItem(item: BaseItemDto) -> OfflineItemCoordinator {
OfflineItemCoordinator(item: item, viewModel: viewModel)
}

func makeLibrary(viewModel: PagingLibraryViewModel<BaseItemDto>) -> OfflineLibraryCoordinator<BaseItemDto> {
OfflineLibraryCoordinator(viewModel: viewModel, offlineViewModel: self.viewModel)
}

func makeItemOverview(item: BaseItemDto) -> NavigationViewCoordinator<BasicNavigationViewCoordinator> {
NavigationViewCoordinator {
ItemOverviewView(item: item)
}
}

func makeMediaSourceInfo(source: MediaSourceInfo) -> NavigationViewCoordinator<MediaSourceInfoCoordinator> {
NavigationViewCoordinator(MediaSourceInfoCoordinator(mediaSourceInfo: source))
}

func makeDownloadTask(downloadTask: DownloadEntity) -> NavigationViewCoordinator<DownloadTaskCoordinator> {
NavigationViewCoordinator(DownloadTaskCoordinator(downloadTask: downloadTask))
}

@ViewBuilder
func makeStart() -> some View {
OfflineItemView(item: itemDto, offlineModel: viewModel)
}
}
70 changes: 70 additions & 0 deletions Shared/Coordinators/OfflineLibraryCoordinator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//
// 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) 2024 Jellyfin & Jellyfin Contributors
//

import Defaults
import Foundation
import JellyfinAPI
import Stinsen
import SwiftUI

final class OfflineLibraryCoordinator<Element: Poster>: NavigationCoordinatable {

let stack = NavigationStack(initial: \OfflineLibraryCoordinator.start)

@Root
var start = makeStart

#if os(tvOS)
@Route(.modal)
var item = makeItem
@Route(.push)
var library = makeLibrary
#else
@Route(.push)
var item = makeItem
@Route(.push)
var library = makeLibrary
@Route(.modal)
var filter = makeFilter
#endif

private let viewModel: PagingLibraryViewModel<Element>
private let offlineViewModel: OfflineViewModel

init(viewModel: PagingLibraryViewModel<Element>, offlineViewModel: OfflineViewModel) {
self.viewModel = viewModel
self.offlineViewModel = offlineViewModel
}

@ViewBuilder
func makeStart() -> some View {
PagingLibraryView(viewModel: viewModel)
}

#if os(tvOS)
func makeItem(item: BaseItemDto) -> NavigationViewCoordinator<ItemCoordinator> {
NavigationViewCoordinator(ItemCoordinator(item: item))
}

func makeLibrary(viewModel: PagingLibraryViewModel<BaseItemDto>) -> NavigationViewCoordinator<LibraryCoordinator<BaseItemDto>> {
NavigationViewCoordinator(LibraryCoordinator<BaseItemDto>(viewModel: viewModel))
}
#else
func makeItem(item: BaseItemDto) -> OfflineItemCoordinator {
OfflineItemCoordinator(item: item, viewModel: offlineViewModel)
}

func makeLibrary(viewModel: PagingLibraryViewModel<BaseItemDto>) -> LibraryCoordinator<BaseItemDto> {
LibraryCoordinator<BaseItemDto>(viewModel: viewModel)
}

func makeFilter(parameters: FilterCoordinator.Parameters) -> NavigationViewCoordinator<FilterCoordinator> {
NavigationViewCoordinator(FilterCoordinator(parameters: parameters))
}
#endif
}
7 changes: 7 additions & 0 deletions Shared/Extensions/Int.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ extension FixedWidthInteger {
.appending(minutesText)
.appending(secondsText)
}

var sizeLable: String {
let bcf = ByteCountFormatter()
bcf.allowedUnits = [.useMB, .useGB]
bcf.countStyle = .file
return bcf.string(fromByteCount: Int64(self))
}
}

extension Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ extension BaseItemDto: Poster {
case .episode:
if Defaults[.Customization.Episodes.useSeriesLandscapeBackdrop] {
[
imageSource(.primary, maxWidth: maxWidth),
seriesImageSource(.thumb, maxWidth: maxWidth),
seriesImageSource(.backdrop, maxWidth: maxWidth),
imageSource(.primary, maxWidth: maxWidth),
]
} else {
[imageSource(.primary, maxWidth: maxWidth)]
Expand Down
Loading