Merge branch 'some-ui-polish' into tvos-home-screen-big-view
This commit is contained in:
commit
63fe0a1eab
|
@ -19,6 +19,7 @@ final class ItemCoordinator: NavigationCoordinatable {
|
|||
@Root var start = makeStart
|
||||
@Route(.push) var item = makeItem
|
||||
@Route(.push) var library = makeLibrary
|
||||
@Route(.modal) var itemOverview = makeItemOverview
|
||||
@Route(.fullScreen) var videoPlayer = makeVideoPlayer
|
||||
|
||||
let itemDto: BaseItemDto
|
||||
|
@ -34,6 +35,10 @@ final class ItemCoordinator: NavigationCoordinatable {
|
|||
func makeItem(item: BaseItemDto) -> ItemCoordinator {
|
||||
ItemCoordinator(item: item)
|
||||
}
|
||||
|
||||
func makeItemOverview(item: BaseItemDto) -> NavigationViewCoordinator<ItemOverviewCoordinator> {
|
||||
NavigationViewCoordinator(ItemOverviewCoordinator(item: itemDto))
|
||||
}
|
||||
|
||||
func makeVideoPlayer(viewModel: VideoPlayerViewModel) -> NavigationViewCoordinator<VideoPlayerCoordinator> {
|
||||
NavigationViewCoordinator(VideoPlayerCoordinator(viewModel: viewModel))
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import Stinsen
|
||||
import SwiftUI
|
||||
import JellyfinAPI
|
||||
|
||||
final class ItemOverviewCoordinator: NavigationCoordinatable {
|
||||
|
||||
let stack = NavigationStack(initial: \ItemOverviewCoordinator.start)
|
||||
|
||||
@Root var start = makeStart
|
||||
|
||||
let item: BaseItemDto
|
||||
|
||||
init(item: BaseItemDto) {
|
||||
self.item = item
|
||||
}
|
||||
|
||||
@ViewBuilder func makeStart() -> some View {
|
||||
#if os(tvOS)
|
||||
EmptyView()
|
||||
#else
|
||||
ItemOverviewView(item: item)
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ extension Color {
|
|||
public static let lightGray = Color(UIColor.lightGray)
|
||||
#else
|
||||
public static let systemFill = Color(UIColor.systemFill)
|
||||
public static let systemBackground = Color(UIColor.systemBackground)
|
||||
public static let secondarySystemFill = Color(UIColor.secondarySystemBackground)
|
||||
public static let tertiarySystemFill = Color(UIColor.tertiarySystemBackground)
|
||||
#endif
|
||||
|
|
|
@ -17,14 +17,9 @@ class ItemViewModel: ViewModel {
|
|||
@Published var item: BaseItemDto
|
||||
@Published var playButtonItem: BaseItemDto? {
|
||||
didSet {
|
||||
playButtonItem?.createVideoPlayerViewModel()
|
||||
.sink { completion in
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
} receiveValue: { videoPlayerViewModel in
|
||||
self.itemVideoPlayerViewModel = videoPlayerViewModel
|
||||
self.mediaItems = videoPlayerViewModel.item.createMediaItems()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
if let playButtonItem = playButtonItem {
|
||||
refreshItemVideoPlayerViewModel(for: playButtonItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
@Published var similarItems: [BaseItemDto] = []
|
||||
|
@ -52,6 +47,10 @@ class ItemViewModel: ViewModel {
|
|||
|
||||
getSimilarItems()
|
||||
|
||||
refreshItemVideoPlayerViewModel(for: item)
|
||||
}
|
||||
|
||||
func refreshItemVideoPlayerViewModel(for item: BaseItemDto) {
|
||||
item.createVideoPlayerViewModel()
|
||||
.sink { completion in
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
extension View {
|
||||
|
||||
/// Applies Portrait Poster frame with proper corner radius ratio against the width
|
||||
func portraitPoster(width: CGFloat) -> some View {
|
||||
self.frame(width: width, height: width * 1.5)
|
||||
.cornerRadius((width * 1.5) / 40)
|
||||
}
|
||||
}
|
|
@ -17,13 +17,12 @@ struct CinematicItemAboutView: View {
|
|||
var body: some View {
|
||||
HStack(alignment: .top, spacing: 10) {
|
||||
ImageView(src: viewModel.item.portraitHeaderViewURL(maxWidth: 257))
|
||||
.frame(width: 257, height: 380)
|
||||
.cornerRadius(10)
|
||||
.portraitPoster(width: 257)
|
||||
|
||||
ZStack(alignment: .topLeading) {
|
||||
Color(UIColor.darkGray).opacity(focused ? 0.2 : 0)
|
||||
.cornerRadius(30)
|
||||
.frame(height: 380)
|
||||
.cornerRadius(9.5)
|
||||
.frame(height: 385.5)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("About")
|
||||
|
|
|
@ -254,6 +254,8 @@
|
|||
E107BB9327880A8F00354E07 /* CollectionItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107BB9227880A8F00354E07 /* CollectionItemViewModel.swift */; };
|
||||
E107BB9427880A8F00354E07 /* CollectionItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107BB9227880A8F00354E07 /* CollectionItemViewModel.swift */; };
|
||||
E107BB972788104100354E07 /* CinematicCollectionItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107BB952788104100354E07 /* CinematicCollectionItemView.swift */; };
|
||||
E10C0941278B8DAB009DBF93 /* PortraitItemSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10C0940278B8DAB009DBF93 /* PortraitItemSize.swift */; };
|
||||
E10C0942278B8DAB009DBF93 /* PortraitItemSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10C0940278B8DAB009DBF93 /* PortraitItemSize.swift */; };
|
||||
E10D87DA2784E4F100BD264C /* ItemViewDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10D87D92784E4F100BD264C /* ItemViewDetailsView.swift */; };
|
||||
E10D87DC2784EC5200BD264C /* EpisodesRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10D87DB2784EC5200BD264C /* EpisodesRowView.swift */; };
|
||||
E10D87DE278510E400BD264C /* PosterSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10D87DD278510E300BD264C /* PosterSize.swift */; };
|
||||
|
@ -428,6 +430,10 @@
|
|||
E1E5D54F2783E67100692DFE /* OverlaySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E5D54E2783E67100692DFE /* OverlaySettingsView.swift */; };
|
||||
E1E5D5512783E67700692DFE /* ExperimentalSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E5D5502783E67700692DFE /* ExperimentalSettingsView.swift */; };
|
||||
E1E5D553278419D900692DFE /* ConfirmCloseOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E5D552278419D900692DFE /* ConfirmCloseOverlay.swift */; };
|
||||
E1EBCB42278BD174009FE6E9 /* TruncatedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB41278BD174009FE6E9 /* TruncatedTextView.swift */; };
|
||||
E1EBCB44278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */; };
|
||||
E1EBCB46278BD595009FE6E9 /* ItemOverviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB45278BD595009FE6E9 /* ItemOverviewView.swift */; };
|
||||
E1EBCB4A278BE443009FE6E9 /* ItemOverviewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */; };
|
||||
E1F0204E26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; };
|
||||
E1F0204F26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; };
|
||||
E1FA2F7427818A8800B4C270 /* SmallMenuOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FA2F7327818A8800B4C270 /* SmallMenuOverlay.swift */; };
|
||||
|
@ -650,6 +656,7 @@
|
|||
E103A6A8278AB6FF00820EC7 /* CinematicNextUpCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicNextUpCardView.swift; sourceTree = "<group>"; };
|
||||
E107BB9227880A8F00354E07 /* CollectionItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemViewModel.swift; sourceTree = "<group>"; };
|
||||
E107BB952788104100354E07 /* CinematicCollectionItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicCollectionItemView.swift; sourceTree = "<group>"; };
|
||||
E10C0940278B8DAB009DBF93 /* PortraitItemSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortraitItemSize.swift; sourceTree = "<group>"; };
|
||||
E10D87D92784E4F100BD264C /* ItemViewDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemViewDetailsView.swift; sourceTree = "<group>"; };
|
||||
E10D87DB2784EC5200BD264C /* EpisodesRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodesRowView.swift; sourceTree = "<group>"; };
|
||||
E10D87DD278510E300BD264C /* PosterSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PosterSize.swift; sourceTree = "<group>"; };
|
||||
|
@ -747,6 +754,9 @@
|
|||
E1E5D54E2783E67100692DFE /* OverlaySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlaySettingsView.swift; sourceTree = "<group>"; };
|
||||
E1E5D5502783E67700692DFE /* ExperimentalSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperimentalSettingsView.swift; sourceTree = "<group>"; };
|
||||
E1E5D552278419D900692DFE /* ConfirmCloseOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmCloseOverlay.swift; sourceTree = "<group>"; };
|
||||
E1EBCB41278BD174009FE6E9 /* TruncatedTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TruncatedTextView.swift; sourceTree = "<group>"; };
|
||||
E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemOverviewCoordinator.swift; sourceTree = "<group>"; };
|
||||
E1EBCB45278BD595009FE6E9 /* ItemOverviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemOverviewView.swift; sourceTree = "<group>"; };
|
||||
E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerJumpLength.swift; sourceTree = "<group>"; };
|
||||
E1FA2F7327818A8800B4C270 /* SmallMenuOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallMenuOverlay.swift; sourceTree = "<group>"; };
|
||||
E1FCD08726C35A0D007C8DCF /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = "<group>"; };
|
||||
|
@ -1193,11 +1203,13 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
E188460326DEF04800B0C5B7 /* EpisodeCardVStackView.swift */,
|
||||
E10D87DB2784EC5200BD264C /* EpisodesRowView.swift */,
|
||||
E1AD105B26D9ABDD003E4A08 /* PillHStackView.swift */,
|
||||
E1AD105526D981CE003E4A08 /* PortraitHStackView.swift */,
|
||||
C4BE076D2720FEA8003F4AD1 /* PortraitItemElement.swift */,
|
||||
53F866432687A45F00DCD1D7 /* PortraitItemView.swift */,
|
||||
E1AA331C2782541500F6439C /* PrimaryButtonView.swift */,
|
||||
E1EBCB41278BD174009FE6E9 /* TruncatedTextView.swift */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1257,11 +1269,12 @@
|
|||
6220D0B926D6092100B8E046 /* FilterCoordinator.swift */,
|
||||
62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */,
|
||||
6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */,
|
||||
E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */,
|
||||
6220D0B326D5ED8000B8E046 /* LibraryCoordinator.swift */,
|
||||
62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */,
|
||||
C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */,
|
||||
C4BE07702725EB06003F4AD1 /* LiveTVProgramsCoordinator.swift */,
|
||||
C4BE07782726EE82003F4AD1 /* LiveTVTabCoordinator.swift */,
|
||||
C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */,
|
||||
62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */,
|
||||
E193D5412719404B00900D82 /* MainCoordinator */,
|
||||
C40CD921271F8CD8000FB198 /* MoviesLibrariesCoordinator.swift */,
|
||||
6220D0B626D5EE1100B8E046 /* SearchCoordinator.swift */,
|
||||
|
@ -1420,18 +1433,19 @@
|
|||
5338F74D263B61370014BF09 /* ConnectToServerView.swift */,
|
||||
5389276D263C25100035E14B /* ContinueWatchingView.swift */,
|
||||
625CB56E2678C23300530A6E /* HomeView.swift */,
|
||||
E1EBCB45278BD595009FE6E9 /* ItemOverviewView.swift */,
|
||||
E14F7D0A26DB3714007C3AE6 /* ItemView */,
|
||||
53FF7F29263CF3F500585C35 /* LatestMediaView.swift */,
|
||||
C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */,
|
||||
C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */,
|
||||
53E4E646263F6CF100F67C6B /* LibraryFilterView.swift */,
|
||||
6213388F265F83A900A81A2A /* LibraryListView.swift */,
|
||||
53EE24E5265060780068F029 /* LibrarySearchView.swift */,
|
||||
53DF641D263D9C0600A7CD1A /* LibraryView.swift */,
|
||||
C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */,
|
||||
C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */,
|
||||
5389276F263C25230035E14B /* NextUpView.swift */,
|
||||
E1E5D54A2783E26100692DFE /* SettingsView */,
|
||||
E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */,
|
||||
E13DD3E427177D15009D4DAF /* ServerListView.swift */,
|
||||
E1E5D54A2783E26100692DFE /* SettingsView */,
|
||||
E13DD3FB2717EAE8009D4DAF /* UserListView.swift */,
|
||||
E13DD3F4271793BB009D4DAF /* UserSignInView.swift */,
|
||||
E193D5452719418B00900D82 /* VideoPlayer */,
|
||||
|
@ -1453,7 +1467,6 @@
|
|||
E14F7D0A26DB3714007C3AE6 /* ItemView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E10D87DB2784EC5200BD264C /* EpisodesRowView.swift */,
|
||||
535BAE9E2649E569005FA86D /* ItemView.swift */,
|
||||
E18845F726DEA9C900B0C5B7 /* ItemViewBody.swift */,
|
||||
E10D87D92784E4F100BD264C /* ItemViewDetailsView.swift */,
|
||||
|
@ -1550,12 +1563,13 @@
|
|||
E1AD105326D96F5A003E4A08 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */,
|
||||
531690F9267AD6EC005D8AB9 /* PlainNavigationLinkButton.swift */,
|
||||
531AC8BE26750DE20091C7EB /* ImageView.swift */,
|
||||
621338B22660A07800A81A2A /* LazyView.swift */,
|
||||
C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */,
|
||||
53E4E648263F725B00F67C6B /* MultiSelectorView.swift */,
|
||||
6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */,
|
||||
531690F9267AD6EC005D8AB9 /* PlainNavigationLinkButton.swift */,
|
||||
E10C0940278B8DAB009DBF93 /* PortraitItemSize.swift */,
|
||||
624C21742685CF60007F1390 /* SearchablePickerView.swift */,
|
||||
53DE4BD1267098F300739748 /* SearchBarView.swift */,
|
||||
);
|
||||
|
@ -2080,6 +2094,7 @@
|
|||
E1E5D5462783C28100692DFE /* CinematicItemAboutView.swift in Sources */,
|
||||
E1FCD09726C47118007C8DCF /* ErrorMessage.swift in Sources */,
|
||||
E193D53527193F8100900D82 /* ItemCoordinator.swift in Sources */,
|
||||
E1EBCB4A278BE443009FE6E9 /* ItemOverviewCoordinator.swift in Sources */,
|
||||
53116A19268B947A003024C9 /* PlainLinkButton.swift in Sources */,
|
||||
C4BE07772725EBEA003F4AD1 /* LiveTVProgramsViewModel.swift in Sources */,
|
||||
536D3D88267C17350004248C /* PublicUserButton.swift in Sources */,
|
||||
|
@ -2195,6 +2210,7 @@
|
|||
6264E88D273850380081A12A /* Strings.swift in Sources */,
|
||||
536D3D76267BA9BB0004248C /* MainTabViewModel.swift in Sources */,
|
||||
E193D5512719432400900D82 /* ServerDetailViewModel.swift in Sources */,
|
||||
E10C0942278B8DAB009DBF93 /* PortraitItemSize.swift in Sources */,
|
||||
C4E5081B2703F82A0045C9AB /* LibraryListView.swift in Sources */,
|
||||
E193D53B27193F9200900D82 /* SettingsCoordinator.swift in Sources */,
|
||||
E1E5D5392783A56B00692DFE /* EpisodesRowView.swift in Sources */,
|
||||
|
@ -2235,6 +2251,7 @@
|
|||
53FF7F2A263CF3F500585C35 /* LatestMediaView.swift in Sources */,
|
||||
E122A9132788EAAD0060FA63 /* MediaStreamExtension.swift in Sources */,
|
||||
E1C812C5277A90B200918266 /* URLComponentsExtensions.swift in Sources */,
|
||||
E1EBCB44278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift in Sources */,
|
||||
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
|
||||
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */,
|
||||
62C29EA826D103D500C1D2E7 /* LibraryListCoordinator.swift in Sources */,
|
||||
|
@ -2265,6 +2282,7 @@
|
|||
E19169CE272514760085832A /* HTTPScheme.swift in Sources */,
|
||||
53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */,
|
||||
C4AE2C3027498D2300AE13CF /* LiveTVHomeView.swift in Sources */,
|
||||
E1EBCB42278BD174009FE6E9 /* TruncatedTextView.swift in Sources */,
|
||||
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */,
|
||||
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */,
|
||||
62E632DA267D2BC40063E547 /* LatestMediaViewModel.swift in Sources */,
|
||||
|
@ -2319,6 +2337,7 @@
|
|||
E10D87DC2784EC5200BD264C /* EpisodesRowView.swift in Sources */,
|
||||
E1C812BE277A8E5D00918266 /* VLCPlayerViewController.swift in Sources */,
|
||||
E1AA331D2782541500F6439C /* PrimaryButtonView.swift in Sources */,
|
||||
E10C0941278B8DAB009DBF93 /* PortraitItemSize.swift in Sources */,
|
||||
62C29EA626D1036A00C1D2E7 /* HomeCoordinator.swift in Sources */,
|
||||
531AC8BF26750DE20091C7EB /* ImageView.swift in Sources */,
|
||||
C4BE07762725EBEA003F4AD1 /* LiveTVProgramsViewModel.swift in Sources */,
|
||||
|
@ -2336,6 +2355,7 @@
|
|||
62EC352F267666A5000E9F2D /* SessionManager.swift in Sources */,
|
||||
62E632E3267D3BA60063E547 /* MovieItemViewModel.swift in Sources */,
|
||||
C4BE076F2720FEFF003F4AD1 /* PlainNavigationLinkButton.swift in Sources */,
|
||||
E1EBCB46278BD595009FE6E9 /* ItemOverviewView.swift in Sources */,
|
||||
091B5A8A2683142E00D78B61 /* ServerDiscovery.swift in Sources */,
|
||||
62E632EF267D43320063E547 /* LibraryFilterViewModel.swift in Sources */,
|
||||
5D64683D277B1649009E09AE /* PreferenceUIHostingSwizzling.swift in Sources */,
|
||||
|
@ -2745,7 +2765,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 66;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = TY84JMYEFE;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
EXCLUDED_ARCHS = "";
|
||||
|
@ -2782,7 +2802,7 @@
|
|||
CURRENT_PROJECT_VERSION = 66;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = TY84JMYEFE;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
EXCLUDED_ARCHS = "";
|
||||
|
@ -2813,7 +2833,7 @@
|
|||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 66;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = TY84JMYEFE;
|
||||
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
@ -2840,7 +2860,7 @@
|
|||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 66;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = TY84JMYEFE;
|
||||
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
|
@ -106,6 +106,13 @@ struct EpisodesRowView: View {
|
|||
bh: episode.getBackdropImageBlurHash())
|
||||
.mask(Rectangle().frame(width: 200, height: 112).cornerRadius(10))
|
||||
.frame(width: 200, height: 112)
|
||||
.overlay {
|
||||
if episode.id == viewModel.episodeItemViewModel.item.id {
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.stroke(Color.jellyfinPurple, lineWidth: 4)
|
||||
}
|
||||
}
|
||||
.padding(.top)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text(episode.getEpisodeLocator() ?? "")
|
|
@ -46,8 +46,7 @@ struct PortraitImageHStackView<TopBarView: View, ItemType: PortraitImageStackabl
|
|||
ImageView(src: item.imageURLContsructor(maxWidth: Int(maxWidth)),
|
||||
bh: item.blurHash,
|
||||
failureInitials: item.failureInitials)
|
||||
.frame(width: maxWidth, height: maxWidth * 1.5)
|
||||
.cornerRadius(10)
|
||||
.portraitPoster(width: maxWidth)
|
||||
.shadow(radius: 4, y: 2)
|
||||
|
||||
if item.showTitle {
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct TruncatedTextView: View {
|
||||
|
||||
@State private var truncated: Bool = false
|
||||
@State private var shrinkText: String
|
||||
private var text: String
|
||||
let font: UIFont
|
||||
let lineLimit: Int
|
||||
let seeMoreAction: () -> Void
|
||||
|
||||
private var moreLessText: String {
|
||||
if !truncated {
|
||||
return ""
|
||||
} else {
|
||||
return "See More"
|
||||
}
|
||||
}
|
||||
|
||||
init(_ text: String,
|
||||
lineLimit: Int,
|
||||
font: UIFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body),
|
||||
seeMoreAction: @escaping () -> Void) {
|
||||
self.text = text
|
||||
self.lineLimit = lineLimit
|
||||
_shrinkText = State(wrappedValue: text)
|
||||
self.font = font
|
||||
self.seeMoreAction = seeMoreAction
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .center) {
|
||||
Group {
|
||||
Text(shrinkText)
|
||||
.overlay {
|
||||
if truncated {
|
||||
LinearGradient(stops: [.init(color: .systemBackground.opacity(0), location: 0.5),
|
||||
.init(color: .systemBackground.opacity(0.8), location: 0.7),
|
||||
.init(color: .systemBackground, location: 1)],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
.lineLimit(lineLimit)
|
||||
.background {
|
||||
// Render the limited text and measure its size
|
||||
Text(text)
|
||||
.lineLimit(lineLimit + 2)
|
||||
.background {
|
||||
GeometryReader { visibleTextGeometry in
|
||||
Color.clear
|
||||
.onAppear {
|
||||
let size = CGSize(width: visibleTextGeometry.size.width, height: .greatestFiniteMagnitude)
|
||||
let attributes:[NSAttributedString.Key:Any] = [NSAttributedString.Key.font: font]
|
||||
var low = 0
|
||||
var heigh = shrinkText.count
|
||||
var mid = heigh
|
||||
while ((heigh - low) > 1) {
|
||||
let attributedText = NSAttributedString(string: shrinkText, attributes: attributes)
|
||||
let boundingRect = attributedText.boundingRect(with: size, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil)
|
||||
if boundingRect.size.height > visibleTextGeometry.size.height {
|
||||
truncated = true
|
||||
heigh = mid
|
||||
mid = (heigh + low)/2
|
||||
|
||||
} else {
|
||||
if mid == text.count {
|
||||
break
|
||||
} else {
|
||||
low = mid
|
||||
mid = (low + heigh)/2
|
||||
}
|
||||
}
|
||||
shrinkText = String(text.prefix(mid))
|
||||
}
|
||||
|
||||
if truncated {
|
||||
shrinkText = String(shrinkText.prefix(shrinkText.count - 2))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.hidden()
|
||||
}
|
||||
.font(Font(font))
|
||||
|
||||
if truncated {
|
||||
Button {
|
||||
seeMoreAction()
|
||||
} label: {
|
||||
Text(moreLessText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import JellyfinAPI
|
||||
import SwiftUI
|
||||
|
||||
struct ItemOverviewView: View {
|
||||
|
||||
@EnvironmentObject var itemOverviewRouter: ItemOverviewCoordinator.Router
|
||||
let item: BaseItemDto
|
||||
|
||||
var body: some View {
|
||||
ScrollView(showsIndicators: false) {
|
||||
Text(item.overview ?? "")
|
||||
.font(.footnote)
|
||||
.padding()
|
||||
}
|
||||
.navigationBarTitle("Overview", displayMode: .inline)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarLeading) {
|
||||
Button {
|
||||
itemOverviewRouter.dismissCoordinator()
|
||||
} label: {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,8 @@ import SwiftUI
|
|||
|
||||
struct ItemViewBody: View {
|
||||
|
||||
@Environment(\.horizontalSizeClass) private var hSizeClass
|
||||
@Environment(\.verticalSizeClass) private var vSizeClass
|
||||
@EnvironmentObject var itemRouter: ItemCoordinator.Router
|
||||
@EnvironmentObject private var viewModel: ItemViewModel
|
||||
@Default(.showCastAndCrew) var showCastAndCrew
|
||||
|
@ -20,11 +22,26 @@ struct ItemViewBody: View {
|
|||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
// MARK: Overview
|
||||
|
||||
Text(viewModel.item.overview ?? "")
|
||||
.font(.footnote)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 3)
|
||||
|
||||
if let itemOverview = viewModel.item.overview {
|
||||
if hSizeClass == .compact && vSizeClass == .regular {
|
||||
TruncatedTextView(itemOverview,
|
||||
lineLimit: 5,
|
||||
font: UIFont.preferredFont(forTextStyle: .footnote)) {
|
||||
itemRouter.route(to: \.itemOverview, viewModel.item)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.top)
|
||||
} else {
|
||||
Text(itemOverview)
|
||||
.font(.footnote)
|
||||
.padding()
|
||||
}
|
||||
} else {
|
||||
Text("No overview available")
|
||||
.font(.footnote)
|
||||
.padding()
|
||||
}
|
||||
|
||||
// MARK: Seasons
|
||||
|
||||
|
|
|
@ -21,8 +21,7 @@ struct PortraitHeaderOverlayView: View {
|
|||
|
||||
// MARK: Portrait Image
|
||||
ImageView(src: viewModel.item.portraitHeaderViewURL(maxWidth: 130))
|
||||
.frame(width: 130, height: 195)
|
||||
.cornerRadius(10)
|
||||
.portraitPoster(width: 130)
|
||||
|
||||
VStack(alignment: .leading, spacing: 1) {
|
||||
Spacer()
|
||||
|
|
Loading…
Reference in New Issue