Cleanup and temp views for iOS
This commit is contained in:
parent
b5719e505f
commit
ed57ea5577
|
@ -91,22 +91,18 @@ struct LandscapeItemElement: View {
|
||||||
)
|
)
|
||||||
.shadow(radius: focused ? 10.0 : 0, y: focused ? 10.0 : 0)
|
.shadow(radius: focused ? 10.0 : 0, y: focused ? 10.0 : 0)
|
||||||
.shadow(radius: focused ? 10.0 : 0, y: focused ? 10.0 : 0)
|
.shadow(radius: focused ? 10.0 : 0, y: focused ? 10.0 : 0)
|
||||||
if focused {
|
if inSeasonView ?? false {
|
||||||
if inSeasonView ?? false {
|
Text("\(item.getEpisodeLocator() ?? "") • \(item.name ?? "")")
|
||||||
Text("\(item.getEpisodeLocator() ?? "") • \(item.name ?? "")")
|
.font(.callout)
|
||||||
.font(.callout)
|
.fontWeight(.semibold)
|
||||||
.fontWeight(.semibold)
|
.lineLimit(1)
|
||||||
.lineLimit(1)
|
.frame(width: 445)
|
||||||
.frame(width: 445)
|
|
||||||
} else {
|
|
||||||
Text(item.type == "Episode" ? "\(item.seriesName ?? "") • \(item.getEpisodeLocator() ?? "")" : item.name ?? "")
|
|
||||||
.font(.callout)
|
|
||||||
.fontWeight(.semibold)
|
|
||||||
.lineLimit(1)
|
|
||||||
.frame(width: 445)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Spacer().frame(height: 25)
|
Text(item.type == "Episode" ? "\(item.seriesName ?? "") • \(item.getEpisodeLocator() ?? "")" : item.name ?? "")
|
||||||
|
.font(.callout)
|
||||||
|
.fontWeight(.semibold)
|
||||||
|
.lineLimit(1)
|
||||||
|
.frame(width: 445)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: envFocused) { envFocus in
|
.onChange(of: envFocused) { envFocus in
|
||||||
|
|
|
@ -1,96 +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 2021 Aiden Vigue & Jellyfin Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import JellyfinAPI
|
|
||||||
|
|
||||||
struct LiveTVChannelItemElement: View {
|
|
||||||
@Environment(\.isFocused) var envFocused: Bool
|
|
||||||
@State var focused: Bool = false
|
|
||||||
|
|
||||||
var channel: BaseItemDto
|
|
||||||
var program: BaseItemDto?
|
|
||||||
|
|
||||||
var dateFormatter: DateFormatter {
|
|
||||||
let df = DateFormatter()
|
|
||||||
df.dateFormat = "h:mm"
|
|
||||||
return df
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
VStack {
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
Text(channel.number ?? "")
|
|
||||||
.font(.footnote)
|
|
||||||
.frame(alignment: .trailing)
|
|
||||||
}.frame(alignment: .top)
|
|
||||||
ImageView(src: channel.getPrimaryImage(maxWidth: 125))
|
|
||||||
.frame(width: 125, alignment: .center)
|
|
||||||
.offset(x: 0, y: -32)
|
|
||||||
Text(channel.name ?? "?")
|
|
||||||
.font(.footnote)
|
|
||||||
.lineLimit(1)
|
|
||||||
.frame(alignment: .center)
|
|
||||||
if let currentProgram = program {
|
|
||||||
Text(currentProgram.name ?? "")
|
|
||||||
.font(.body)
|
|
||||||
.lineLimit(1)
|
|
||||||
.foregroundColor(.green)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let currentProgram = program,
|
|
||||||
let startDate = currentProgram.startDate,
|
|
||||||
let endDate = currentProgram.endDate {
|
|
||||||
let start = startDate.timeIntervalSinceReferenceDate
|
|
||||||
let end = endDate.timeIntervalSinceReferenceDate
|
|
||||||
let now = Date().timeIntervalSinceReferenceDate
|
|
||||||
let length = end - start
|
|
||||||
let progress = now - start
|
|
||||||
let progPercent = progress / length
|
|
||||||
VStack {
|
|
||||||
HStack {
|
|
||||||
Text(dateFormatter.string(from: startDate))
|
|
||||||
.font(.footnote)
|
|
||||||
.lineLimit(1)
|
|
||||||
.frame(alignment: .leading)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Text(dateFormatter.string(from: endDate))
|
|
||||||
.font(.footnote)
|
|
||||||
.lineLimit(1)
|
|
||||||
.frame(alignment: .trailing)
|
|
||||||
}
|
|
||||||
GeometryReader { gp in
|
|
||||||
ZStack(alignment: .leading) {
|
|
||||||
RoundedRectangle(cornerRadius: 6)
|
|
||||||
.fill(Color.gray)
|
|
||||||
.opacity(0.4)
|
|
||||||
.frame(minWidth: 100, maxWidth: .infinity, minHeight: 12, maxHeight: 12)
|
|
||||||
RoundedRectangle(cornerRadius: 6)
|
|
||||||
.fill(Color(red: 172/255, green: 92/255, blue: 195/255))
|
|
||||||
.frame(width: CGFloat(progPercent * gp.size.width), height: 12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
.background(Color.clear)
|
|
||||||
.border(focused ? Color.blue : Color.clear, width: 4)
|
|
||||||
.onChange(of: envFocused) { envFocus in
|
|
||||||
withAnimation(.linear(duration: 0.15)) {
|
|
||||||
self.focused = envFocus
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.scaleEffect(focused ? 1.1 : 1)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import JellyfinAPI
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import SwiftUICollection
|
import SwiftUICollection
|
||||||
|
|
||||||
|
@ -51,7 +52,13 @@ struct LiveTVChannelsView: View {
|
||||||
Button {
|
Button {
|
||||||
self.router.route(to: \.videoPlayer, channel)
|
self.router.route(to: \.videoPlayer, channel)
|
||||||
} label: {
|
} label: {
|
||||||
LiveTVChannelItemElement(channel: channel, program: item.program)
|
LiveTVChannelItemElement(
|
||||||
|
channel: channel,
|
||||||
|
program: item.program,
|
||||||
|
startString: item.program?.getLiveStartTimeString(formatter: viewModel.timeFormatter) ?? " ",
|
||||||
|
endString: item.program?.getLiveEndTimeString(formatter: viewModel.timeFormatter) ?? " ",
|
||||||
|
progressPercent: item.program?.getLiveProgressPercentage() ?? 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.buttonStyle(PlainNavigationLinkButtonStyle())
|
.buttonStyle(PlainNavigationLinkButtonStyle())
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,6 +233,9 @@
|
||||||
C40CD928271F8DAB000FB198 /* MovieLibrariesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */; };
|
C40CD928271F8DAB000FB198 /* MovieLibrariesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */; };
|
||||||
C40CD929271F8DAB000FB198 /* MovieLibrariesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */; };
|
C40CD929271F8DAB000FB198 /* MovieLibrariesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */; };
|
||||||
C45B29BB26FAC5B600CEF5E0 /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */; };
|
C45B29BB26FAC5B600CEF5E0 /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */; };
|
||||||
|
C4AE2C3027498D2300AE13CF /* LiveTVHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */; };
|
||||||
|
C4AE2C3227498D6A00AE13CF /* LiveTVProgramsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */; };
|
||||||
|
C4AE2C3327498DBE00AE13CF /* LiveTVChannelItemElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */; };
|
||||||
C4BE0763271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0762271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift */; };
|
C4BE0763271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0762271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift */; };
|
||||||
C4BE0764271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0762271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift */; };
|
C4BE0764271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0762271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift */; };
|
||||||
C4BE0766271FC109003F4AD1 /* TVLibrariesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0765271FC109003F4AD1 /* TVLibrariesViewModel.swift */; };
|
C4BE0766271FC109003F4AD1 /* TVLibrariesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0765271FC109003F4AD1 /* TVLibrariesViewModel.swift */; };
|
||||||
|
@ -572,6 +575,8 @@
|
||||||
C40CD921271F8CD8000FB198 /* MoviesLibrariesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoviesLibrariesCoordinator.swift; sourceTree = "<group>"; };
|
C40CD921271F8CD8000FB198 /* MoviesLibrariesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoviesLibrariesCoordinator.swift; sourceTree = "<group>"; };
|
||||||
C40CD924271F8D1E000FB198 /* MovieLibrariesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieLibrariesViewModel.swift; sourceTree = "<group>"; };
|
C40CD924271F8D1E000FB198 /* MovieLibrariesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieLibrariesViewModel.swift; sourceTree = "<group>"; };
|
||||||
C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieLibrariesView.swift; sourceTree = "<group>"; };
|
C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieLibrariesView.swift; sourceTree = "<group>"; };
|
||||||
|
C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVHomeView.swift; sourceTree = "<group>"; };
|
||||||
|
C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVProgramsView.swift; sourceTree = "<group>"; };
|
||||||
C4BE0762271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesCoordinator.swift; sourceTree = "<group>"; };
|
C4BE0762271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesCoordinator.swift; sourceTree = "<group>"; };
|
||||||
C4BE0765271FC109003F4AD1 /* TVLibrariesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesViewModel.swift; sourceTree = "<group>"; };
|
C4BE0765271FC109003F4AD1 /* TVLibrariesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesViewModel.swift; sourceTree = "<group>"; };
|
||||||
C4BE0768271FC164003F4AD1 /* TVLibrariesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesView.swift; sourceTree = "<group>"; };
|
C4BE0768271FC164003F4AD1 /* TVLibrariesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -869,7 +874,6 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
531690F6267ACC00005D8AB9 /* LandscapeItemElement.swift */,
|
531690F6267ACC00005D8AB9 /* LandscapeItemElement.swift */,
|
||||||
C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */,
|
|
||||||
E100720626BDABC100CE3E31 /* MediaPlayButtonRowView.swift */,
|
E100720626BDABC100CE3E31 /* MediaPlayButtonRowView.swift */,
|
||||||
53272531268BF09D0035FBF1 /* MediaViewActionButton.swift */,
|
53272531268BF09D0035FBF1 /* MediaViewActionButton.swift */,
|
||||||
53116A18268B947A003024C9 /* PlainLinkButton.swift */,
|
53116A18268B947A003024C9 /* PlainLinkButton.swift */,
|
||||||
|
@ -1256,6 +1260,8 @@
|
||||||
625CB56E2678C23300530A6E /* HomeView.swift */,
|
625CB56E2678C23300530A6E /* HomeView.swift */,
|
||||||
E14F7D0A26DB3714007C3AE6 /* ItemView */,
|
E14F7D0A26DB3714007C3AE6 /* ItemView */,
|
||||||
53FF7F29263CF3F500585C35 /* LatestMediaView.swift */,
|
53FF7F29263CF3F500585C35 /* LatestMediaView.swift */,
|
||||||
|
C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */,
|
||||||
|
C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */,
|
||||||
53E4E646263F6CF100F67C6B /* LibraryFilterView.swift */,
|
53E4E646263F6CF100F67C6B /* LibraryFilterView.swift */,
|
||||||
6213388F265F83A900A81A2A /* LibraryListView.swift */,
|
6213388F265F83A900A81A2A /* LibraryListView.swift */,
|
||||||
53EE24E5265060780068F029 /* LibrarySearchView.swift */,
|
53EE24E5265060780068F029 /* LibrarySearchView.swift */,
|
||||||
|
@ -1351,6 +1357,7 @@
|
||||||
E1AD105326D96F5A003E4A08 /* Views */ = {
|
E1AD105326D96F5A003E4A08 /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */,
|
||||||
531690F9267AD6EC005D8AB9 /* PlainNavigationLinkButton.swift */,
|
531690F9267AD6EC005D8AB9 /* PlainNavigationLinkButton.swift */,
|
||||||
531AC8BE26750DE20091C7EB /* ImageView.swift */,
|
531AC8BE26750DE20091C7EB /* ImageView.swift */,
|
||||||
621338B22660A07800A81A2A /* LazyView.swift */,
|
621338B22660A07800A81A2A /* LazyView.swift */,
|
||||||
|
@ -1962,6 +1969,7 @@
|
||||||
53F8377D265FF67C00F456B3 /* VideoPlayerSettingsView.swift in Sources */,
|
53F8377D265FF67C00F456B3 /* VideoPlayerSettingsView.swift in Sources */,
|
||||||
E19169CE272514760085832A /* HTTPScheme.swift in Sources */,
|
E19169CE272514760085832A /* HTTPScheme.swift in Sources */,
|
||||||
53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */,
|
53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */,
|
||||||
|
C4AE2C3027498D2300AE13CF /* LiveTVHomeView.swift in Sources */,
|
||||||
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */,
|
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */,
|
||||||
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */,
|
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */,
|
||||||
0959A5FD2686D29800C7C9A9 /* VideoUpNextView.swift in Sources */,
|
0959A5FD2686D29800C7C9A9 /* VideoUpNextView.swift in Sources */,
|
||||||
|
@ -1972,6 +1980,7 @@
|
||||||
53892770263C25230035E14B /* NextUpView.swift in Sources */,
|
53892770263C25230035E14B /* NextUpView.swift in Sources */,
|
||||||
6264E88C273850380081A12A /* Strings.swift in Sources */,
|
6264E88C273850380081A12A /* Strings.swift in Sources */,
|
||||||
C4BE0766271FC109003F4AD1 /* TVLibrariesViewModel.swift in Sources */,
|
C4BE0766271FC109003F4AD1 /* TVLibrariesViewModel.swift in Sources */,
|
||||||
|
C4AE2C3227498D6A00AE13CF /* LiveTVProgramsView.swift in Sources */,
|
||||||
62ECA01826FA685A00E8EBB7 /* DeepLink.swift in Sources */,
|
62ECA01826FA685A00E8EBB7 /* DeepLink.swift in Sources */,
|
||||||
535BAEA5264A151C005FA86D /* VideoPlayer.swift in Sources */,
|
535BAEA5264A151C005FA86D /* VideoPlayer.swift in Sources */,
|
||||||
62E632E6267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */,
|
62E632E6267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */,
|
||||||
|
@ -1995,6 +2004,7 @@
|
||||||
6220D0CC26D640C400B8E046 /* AppURLHandler.swift in Sources */,
|
6220D0CC26D640C400B8E046 /* AppURLHandler.swift in Sources */,
|
||||||
62E632F3267D54030063E547 /* ItemViewModel.swift in Sources */,
|
62E632F3267D54030063E547 /* ItemViewModel.swift in Sources */,
|
||||||
53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */,
|
53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */,
|
||||||
|
C4AE2C3327498DBE00AE13CF /* LiveTVChannelItemElement.swift in Sources */,
|
||||||
E1E48CC9271E6D410021A2F9 /* RefreshHelper.swift in Sources */,
|
E1E48CC9271E6D410021A2F9 /* RefreshHelper.swift in Sources */,
|
||||||
E1D4BF842719D25A00A11E64 /* TrackLanguage.swift in Sources */,
|
E1D4BF842719D25A00A11E64 /* TrackLanguage.swift in Sources */,
|
||||||
C4BE07792726EE82003F4AD1 /* LiveTVTabCoordinator.swift in Sources */,
|
C4BE07792726EE82003F4AD1 /* LiveTVTabCoordinator.swift in Sources */,
|
||||||
|
@ -2241,7 +2251,7 @@
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 66;
|
CURRENT_PROJECT_VERSION = 66;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer tvOS/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer tvOS/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = JM7WWM3V8C;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
INFOPLIST_FILE = "JellyfinPlayer tvOS/Info.plist";
|
INFOPLIST_FILE = "JellyfinPlayer tvOS/Info.plist";
|
||||||
|
@ -2271,7 +2281,7 @@
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 66;
|
CURRENT_PROJECT_VERSION = 66;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer tvOS/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer tvOS/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = JM7WWM3V8C;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
INFOPLIST_FILE = "JellyfinPlayer tvOS/Info.plist";
|
INFOPLIST_FILE = "JellyfinPlayer tvOS/Info.plist";
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1300"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "5358705F2669D21600D05A09"
|
||||||
|
BuildableName = "JellyfinPlayer tvOS.app"
|
||||||
|
BlueprintName = "JellyfinPlayer tvOS"
|
||||||
|
ReferencedContainer = "container:JellyfinPlayer.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "5358705F2669D21600D05A09"
|
||||||
|
BuildableName = "JellyfinPlayer tvOS.app"
|
||||||
|
BlueprintName = "JellyfinPlayer tvOS"
|
||||||
|
ReferencedContainer = "container:JellyfinPlayer.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "5358705F2669D21600D05A09"
|
||||||
|
BuildableName = "JellyfinPlayer tvOS.app"
|
||||||
|
BlueprintName = "JellyfinPlayer tvOS"
|
||||||
|
ReferencedContainer = "container:JellyfinPlayer.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* JellyfinPlayer/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
|
||||||
|
|
||||||
|
struct LiveTVHomeView: View {
|
||||||
|
var body: some View {
|
||||||
|
Text("Coming Soon")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* JellyfinPlayer/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
|
||||||
|
|
||||||
|
struct LiveTVProgramsView: View {
|
||||||
|
var body: some View {
|
||||||
|
Text("Coming Soon")
|
||||||
|
}
|
||||||
|
}
|
|
@ -170,7 +170,34 @@ public extension BaseItemDto {
|
||||||
return "\(String(progminutes))m"
|
return "\(String(progminutes))m"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getLiveStartTimeString(formatter: DateFormatter) -> String {
|
||||||
|
if let startDate = self.startDate {
|
||||||
|
return formatter.string(from: startDate)
|
||||||
|
}
|
||||||
|
return " "
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLiveEndTimeString(formatter: DateFormatter) -> String {
|
||||||
|
if let endDate = self.endDate {
|
||||||
|
return formatter.string(from: endDate)
|
||||||
|
}
|
||||||
|
return " "
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLiveProgressPercentage() -> Double {
|
||||||
|
if let startDate = self.startDate,
|
||||||
|
let endDate = self.endDate {
|
||||||
|
let start = startDate.timeIntervalSinceReferenceDate
|
||||||
|
let end = endDate.timeIntervalSinceReferenceDate
|
||||||
|
let now = Date().timeIntervalSinceReferenceDate
|
||||||
|
let length = end - start
|
||||||
|
let progress = now - start
|
||||||
|
return progress / length
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: ItemType
|
// MARK: ItemType
|
||||||
|
|
||||||
enum ItemType: String {
|
enum ItemType: String {
|
||||||
|
|
|
@ -37,9 +37,16 @@ final class LiveTVChannelsViewModel: ViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Published var rows = [LiveTVChannelRow]()
|
@Published var rows = [LiveTVChannelRow]()
|
||||||
|
|
||||||
private var programs = [BaseItemDto]()
|
private var programs = [BaseItemDto]()
|
||||||
private var channelProgramsList = [BaseItemDto: [BaseItemDto]]()
|
private var channelProgramsList = [BaseItemDto: [BaseItemDto]]()
|
||||||
|
|
||||||
|
var timeFormatter: DateFormatter {
|
||||||
|
let df = DateFormatter()
|
||||||
|
df.dateFormat = "h:mm"
|
||||||
|
return df
|
||||||
|
}
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
@ -91,9 +98,6 @@ final class LiveTVChannelsViewModel: ViewModel {
|
||||||
let minEndDate = Date.now.addComponentsToDate(hours: -1)
|
let minEndDate = Date.now.addComponentsToDate(hours: -1)
|
||||||
let maxStartDate = minEndDate.addComponentsToDate(hours: 6)
|
let maxStartDate = minEndDate.addComponentsToDate(hours: 6)
|
||||||
|
|
||||||
NSLog("*** maxStartDate: \(maxStartDate)")
|
|
||||||
NSLog("*** minEndDate: \(minEndDate)")
|
|
||||||
|
|
||||||
let getProgramsDto = GetProgramsDto(
|
let getProgramsDto = GetProgramsDto(
|
||||||
channelIds: channelIds,
|
channelIds: channelIds,
|
||||||
userId: SessionManager.main.currentLogin.user.id,
|
userId: SessionManager.main.currentLogin.user.id,
|
||||||
|
@ -123,11 +127,7 @@ final class LiveTVChannelsViewModel: ViewModel {
|
||||||
private func processChannelPrograms() -> [LiveTVChannelProgram] {
|
private func processChannelPrograms() -> [LiveTVChannelProgram] {
|
||||||
var channelPrograms = [LiveTVChannelProgram]()
|
var channelPrograms = [LiveTVChannelProgram]()
|
||||||
let now = Date()
|
let now = Date()
|
||||||
let df = DateFormatter()
|
|
||||||
df.dateFormat = "MM/dd h:mm ZZZ"
|
|
||||||
NSLog("begin processing programs")
|
|
||||||
for channel in self.channels {
|
for channel in self.channels {
|
||||||
NSLog("\n\(channel.name)")
|
|
||||||
let prgs = self.programs.filter { item in
|
let prgs = self.programs.filter { item in
|
||||||
item.channelId == channel.id
|
item.channelId == channel.id
|
||||||
}
|
}
|
||||||
|
@ -135,15 +135,6 @@ final class LiveTVChannelsViewModel: ViewModel {
|
||||||
|
|
||||||
var currentPrg: BaseItemDto?
|
var currentPrg: BaseItemDto?
|
||||||
for prg in prgs {
|
for prg in prgs {
|
||||||
var startString = ""
|
|
||||||
var endString = ""
|
|
||||||
if let start = prg.startDate {
|
|
||||||
startString = df.string(from: start)
|
|
||||||
}
|
|
||||||
if let end = prg.endDate {
|
|
||||||
endString = df.string(from: end)
|
|
||||||
}
|
|
||||||
NSLog("\(prg.name) - \(startString) to \(endString)")
|
|
||||||
if let startDate = prg.startDate,
|
if let startDate = prg.startDate,
|
||||||
let endDate = prg.endDate,
|
let endDate = prg.endDate,
|
||||||
now.timeIntervalSinceReferenceDate > startDate.timeIntervalSinceReferenceDate &&
|
now.timeIntervalSinceReferenceDate > startDate.timeIntervalSinceReferenceDate &&
|
||||||
|
@ -154,7 +145,6 @@ final class LiveTVChannelsViewModel: ViewModel {
|
||||||
|
|
||||||
channelPrograms.append(LiveTVChannelProgram(channel: channel, program: currentPrg))
|
channelPrograms.append(LiveTVChannelProgram(channel: channel, program: currentPrg))
|
||||||
}
|
}
|
||||||
NSLog("finished processing programs")
|
|
||||||
return channelPrograms
|
return channelPrograms
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
//
|
||||||
|
/*
|
||||||
|
* 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 LiveTVChannelItemElement: View {
|
||||||
|
@Environment(\.isFocused) var envFocused: Bool
|
||||||
|
@State var focused: Bool = false
|
||||||
|
|
||||||
|
var channel: BaseItemDto
|
||||||
|
var program: BaseItemDto?
|
||||||
|
var startString = " "
|
||||||
|
var endString = " "
|
||||||
|
var progressPercent = Double(0)
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Text(channel.number ?? "")
|
||||||
|
.font(.footnote)
|
||||||
|
.frame(alignment: .trailing)
|
||||||
|
}.frame(alignment: .top)
|
||||||
|
ImageView(src: channel.getPrimaryImage(maxWidth: 125))
|
||||||
|
.frame(width: 125, alignment: .center)
|
||||||
|
.offset(x: 0, y: -32)
|
||||||
|
Text(channel.name ?? "?")
|
||||||
|
.font(.footnote)
|
||||||
|
.lineLimit(1)
|
||||||
|
.frame(alignment: .center)
|
||||||
|
Text(program?.name ?? "N/A")
|
||||||
|
.font(.body)
|
||||||
|
.lineLimit(1)
|
||||||
|
.foregroundColor(.green)
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Text(startString)
|
||||||
|
.font(.footnote)
|
||||||
|
.lineLimit(1)
|
||||||
|
.frame(alignment: .leading)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Text(endString)
|
||||||
|
.font(.footnote)
|
||||||
|
.lineLimit(1)
|
||||||
|
.frame(alignment: .trailing)
|
||||||
|
}
|
||||||
|
GeometryReader { gp in
|
||||||
|
ZStack(alignment: .leading) {
|
||||||
|
RoundedRectangle(cornerRadius: 6)
|
||||||
|
.fill(Color.gray)
|
||||||
|
.opacity(0.4)
|
||||||
|
.frame(minWidth: 100, maxWidth: .infinity, minHeight: 12, maxHeight: 12)
|
||||||
|
RoundedRectangle(cornerRadius: 6)
|
||||||
|
.fill(Color(red: 172/255, green: 92/255, blue: 195/255))
|
||||||
|
.frame(width: CGFloat(progressPercent * gp.size.width), height: 12)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.background(Color.clear)
|
||||||
|
.border(focused ? Color.blue : Color.clear, width: 4)
|
||||||
|
.onChange(of: envFocused) { envFocus in
|
||||||
|
withAnimation(.linear(duration: 0.15)) {
|
||||||
|
self.focused = envFocus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scaleEffect(focused ? 1.1 : 1)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue