Simplify item view creation
This commit is contained in:
parent
7a79b78e38
commit
2dbb0bd890
|
@ -78,8 +78,8 @@
|
|||
53649AB2269D019100A2D8B7 /* LogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53649AB0269CFB1900A2D8B7 /* LogManager.swift */; };
|
||||
53649AB3269D3F5B00A2D8B7 /* LogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53649AB0269CFB1900A2D8B7 /* LogManager.swift */; };
|
||||
53649AB5269D423A00A2D8B7 /* Puppy in Frameworks */ = {isa = PBXBuildFile; productRef = 53649AB4269D423A00A2D8B7 /* Puppy */; };
|
||||
5364F455266CA0DC0026ECBA /* APIExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5364F454266CA0DC0026ECBA /* APIExtensions.swift */; };
|
||||
5364F456266CA0DC0026ECBA /* APIExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5364F454266CA0DC0026ECBA /* APIExtensions.swift */; };
|
||||
5364F455266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5364F454266CA0DC0026ECBA /* BaseItemPersonExtensions.swift */; };
|
||||
5364F456266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5364F454266CA0DC0026ECBA /* BaseItemPersonExtensions.swift */; };
|
||||
536D3D74267BA8170004248C /* BackgroundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536D3D73267BA8170004248C /* BackgroundManager.swift */; };
|
||||
536D3D76267BA9BB0004248C /* MainTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536D3D75267BA9BB0004248C /* MainTabViewModel.swift */; };
|
||||
536D3D78267BD5C30004248C /* ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB57B2678CE1000530A6E /* ViewModel.swift */; };
|
||||
|
@ -188,7 +188,6 @@
|
|||
625CB57A2678C4A400530A6E /* ActivityIndicator in Frameworks */ = {isa = PBXBuildFile; productRef = 625CB5792678C4A400530A6E /* ActivityIndicator */; };
|
||||
6260FFF926A09754003FA968 /* CombineExt in Frameworks */ = {isa = PBXBuildFile; productRef = 6260FFF826A09754003FA968 /* CombineExt */; };
|
||||
6261A0E026A0AB710072EF1C /* CombineExt in Frameworks */ = {isa = PBXBuildFile; productRef = 6261A0DF26A0AB710072EF1C /* CombineExt */; };
|
||||
6267B3D42671024A00A7371D /* APIExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5364F454266CA0DC0026ECBA /* APIExtensions.swift */; };
|
||||
6267B3D626710B8900A7371D /* CollectionExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6267B3D526710B8900A7371D /* CollectionExtensions.swift */; };
|
||||
6267B3D726710B9700A7371D /* CollectionExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6267B3D526710B8900A7371D /* CollectionExtensions.swift */; };
|
||||
6267B3D826710B9800A7371D /* CollectionExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6267B3D526710B8900A7371D /* CollectionExtensions.swift */; };
|
||||
|
@ -242,6 +241,20 @@
|
|||
E173DA5026D048D600CC4EB7 /* ServerDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */; };
|
||||
E173DA5226D04AAF00CC4EB7 /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */; };
|
||||
E173DA5426D050F500CC4EB7 /* ServerDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA5326D050F500CC4EB7 /* ServerDetailViewModel.swift */; };
|
||||
E1AD104A26D94822003E4A08 /* DetailItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD104926D94822003E4A08 /* DetailItem.swift */; };
|
||||
E1AD104B26D94822003E4A08 /* DetailItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD104926D94822003E4A08 /* DetailItem.swift */; };
|
||||
E1AD104D26D96CE3003E4A08 /* BaseItemDtoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD104C26D96CE3003E4A08 /* BaseItemDtoExtensions.swift */; };
|
||||
E1AD104E26D96CE3003E4A08 /* BaseItemDtoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD104C26D96CE3003E4A08 /* BaseItemDtoExtensions.swift */; };
|
||||
E1AD105426D97161003E4A08 /* BaseItemDtoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD104C26D96CE3003E4A08 /* BaseItemDtoExtensions.swift */; };
|
||||
E1AD105626D981CE003E4A08 /* PortraitHStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD105526D981CE003E4A08 /* PortraitHStackView.swift */; };
|
||||
E1AD105726D981CE003E4A08 /* PortraitHStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD105526D981CE003E4A08 /* PortraitHStackView.swift */; };
|
||||
E1AD105926D9A543003E4A08 /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338B22660A07800A81A2A /* LazyView.swift */; };
|
||||
E1AD105C26D9ABDD003E4A08 /* PillHStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD105B26D9ABDD003E4A08 /* PillHStackView.swift */; };
|
||||
E1AD105D26D9ABDD003E4A08 /* PillHStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD105B26D9ABDD003E4A08 /* PillHStackView.swift */; };
|
||||
E1AD105F26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD105E26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift */; };
|
||||
E1AD106026D9ADDD003E4A08 /* NameGUIDPairExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD105E26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift */; };
|
||||
E1AD106226D9B7CD003E4A08 /* PortraitHeaderOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD106126D9B7CD003E4A08 /* PortraitHeaderOverlayView.swift */; };
|
||||
E1AD106326D9B7CD003E4A08 /* PortraitHeaderOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD106126D9B7CD003E4A08 /* PortraitHeaderOverlayView.swift */; };
|
||||
E1F0204E26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; };
|
||||
E1F0204F26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; };
|
||||
E1FCD08826C35A0D007C8DCF /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD08726C35A0D007C8DCF /* NetworkError.swift */; };
|
||||
|
@ -347,7 +360,7 @@
|
|||
5362E4C6267D40F4000E2F71 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
5362E4C8267D40F7000E2F71 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
53649AB0269CFB1900A2D8B7 /* LogManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogManager.swift; sourceTree = "<group>"; };
|
||||
5364F454266CA0DC0026ECBA /* APIExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIExtensions.swift; sourceTree = "<group>"; };
|
||||
5364F454266CA0DC0026ECBA /* BaseItemPersonExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseItemPersonExtensions.swift; sourceTree = "<group>"; };
|
||||
536D3D73267BA8170004248C /* BackgroundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundManager.swift; sourceTree = "<group>"; };
|
||||
536D3D75267BA9BB0004248C /* MainTabViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabViewModel.swift; sourceTree = "<group>"; };
|
||||
536D3D7E267BDF100004248C /* LatestMediaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestMediaView.swift; sourceTree = "<group>"; };
|
||||
|
@ -446,6 +459,12 @@
|
|||
E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailView.swift; sourceTree = "<group>"; };
|
||||
E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = "<group>"; };
|
||||
E173DA5326D050F500CC4EB7 /* ServerDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailViewModel.swift; sourceTree = "<group>"; };
|
||||
E1AD104926D94822003E4A08 /* DetailItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailItem.swift; sourceTree = "<group>"; };
|
||||
E1AD104C26D96CE3003E4A08 /* BaseItemDtoExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseItemDtoExtensions.swift; sourceTree = "<group>"; };
|
||||
E1AD105526D981CE003E4A08 /* PortraitHStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortraitHStackView.swift; sourceTree = "<group>"; };
|
||||
E1AD105B26D9ABDD003E4A08 /* PillHStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillHStackView.swift; sourceTree = "<group>"; };
|
||||
E1AD105E26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameGUIDPairExtensions.swift; sourceTree = "<group>"; };
|
||||
E1AD106126D9B7CD003E4A08 /* PortraitHeaderOverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortraitHeaderOverlayView.swift; sourceTree = "<group>"; };
|
||||
E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerJumpLength.swift; sourceTree = "<group>"; };
|
||||
E1FCD08726C35A0D007C8DCF /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = "<group>"; };
|
||||
E1FCD09526C47118007C8DCF /* ErrorMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorMessage.swift; sourceTree = "<group>"; };
|
||||
|
@ -658,7 +677,11 @@
|
|||
535870AB2669D8D300D05A09 /* Objects */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E1AD105326D96F5A003E4A08 /* Views */,
|
||||
62EC353326766B03000E9F2D /* DeviceRotationViewModifier.swift */,
|
||||
53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */,
|
||||
535870AC2669D8DD00D05A09 /* Typings.swift */,
|
||||
E1AD104926D94822003E4A08 /* DetailItem.swift */,
|
||||
E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */,
|
||||
);
|
||||
path = Objects;
|
||||
|
@ -898,6 +921,9 @@
|
|||
53F866422687A45400DCD1D7 /* Components */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E1AD105B26D9ABDD003E4A08 /* PillHStackView.swift */,
|
||||
E1AD106126D9B7CD003E4A08 /* PortraitHeaderOverlayView.swift */,
|
||||
E1AD105526D981CE003E4A08 /* PortraitHStackView.swift */,
|
||||
53F866432687A45F00DCD1D7 /* PortraitItemView.swift */,
|
||||
);
|
||||
path = Components;
|
||||
|
@ -906,21 +932,13 @@
|
|||
621338912660106C00A81A2A /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
53DE4BD1267098F300739748 /* SearchBarView.swift */,
|
||||
E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */,
|
||||
53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */,
|
||||
531AC8BE26750DE20091C7EB /* ImageView.swift */,
|
||||
5364F454266CA0DC0026ECBA /* APIExtensions.swift */,
|
||||
5389277B263CC3DB0035E14B /* BlurHashDecode.swift */,
|
||||
621338B22660A07800A81A2A /* LazyView.swift */,
|
||||
53E4E648263F725B00F67C6B /* MultiSelectorView.swift */,
|
||||
6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */,
|
||||
621338922660107500A81A2A /* StringExtensions.swift */,
|
||||
6267B3D526710B8900A7371D /* CollectionExtensions.swift */,
|
||||
6267B3D92671138200A7371D /* ImageExtensions.swift */,
|
||||
62EC353326766B03000E9F2D /* DeviceRotationViewModifier.swift */,
|
||||
E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */,
|
||||
62CB3F4A2685BB77003D0A6F /* DefaultsExtension.swift */,
|
||||
624C21742685CF60007F1390 /* SearchablePickerView.swift */,
|
||||
6267B3D92671138200A7371D /* ImageExtensions.swift */,
|
||||
E1AD105226D96D5F003E4A08 /* JellyfinAPIExtensions */,
|
||||
621338922660107500A81A2A /* StringExtensions.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
|
@ -940,10 +958,10 @@
|
|||
62EC352A26766657000E9F2D /* Singleton */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
62EC352B26766675000E9F2D /* ServerEnvironment.swift */,
|
||||
62EC352E267666A5000E9F2D /* SessionManager.swift */,
|
||||
536D3D73267BA8170004248C /* BackgroundManager.swift */,
|
||||
53649AB0269CFB1900A2D8B7 /* LogManager.swift */,
|
||||
62EC352B26766675000E9F2D /* ServerEnvironment.swift */,
|
||||
62EC352E267666A5000E9F2D /* SessionManager.swift */,
|
||||
);
|
||||
path = Singleton;
|
||||
sourceTree = "<group>";
|
||||
|
@ -968,12 +986,35 @@
|
|||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E1AD105226D96D5F003E4A08 /* JellyfinAPIExtensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5364F454266CA0DC0026ECBA /* BaseItemPersonExtensions.swift */,
|
||||
E1AD104C26D96CE3003E4A08 /* BaseItemDtoExtensions.swift */,
|
||||
E1AD105E26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift */,
|
||||
);
|
||||
path = JellyfinAPIExtensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E1AD105326D96F5A003E4A08 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
531AC8BE26750DE20091C7EB /* ImageView.swift */,
|
||||
621338B22660A07800A81A2A /* LazyView.swift */,
|
||||
53E4E648263F725B00F67C6B /* MultiSelectorView.swift */,
|
||||
6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */,
|
||||
624C21742685CF60007F1390 /* SearchablePickerView.swift */,
|
||||
53DE4BD1267098F300739748 /* SearchBarView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E1FCD08E26C466F3007C8DCF /* Errors */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E1FCD08726C35A0D007C8DCF /* NetworkError.swift */,
|
||||
E131691626C583BC0074BFEE /* LogConstructor.swift */,
|
||||
E1FCD09526C47118007C8DCF /* ErrorMessage.swift */,
|
||||
E131691626C583BC0074BFEE /* LogConstructor.swift */,
|
||||
E1FCD08726C35A0D007C8DCF /* NetworkError.swift */,
|
||||
);
|
||||
path = Errors;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1346,6 +1387,7 @@
|
|||
E1FCD08926C35A0D007C8DCF /* NetworkError.swift in Sources */,
|
||||
531690ED267ABF46005D8AB9 /* ContinueWatchingView.swift in Sources */,
|
||||
62EC3530267666A5000E9F2D /* SessionManager.swift in Sources */,
|
||||
E1AD104B26D94822003E4A08 /* DetailItem.swift in Sources */,
|
||||
53272539268C20100035FBF1 /* EpisodeItemView.swift in Sources */,
|
||||
531690F7267ACC00005D8AB9 /* LandscapeItemElement.swift in Sources */,
|
||||
62E632E1267D30CA0063E547 /* LibraryViewModel.swift in Sources */,
|
||||
|
@ -1359,15 +1401,18 @@
|
|||
62E632F4267D54030063E547 /* DetailItemViewModel.swift in Sources */,
|
||||
6267B3D826710B9800A7371D /* CollectionExtensions.swift in Sources */,
|
||||
62E632E7267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */,
|
||||
E1AD106326D9B7CD003E4A08 /* PortraitHeaderOverlayView.swift in Sources */,
|
||||
E100720726BDABC100CE3E31 /* MediaPlayButtonRowView.swift in Sources */,
|
||||
535870A52669D8AE00D05A09 /* ParallaxHeader.swift in Sources */,
|
||||
53272532268BF09D0035FBF1 /* MediaViewActionButton.swift in Sources */,
|
||||
531690F0267ABF72005D8AB9 /* NextUpView.swift in Sources */,
|
||||
535870A72669D8AE00D05A09 /* MultiSelectorView.swift in Sources */,
|
||||
E1AD104E26D96CE3003E4A08 /* BaseItemDtoExtensions.swift in Sources */,
|
||||
62E632DD267D2E130063E547 /* LibrarySearchViewModel.swift in Sources */,
|
||||
536D3D81267BDFC60004248C /* PortraitItemElement.swift in Sources */,
|
||||
531690E5267ABD5C005D8AB9 /* MainTabView.swift in Sources */,
|
||||
5310695B2684E7EE00CFFDBA /* AudioView.swift in Sources */,
|
||||
E1AD106026D9ADDD003E4A08 /* NameGUIDPairExtensions.swift in Sources */,
|
||||
5398514726B64E4100101B49 /* SearchBarView.swift in Sources */,
|
||||
091B5A8D268315D400D78B61 /* ServerDiscovery.swift in Sources */,
|
||||
53ABFDE7267974EF00886593 /* ConnectToServerViewModel.swift in Sources */,
|
||||
|
@ -1391,9 +1436,11 @@
|
|||
536D3D74267BA8170004248C /* BackgroundManager.swift in Sources */,
|
||||
535870632669D21600D05A09 /* JellyfinPlayer_tvOSApp.swift in Sources */,
|
||||
53ABFDE4267974EF00886593 /* LibraryListViewModel.swift in Sources */,
|
||||
5364F456266CA0DC0026ECBA /* APIExtensions.swift in Sources */,
|
||||
5364F456266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */,
|
||||
E1AD105D26D9ABDD003E4A08 /* PillHStackView.swift in Sources */,
|
||||
531690FA267AD6EC005D8AB9 /* PlainNavigationLinkButton.swift in Sources */,
|
||||
E131691826C583BC0074BFEE /* LogConstructor.swift in Sources */,
|
||||
E1AD105726D981CE003E4A08 /* PortraitHStackView.swift in Sources */,
|
||||
535870A32669D89F00D05A09 /* Model.xcdatamodeld in Sources */,
|
||||
09389CC826819B4600AE350E /* VideoPlayerModel.swift in Sources */,
|
||||
);
|
||||
|
@ -1403,7 +1450,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5364F455266CA0DC0026ECBA /* APIExtensions.swift in Sources */,
|
||||
5364F455266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */,
|
||||
621338932660107500A81A2A /* StringExtensions.swift in Sources */,
|
||||
53FF7F2A263CF3F500585C35 /* LatestMediaView.swift in Sources */,
|
||||
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
|
||||
|
@ -1412,6 +1459,7 @@
|
|||
5377CBFE263B596B003A4E83 /* PersistenceController.swift in Sources */,
|
||||
5389276E263C25100035E14B /* ContinueWatchingView.swift in Sources */,
|
||||
53F866442687A45F00DCD1D7 /* PortraitItemView.swift in Sources */,
|
||||
E1AD105626D981CE003E4A08 /* PortraitHStackView.swift in Sources */,
|
||||
53AD124E26702B8A0094A276 /* SeasonItemView.swift in Sources */,
|
||||
535BAE9F2649E569005FA86D /* ItemView.swift in Sources */,
|
||||
6225FCCB2663841E00E067F6 /* ParallaxHeader.swift in Sources */,
|
||||
|
@ -1426,6 +1474,7 @@
|
|||
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */,
|
||||
0959A5FD2686D29800C7C9A9 /* VideoUpNextView.swift in Sources */,
|
||||
62E632DA267D2BC40063E547 /* LatestMediaViewModel.swift in Sources */,
|
||||
E1AD105C26D9ABDD003E4A08 /* PillHStackView.swift in Sources */,
|
||||
625CB56F2678C23300530A6E /* HomeView.swift in Sources */,
|
||||
E173DA5226D04AAF00CC4EB7 /* ColorExtension.swift in Sources */,
|
||||
53892770263C25230035E14B /* NextUpView.swift in Sources */,
|
||||
|
@ -1447,9 +1496,11 @@
|
|||
625CB56A2678B71200530A6E /* SplashViewModel.swift in Sources */,
|
||||
62E632F3267D54030063E547 /* DetailItemViewModel.swift in Sources */,
|
||||
53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */,
|
||||
E1AD106226D9B7CD003E4A08 /* PortraitHeaderOverlayView.swift in Sources */,
|
||||
53E4E649263F725B00F67C6B /* MultiSelectorView.swift in Sources */,
|
||||
621338B32660A07800A81A2A /* LazyView.swift in Sources */,
|
||||
531AC8BF26750DE20091C7EB /* ImageView.swift in Sources */,
|
||||
E1AD104A26D94822003E4A08 /* DetailItem.swift in Sources */,
|
||||
62E632E0267D30CA0063E547 /* LibraryViewModel.swift in Sources */,
|
||||
624C21752685CF60007F1390 /* SearchablePickerView.swift in Sources */,
|
||||
E173DA5026D048D600CC4EB7 /* ServerDetailView.swift in Sources */,
|
||||
|
@ -1457,7 +1508,9 @@
|
|||
62E632E3267D3BA60063E547 /* MovieItemViewModel.swift in Sources */,
|
||||
091B5A8A2683142E00D78B61 /* ServerDiscovery.swift in Sources */,
|
||||
62E632EF267D43320063E547 /* LibraryFilterViewModel.swift in Sources */,
|
||||
E1AD104D26D96CE3003E4A08 /* BaseItemDtoExtensions.swift in Sources */,
|
||||
535870AD2669D8DD00D05A09 /* Typings.swift in Sources */,
|
||||
E1AD105F26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift in Sources */,
|
||||
62EC352C26766675000E9F2D /* ServerEnvironment.swift in Sources */,
|
||||
6267B3DA2671138200A7371D /* ImageExtensions.swift in Sources */,
|
||||
62EC353426766B03000E9F2D /* DeviceRotationViewModifier.swift in Sources */,
|
||||
|
@ -1481,11 +1534,12 @@
|
|||
files = (
|
||||
53649AB3269D3F5B00A2D8B7 /* LogManager.swift in Sources */,
|
||||
62EC353126766848000E9F2D /* ServerEnvironment.swift in Sources */,
|
||||
6267B3D42671024A00A7371D /* APIExtensions.swift in Sources */,
|
||||
6267B3D726710B9700A7371D /* CollectionExtensions.swift in Sources */,
|
||||
628B953C2670D2430091AF3B /* StringExtensions.swift in Sources */,
|
||||
6267B3DB2671139400A7371D /* ImageExtensions.swift in Sources */,
|
||||
E1AD105926D9A543003E4A08 /* LazyView.swift in Sources */,
|
||||
628B95372670CB800091AF3B /* JellyfinWidget.swift in Sources */,
|
||||
E1AD105426D97161003E4A08 /* BaseItemDtoExtensions.swift in Sources */,
|
||||
6228B1C22670EB010067FD35 /* PersistenceController.swift in Sources */,
|
||||
E1FCD09A26C4F35A007C8DCF /* ErrorMessage.swift in Sources */,
|
||||
628B95272670CABD0091AF3B /* NextUpWidget.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
/*
|
||||
* 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
|
||||
|
||||
protocol PillStackable {
|
||||
var title: String { get }
|
||||
}
|
||||
|
||||
struct PillHStackView<NavigationView: View, ItemType: PillStackable>: View {
|
||||
|
||||
let title: String
|
||||
let items: [ItemType]
|
||||
let navigationView: (ItemType) -> NavigationView
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text(title)
|
||||
.font(.callout)
|
||||
.fontWeight(.semibold)
|
||||
.padding(.top, 3)
|
||||
.padding(.leading, 16)
|
||||
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack {
|
||||
ForEach(items, id: \.title) { item in
|
||||
NavigationLink(destination: LazyView {
|
||||
navigationView(item)
|
||||
}) {
|
||||
ZStack {
|
||||
Color(UIColor.secondarySystemBackground)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.cornerRadius(10)
|
||||
|
||||
Text(item.title)
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.white)
|
||||
.fixedSize()
|
||||
.padding(.leading, 10)
|
||||
.padding(.trailing, 10)
|
||||
.padding(.top, 10)
|
||||
.padding(.bottom, 10)
|
||||
}
|
||||
.fixedSize()
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.leading, 16)
|
||||
.padding(.trailing, UIDevice.current.userInterfaceIdiom == .pad ? 16 : 55)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
/*
|
||||
* 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
|
||||
|
||||
public protocol PortraitImageStackable {
|
||||
func imageURLContsructor(maxWidth: Int) -> URL
|
||||
var title: String { get }
|
||||
var description: String? { get }
|
||||
var blurHash: String { get }
|
||||
}
|
||||
|
||||
struct PortraitImageHStackView<NavigationView: View, ItemType: PortraitImageStackable>: View {
|
||||
|
||||
let title: String
|
||||
let items: [ItemType]
|
||||
let maxWidth: Int
|
||||
let navigationView: (ItemType) -> NavigationView
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text(title)
|
||||
.font(.callout)
|
||||
.fontWeight(.semibold)
|
||||
.padding(.top, 3)
|
||||
.padding(.leading, 16)
|
||||
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
VStack {
|
||||
Spacer().frame(height: 8)
|
||||
HStack {
|
||||
Spacer().frame(width: 16)
|
||||
ForEach(items, id: \.title) { item in
|
||||
NavigationLink(
|
||||
destination: LazyView {
|
||||
navigationView(item)
|
||||
},
|
||||
label: {
|
||||
VStack {
|
||||
ImageView(src: item.imageURLContsructor(maxWidth: maxWidth),
|
||||
bh: item.blurHash)
|
||||
.frame(width: 100, height: CGFloat(maxWidth))
|
||||
.cornerRadius(10)
|
||||
.shadow(radius: 4, y: 2)
|
||||
|
||||
Text(item.title)
|
||||
.font(.footnote)
|
||||
.fontWeight(.regular)
|
||||
.lineLimit(1)
|
||||
.frame(width: 100)
|
||||
.foregroundColor(.primary)
|
||||
|
||||
if let description = item.description {
|
||||
Text(description)
|
||||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
.lineLimit(1)
|
||||
.frame(width: 100)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Spacer().frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 16 : 55)
|
||||
}
|
||||
}
|
||||
}.padding(.top, -3)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
//
|
||||
/*
|
||||
* 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
|
||||
import JellyfinAPI
|
||||
|
||||
struct PortraitHeaderOverlayView: View {
|
||||
|
||||
@EnvironmentObject var viewModel: DetailItemViewModel
|
||||
let item: BaseItemDto
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack(alignment: .bottom, spacing: 12) {
|
||||
ImageView(src: item.portraitHeaderViewURL(maxWidth: 130))
|
||||
.frame(width: 130, height: 195)
|
||||
.cornerRadius(10)
|
||||
|
||||
VStack(alignment: .leading, spacing: 1) {
|
||||
Spacer()
|
||||
|
||||
Text(item.name ?? "")
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.offset(y: 5)
|
||||
|
||||
Text(item.getItemRuntime())
|
||||
.font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.padding(.top, 10)
|
||||
|
||||
HStack {
|
||||
if let productionYear = item.productionYear {
|
||||
Text(String(productionYear))
|
||||
.font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
if let officialRating = item.officialRating {
|
||||
Text(officialRating)
|
||||
.font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.padding(EdgeInsets(top: 1, leading: 4, bottom: 1, trailing: 4))
|
||||
.overlay(RoundedRectangle(cornerRadius: 2)
|
||||
.stroke(Color.secondary, lineWidth: 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? 98 : 30)
|
||||
}
|
||||
|
||||
HStack {
|
||||
// Play button
|
||||
Button {
|
||||
()
|
||||
// self.playbackInfo.itemToPlay = item
|
||||
// self.playbackInfo.shouldShowPlayer = true
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "play.fill").foregroundColor(Color.white).font(.system(size: 20))
|
||||
Text(item.getItemProgressString() == "" ? "Play" : item.getItemProgressString())
|
||||
.foregroundColor(Color.white).font(.callout).fontWeight(.semibold)
|
||||
}
|
||||
.frame(width: 130, height: 40)
|
||||
.background(Color.jellyfinPurple)
|
||||
.cornerRadius(10)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
print("Heart")
|
||||
} label: {
|
||||
Image(systemName: "heart").foregroundColor(.primary)
|
||||
.font(.system(size: 20))
|
||||
}
|
||||
|
||||
Button {
|
||||
print("Check")
|
||||
} label: {
|
||||
Image(systemName: "checkmark.circle").foregroundColor(.primary)
|
||||
.font(.system(size: 20))
|
||||
}
|
||||
|
||||
|
||||
// Button {
|
||||
// updateFavoriteState()
|
||||
// ()
|
||||
// } label: {
|
||||
// if viewModel.isFavorited {
|
||||
// Image(systemName: "heart.fill").foregroundColor(Color(UIColor.systemRed))
|
||||
// .font(.system(size: 20))
|
||||
// } else {
|
||||
// Image(systemName: "heart").foregroundColor(Color.primary)
|
||||
// .font(.system(size: 20))
|
||||
// }
|
||||
// }
|
||||
// .disabled(viewModel.isLoading)
|
||||
// Button {
|
||||
// viewModel.updateWatchState()
|
||||
// ()
|
||||
// } label: {
|
||||
// if viewModel.isWatched {
|
||||
// Image(systemName: "checkmark.circle.fill").foregroundColor(Color.primary)
|
||||
// .font(.system(size: 20))
|
||||
// } else {
|
||||
// Image(systemName: "checkmark.circle").foregroundColor(Color.primary)
|
||||
// .font(.system(size: 20))
|
||||
// }
|
||||
// }
|
||||
// .disabled(viewModel.isLoading)
|
||||
// }
|
||||
}.padding(.top, 8)
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? -189 : -64)
|
||||
}
|
||||
}
|
|
@ -9,7 +9,9 @@
|
|||
|
||||
import SwiftUI
|
||||
import JellyfinAPI
|
||||
|
||||
struct PortraitItemView: View {
|
||||
|
||||
var item: BaseItemDto
|
||||
|
||||
var body: some View {
|
||||
|
|
|
@ -34,118 +34,15 @@ struct ItemView: View {
|
|||
}
|
||||
|
||||
var portraitHeaderOverlayView: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack(alignment: .bottom, spacing: 12) {
|
||||
ImageView(src: item.getPrimaryImage(maxWidth: 130))
|
||||
.frame(width: 130, height: 195)
|
||||
.cornerRadius(10)
|
||||
VStack(alignment: .leading) {
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(item.name ?? "").font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
.lineLimit(1)
|
||||
.offset(y: 5)
|
||||
|
||||
HStack {
|
||||
if item.productionYear != nil {
|
||||
Text(String(item.productionYear ?? 0)).font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
Text(item.getItemRuntime()).font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
|
||||
if item.officialRating != nil {
|
||||
Text(item.officialRating!).font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.padding(EdgeInsets(top: 1, leading: 4, bottom: 1, trailing: 4))
|
||||
.overlay(RoundedRectangle(cornerRadius: 2)
|
||||
.stroke(Color.secondary, lineWidth: 1))
|
||||
}
|
||||
}
|
||||
.padding(.top, 1)
|
||||
}
|
||||
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? 98 : 30)
|
||||
}
|
||||
HStack {
|
||||
// Play button
|
||||
Button {
|
||||
()
|
||||
// self.playbackInfo.itemToPlay = item
|
||||
// self.playbackInfo.shouldShowPlayer = true
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "play.fill").foregroundColor(Color.white).font(.system(size: 20))
|
||||
Text(item.getItemProgressString() == "" ? "Play" : item.getItemProgressString())
|
||||
.foregroundColor(Color.white).font(.callout).fontWeight(.semibold)
|
||||
}
|
||||
.frame(width: 130, height: 40)
|
||||
.background(Color.jellyfinPurple)
|
||||
.cornerRadius(10)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
print("Heart")
|
||||
} label: {
|
||||
Image(systemName: "heart").foregroundColor(.primary)
|
||||
.font(.system(size: 20))
|
||||
}
|
||||
|
||||
Button {
|
||||
print("Check")
|
||||
} label: {
|
||||
Image(systemName: "checkmark.circle").foregroundColor(.primary)
|
||||
.font(.system(size: 20))
|
||||
}
|
||||
|
||||
|
||||
// Button {
|
||||
// updateFavoriteState()
|
||||
// ()
|
||||
// } label: {
|
||||
// if viewModel.isFavorited {
|
||||
// Image(systemName: "heart.fill").foregroundColor(Color(UIColor.systemRed))
|
||||
// .font(.system(size: 20))
|
||||
// } else {
|
||||
// Image(systemName: "heart").foregroundColor(Color.primary)
|
||||
// .font(.system(size: 20))
|
||||
// }
|
||||
// }
|
||||
// .disabled(viewModel.isLoading)
|
||||
// Button {
|
||||
// viewModel.updateWatchState()
|
||||
// ()
|
||||
// } label: {
|
||||
// if viewModel.isWatched {
|
||||
// Image(systemName: "checkmark.circle.fill").foregroundColor(Color.primary)
|
||||
// .font(.system(size: 20))
|
||||
// } else {
|
||||
// Image(systemName: "checkmark.circle").foregroundColor(Color.primary)
|
||||
// .font(.system(size: 20))
|
||||
// }
|
||||
// }
|
||||
// .disabled(viewModel.isLoading)
|
||||
// }
|
||||
}.padding(.top, 8)
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? -189 : -64)
|
||||
PortraitHeaderOverlayView(item: item)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
NavigationLink(destination: LoadingViewNoBlur(isShowing: $videoIsLoading) { VLCPlayerWithControls(item: videoPlayerItem.itemToPlay, loadBinding: $videoIsLoading, pBinding: _videoPlayerItem.projectedValue.shouldShowPlayer)
|
||||
NavigationLink(destination: LoadingViewNoBlur(isShowing: $videoIsLoading) {
|
||||
VLCPlayerWithControls(item: videoPlayerItem.itemToPlay,
|
||||
loadBinding: $videoIsLoading,
|
||||
pBinding: _videoPlayerItem.projectedValue.shouldShowPlayer)
|
||||
.navigationBarHidden(true)
|
||||
.navigationBarBackButtonHidden(true)
|
||||
.statusBar(hidden: true)
|
||||
|
@ -158,29 +55,53 @@ struct ItemView: View {
|
|||
ParallaxHeaderScrollView(header: portraitHeaderView,
|
||||
staticOverlayView: portraitHeaderOverlayView,
|
||||
overlayAlignment: .bottomLeading,
|
||||
headerHeight: UIDevice.current.userInterfaceIdiom == .pad ? 350 : UIScreen.main.bounds
|
||||
.width * 0.5625) {
|
||||
headerHeight: UIDevice.current.userInterfaceIdiom == .pad ? 350 : UIScreen.main.bounds.width * 0.5625) {
|
||||
VStack {
|
||||
Spacer()
|
||||
.frame(height: UIDevice.current.userInterfaceIdiom == .pad ? 135 : 40)
|
||||
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? 54 : 24)
|
||||
|
||||
// MARK: Overview
|
||||
Text(item.overview ?? "")
|
||||
.font(.footnote)
|
||||
.padding(.top, 3)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom, 3)
|
||||
.padding(.leading, 16)
|
||||
.padding(.trailing, UIDevice.current.userInterfaceIdiom == .pad ? 16 : 55)
|
||||
|
||||
|
||||
|
||||
|
||||
if item.type == "Movie" {
|
||||
// MovieItemView(viewModel: .init(item: item))
|
||||
Text("Movie")
|
||||
} else if item.type == "Season" {
|
||||
SeasonItemView(viewModel: .init(item: item))
|
||||
} else if item.type == "Series" {
|
||||
SeriesItemView(viewModel: .init(item: item))
|
||||
} else if item.type == "Episode" {
|
||||
EpisodeItemView(viewModel: .init(item: item))
|
||||
} else {
|
||||
Text("Type: \(item.type ?? "") not implemented yet :(")
|
||||
// MARK: Genres
|
||||
PillHStackView(title: "Genres", items: item.genreItems ?? []) { genre in
|
||||
LibraryView(viewModel: .init(genre: genre), title: genre.title)
|
||||
}
|
||||
|
||||
// MARK: Studios
|
||||
if !(item.studios ?? []).isEmpty {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack {
|
||||
Text("Studios:").font(.callout).fontWeight(.semibold)
|
||||
ForEach(item.studios!, id: \.id) { studio in
|
||||
NavigationLink(destination: LazyView {
|
||||
LibraryView(viewModel: .init(studio: studio), title: studio.name ?? "")
|
||||
}) {
|
||||
Text(studio.name ?? "").font(.footnote)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.leading, 16)
|
||||
.padding(.trailing, UIDevice.current.userInterfaceIdiom == .pad ? 16 : 55)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Cast
|
||||
PortraitImageHStackView(title: "Cast",
|
||||
items: item.people!,
|
||||
maxWidth: 150) { person in
|
||||
LibraryView(viewModel: .init(person: person), title: person.title)
|
||||
}
|
||||
|
||||
// MARK: More Like This
|
||||
|
||||
}
|
||||
.introspectTabBarController { (UITabBarController) in
|
||||
UITabBarController.tabBar.isHidden = false
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* SwiftFin is subject to the terms of the Mozilla Public
|
||||
//
|
||||
/*
|
||||
* 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/.
|
||||
*
|
||||
|
@ -11,7 +13,8 @@ import UIKit
|
|||
|
||||
// 001fC^ = dark grey plain blurhash
|
||||
|
||||
extension BaseItemDto {
|
||||
public extension BaseItemDto {
|
||||
|
||||
// MARK: Images
|
||||
|
||||
func getSeriesBackdropImageBlurHash() -> String {
|
||||
|
@ -149,27 +152,33 @@ extension BaseItemDto {
|
|||
return "\(String(progminutes))m"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func round(_ value: Double, toNearest: Double) -> Double {
|
||||
return round(value / toNearest) * toNearest
|
||||
}
|
||||
// MARK: ItemType
|
||||
|
||||
extension BaseItemPerson {
|
||||
func getImage(baseURL: String, maxWidth: Int) -> URL {
|
||||
let imageType = "Primary"
|
||||
let imageTag = primaryImageTag ?? ""
|
||||
enum ItemType: String {
|
||||
case movie = "Movie"
|
||||
case season = "Season"
|
||||
case episode = "Episode"
|
||||
case series = "Series"
|
||||
|
||||
let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
|
||||
|
||||
let urlString = "\(baseURL)/Items/\(id ?? "")/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=85&tag=\(imageTag)"
|
||||
return URL(string: urlString)!
|
||||
case unknown
|
||||
}
|
||||
|
||||
func getBlurHash() -> String {
|
||||
let rawImgURL = getImage(baseURL: "", maxWidth: 1).absoluteString
|
||||
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1]
|
||||
var itemType: ItemType {
|
||||
guard let originalType = self.type, let knownType = ItemType(rawValue: originalType) else { return .unknown }
|
||||
return knownType
|
||||
}
|
||||
|
||||
return imageBlurHashes?.primary?[imgTag] ?? "001fC^"
|
||||
// MARK: PortraitHeaderViewURL
|
||||
|
||||
func portraitHeaderViewURL(maxWidth: Int) -> URL {
|
||||
switch self.itemType {
|
||||
case .movie, .season, .series:
|
||||
return getPrimaryImage(maxWidth: maxWidth)
|
||||
case .episode:
|
||||
return getSeriesPrimaryImage(maxWidth: maxWidth)
|
||||
case .unknown:
|
||||
return getPrimaryImage(maxWidth: maxWidth)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import JellyfinAPI
|
||||
import UIKit
|
||||
|
||||
extension BaseItemPerson {
|
||||
func getImage(baseURL: String, maxWidth: Int) -> URL {
|
||||
let imageType = "Primary"
|
||||
let imageTag = primaryImageTag ?? ""
|
||||
|
||||
let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
|
||||
|
||||
let urlString = "\(baseURL)/Items/\(id ?? "")/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=85&tag=\(imageTag)"
|
||||
return URL(string: urlString)!
|
||||
}
|
||||
|
||||
func getBlurHash() -> String {
|
||||
let rawImgURL = getImage(baseURL: "", maxWidth: 1).absoluteString
|
||||
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1]
|
||||
|
||||
return imageBlurHashes?.primary?[imgTag] ?? "001fC^"
|
||||
}
|
||||
}
|
||||
|
||||
extension BaseItemPerson: PortraitImageStackable {
|
||||
public func imageURLContsructor(maxWidth: Int) -> URL {
|
||||
return self.getImage(baseURL: ServerEnvironment.current.server.baseURI!, maxWidth: maxWidth)
|
||||
}
|
||||
|
||||
public var title: String {
|
||||
return self.name ?? ""
|
||||
}
|
||||
|
||||
public var description: String? {
|
||||
return self.role
|
||||
}
|
||||
|
||||
public var blurHash: String {
|
||||
return self.getBlurHash()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import JellyfinAPI
|
||||
|
||||
extension NameGuidPair: PillStackable {
|
||||
var title: String {
|
||||
return self.name ?? ""
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import JellyfinAPI
|
||||
|
||||
enum DetailItemType: String {
|
||||
case movie = "Movie"
|
||||
case season = "Season"
|
||||
case series = "Series"
|
||||
case episode = "Episode"
|
||||
}
|
||||
|
||||
struct DetailItem {
|
||||
|
||||
let baseItem: BaseItemDto
|
||||
let type: DetailItemType
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue