Merge pull request #93 from jellyfin/create-pull-request/patch

[ci] SwiftLint
This commit is contained in:
aiden 3 2021-07-06 12:47:09 -04:00 committed by GitHub
commit a2d57dd326
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 197 additions and 203 deletions

View File

@ -91,7 +91,7 @@ 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)
if focused {
if(inSeasonView ?? false) {
if inSeasonView ?? false {
Text("\(item.getEpisodeLocator())\(item.name ?? "")")
.font(.callout)
.fontWeight(.semibold)

View File

@ -15,18 +15,18 @@ struct MediaViewActionButton: View {
var icon: String
var scrollView: Binding<UIScrollView?>?
var iconColor: Color?
var body: some View {
Image(systemName: icon)
.foregroundColor(focused ? .black : iconColor ?? .white)
.onChange(of: envFocused) { envFocus in
if(envFocus == true) {
if envFocus == true {
scrollView?.wrappedValue?.scrollToTop()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
scrollView?.wrappedValue?.scrollToTop()
}
}
withAnimation(.linear(duration: 0.15)) {
self.focused = envFocus
}

View File

@ -36,8 +36,7 @@ struct PortraitItemElement: View {
}
}
.padding(2)
.opacity(1)
, alignment: .bottomLeading)
.opacity(1), alignment: .bottomLeading)
.overlay(
ZStack {
if item.userData?.played ?? false {
@ -46,7 +45,7 @@ struct PortraitItemElement: View {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(Color(.systemBlue))
} else {
if(item.userData?.unplayedItemCount != nil) {
if item.userData?.unplayedItemCount != nil {
Image(systemName: "circle.fill")
.foregroundColor(Color(.systemBlue))
Text(String(item.userData!.unplayedItemCount ?? 0))

View File

@ -13,30 +13,30 @@ import JellyfinAPI
struct EpisodeItemView: View {
@ObservedObject var viewModel: EpisodeItemViewModel
@State var actors: [BaseItemPerson] = [];
@State var studio: String? = nil;
@State var director: String? = nil;
@State var actors: [BaseItemPerson] = []
@State var studio: String?
@State var director: String?
func onAppear() {
actors = []
director = nil
studio = nil
var actor_index = 0;
var actor_index = 0
viewModel.item.people?.forEach { person in
if(person.type == "Actor") {
if(actor_index < 4) {
if person.type == "Actor" {
if actor_index < 4 {
actors.append(person)
}
actor_index = actor_index + 1;
actor_index = actor_index + 1
}
if(person.type == "Director") {
if person.type == "Director" {
director = person.name ?? ""
}
}
studio = viewModel.item.studios?.first?.name ?? nil
}
var body: some View {
ZStack {
ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), bh: viewModel.item.getBackdropImageBlurHash())
@ -71,10 +71,10 @@ struct EpisodeItemView: View {
}
Spacer()
}.padding(.top, -15)
HStack(alignment: .top) {
VStack(alignment: .trailing) {
if(studio != nil) {
if studio != nil {
Text("STUDIO")
.font(.body)
.fontWeight(.semibold)
@ -85,8 +85,8 @@ struct EpisodeItemView: View {
.foregroundColor(.secondary)
.padding(.bottom, 40)
}
if(director != nil) {
if director != nil {
Text("DIRECTOR")
.font(.body)
.fontWeight(.semibold)
@ -97,8 +97,8 @@ struct EpisodeItemView: View {
.foregroundColor(.secondary)
.padding(.bottom, 40)
}
if(!actors.isEmpty) {
if !actors.isEmpty {
Text("CAST")
.font(.body)
.fontWeight(.semibold)
@ -117,7 +117,7 @@ struct EpisodeItemView: View {
.font(.body)
.fontWeight(.medium)
.foregroundColor(.primary)
HStack {
VStack {
Button {
@ -150,7 +150,7 @@ struct EpisodeItemView: View {
}
}.padding(.top, 50)
if(!viewModel.similarItems.isEmpty) {
if !viewModel.similarItems.isEmpty {
Text("More Like This")
.font(.headline)
.fontWeight(.semibold)

View File

@ -28,11 +28,11 @@ struct LibraryView: View {
ScrollView(.vertical) {
LazyVGrid(columns: tracks) {
ForEach(viewModel.items, id: \.id) { item in
if(item.type != "Folder") {
if item.type != "Folder" {
NavigationLink(destination: LazyView { ItemView(item: item) }) {
PortraitItemElement(item: item)
}.buttonStyle(PlainNavigationLinkButtonStyle())
.onAppear() {
.onAppear {
if item == viewModel.items.last && viewModel.hasNextPage {
print("Last item visible, load more items.")
viewModel.requestNextPageAsync()

View File

@ -14,36 +14,36 @@ import SwiftUIFocusGuide
struct MovieItemView: View {
@ObservedObject var viewModel: MovieItemViewModel
@State var actors: [BaseItemPerson] = [];
@State var studio: String? = nil;
@State var director: String? = nil;
@State var wrappedScrollView: UIScrollView?;
@State var actors: [BaseItemPerson] = []
@State var studio: String?
@State var director: String?
@State var wrappedScrollView: UIScrollView?
@StateObject var focusBag = SwiftUIFocusBag()
@Namespace private var namespace
func onAppear() {
actors = []
director = nil
studio = nil
var actor_index = 0;
var actor_index = 0
viewModel.item.people?.forEach { person in
if(person.type == "Actor") {
if(actor_index < 4) {
if person.type == "Actor" {
if actor_index < 4 {
actors.append(person)
}
actor_index = actor_index + 1;
actor_index = actor_index + 1
}
if(person.type == "Director") {
if person.type == "Director" {
director = person.name ?? ""
}
}
studio = viewModel.item.studios?.first?.name ?? nil
}
var body: some View {
ZStack {
ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), bh: viewModel.item.getBackdropImageBlurHash())
@ -75,10 +75,10 @@ struct MovieItemView: View {
.stroke(Color.secondary, lineWidth: 1))
}
}
HStack {
VStack(alignment: .trailing) {
if(studio != nil) {
if studio != nil {
Text("STUDIO")
.font(.body)
.fontWeight(.semibold)
@ -89,8 +89,8 @@ struct MovieItemView: View {
.foregroundColor(.secondary)
.padding(.bottom, 40)
}
if(director != nil) {
if director != nil {
Text("DIRECTOR")
.font(.body)
.fontWeight(.semibold)
@ -101,8 +101,8 @@ struct MovieItemView: View {
.foregroundColor(.secondary)
.padding(.bottom, 40)
}
if(!actors.isEmpty) {
if !actors.isEmpty {
Text("CAST")
.font(.body)
.fontWeight(.semibold)
@ -117,7 +117,7 @@ struct MovieItemView: View {
Spacer()
}
VStack(alignment: .leading) {
if(!(viewModel.item.taglines ?? []).isEmpty) {
if !(viewModel.item.taglines ?? []).isEmpty {
Text(viewModel.item.taglines?.first ?? "")
.font(.body)
.italic()
@ -128,7 +128,7 @@ struct MovieItemView: View {
.font(.body)
.fontWeight(.medium)
.foregroundColor(.primary)
HStack {
VStack {
Button {
@ -162,7 +162,7 @@ struct MovieItemView: View {
}
}.padding(.top, 50)
if(!viewModel.similarItems.isEmpty) {
if !viewModel.similarItems.isEmpty {
Text("More Like This")
.font(.headline)
.fontWeight(.semibold)

View File

@ -13,13 +13,13 @@ import SwiftUIFocusGuide
struct SeasonItemView: View {
@ObservedObject var viewModel: SeasonItemViewModel
@State var wrappedScrollView: UIScrollView?;
@State var wrappedScrollView: UIScrollView?
@StateObject var focusBag = SwiftUIFocusBag()
@Environment(\.resetFocus) var resetFocus
@Namespace private var namespace
var body: some View {
ZStack {
ImageView(src: viewModel.item.getSeriesBackdropImage(maxWidth: 1920), bh: viewModel.item.getSeriesBackdropImageBlurHash())
@ -31,7 +31,7 @@ struct SeasonItemView: View {
.fontWeight(.bold)
.foregroundColor(.primary)
HStack {
if(viewModel.item.productionYear != nil) {
if viewModel.item.productionYear != nil {
Text(String(viewModel.item.productionYear!)).font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.secondary)
@ -58,9 +58,9 @@ struct SeasonItemView: View {
}
}
}
VStack(alignment: .leading) {
if(!(viewModel.item.taglines ?? []).isEmpty) {
if !(viewModel.item.taglines ?? []).isEmpty {
Text(viewModel.item.taglines?.first ?? "")
.font(.body)
.italic()
@ -71,7 +71,7 @@ struct SeasonItemView: View {
.font(.body)
.fontWeight(.medium)
.foregroundColor(.primary)
HStack {
VStack {
Button {
@ -96,7 +96,7 @@ struct SeasonItemView: View {
Spacer()
}.padding(.top, 50)
if(!viewModel.episodes.isEmpty) {
if !viewModel.episodes.isEmpty {
Text("Episodes")
.font(.headline)
.fontWeight(.semibold)

View File

@ -14,14 +14,14 @@ import SwiftUIFocusGuide
struct SeriesItemView: View {
@ObservedObject var viewModel: SeriesItemViewModel
@State var actors: [BaseItemPerson] = [];
@State var studio: String? = nil;
@State var director: String? = nil;
@State var wrappedScrollView: UIScrollView?;
@State var actors: [BaseItemPerson] = []
@State var studio: String?
@State var director: String?
@State var wrappedScrollView: UIScrollView?
@StateObject var focusBag = SwiftUIFocusBag()
@Environment(\.resetFocus) var resetFocus
@Namespace private var namespace
@ -29,22 +29,22 @@ struct SeriesItemView: View {
actors = []
director = nil
studio = nil
var actor_index = 0;
var actor_index = 0
viewModel.item.people?.forEach { person in
if(person.type == "Actor") {
if(actor_index < 4) {
if person.type == "Actor" {
if actor_index < 4 {
actors.append(person)
}
actor_index = actor_index + 1;
actor_index = actor_index + 1
}
if(person.type == "Director") {
if person.type == "Director" {
director = person.name ?? ""
}
}
studio = viewModel.item.studios?.first?.name ?? nil
}
var body: some View {
ZStack {
ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), bh: viewModel.item.getBackdropImageBlurHash())
@ -81,10 +81,10 @@ struct SeriesItemView: View {
}
}
}
HStack {
VStack(alignment: .trailing) {
if(studio != nil) {
if studio != nil {
Text("STUDIO")
.font(.body)
.fontWeight(.semibold)
@ -95,8 +95,8 @@ struct SeriesItemView: View {
.foregroundColor(.secondary)
.padding(.bottom, 40)
}
if(director != nil) {
if director != nil {
Text("DIRECTOR")
.font(.body)
.fontWeight(.semibold)
@ -107,8 +107,8 @@ struct SeriesItemView: View {
.foregroundColor(.secondary)
.padding(.bottom, 40)
}
if(!actors.isEmpty) {
if !actors.isEmpty {
Text("CAST")
.font(.body)
.fontWeight(.semibold)
@ -123,7 +123,7 @@ struct SeriesItemView: View {
Spacer()
}
VStack(alignment: .leading) {
if(!(viewModel.item.taglines ?? []).isEmpty) {
if !(viewModel.item.taglines ?? []).isEmpty {
Text(viewModel.item.taglines?.first ?? "")
.font(.body)
.italic()
@ -134,7 +134,7 @@ struct SeriesItemView: View {
.font(.body)
.fontWeight(.medium)
.foregroundColor(.primary)
HStack {
VStack {
Button {
@ -145,7 +145,7 @@ struct SeriesItemView: View {
Text(viewModel.isFavorited ? "Unfavorite" : "Favorite")
.font(.caption)
}
if(viewModel.nextUpItem != nil) {
if viewModel.nextUpItem != nil {
VStack {
NavigationLink(destination: VideoPlayerView(item: viewModel.nextUpItem!)) {
MediaViewActionButton(icon: "play.fill", scrollView: $wrappedScrollView)
@ -167,8 +167,8 @@ struct SeriesItemView: View {
Spacer()
}
}.padding(.top, 50)
if(viewModel.nextUpItem != nil) {
if viewModel.nextUpItem != nil {
Text("Next Up")
.font(.headline)
.fontWeight(.semibold)
@ -176,8 +176,8 @@ struct SeriesItemView: View {
LandscapeItemElement(item: viewModel.nextUpItem!)
}.buttonStyle(PlainNavigationLinkButtonStyle()).padding(.bottom, 1)
}
if(!viewModel.seasons.isEmpty) {
if !viewModel.seasons.isEmpty {
Text("Seasons")
.font(.headline)
.fontWeight(.semibold)
@ -194,8 +194,8 @@ struct SeriesItemView: View {
}.padding(EdgeInsets(top: -30, leading: -90, bottom: 0, trailing: -90))
.frame(height: 360)
}
if(!viewModel.similarItems.isEmpty) {
if !viewModel.similarItems.isEmpty {
Text("More Like This")
.font(.headline)
.fontWeight(.semibold)

View File

@ -10,7 +10,7 @@
import SwiftUI
class AudioViewController: InfoTabViewController {
override func viewDidLoad() {
super.viewDidLoad()

View File

@ -11,10 +11,9 @@ import TVUIKit
import JellyfinAPI
class InfoTabViewController: UIViewController {
var height : CGFloat = 420
var height: CGFloat = 420
}
class InfoTabBarViewController: UITabBarController, UIGestureRecognizerDelegate {
var videoPlayer: VideoPlayerViewController?
@ -39,11 +38,11 @@ class InfoTabBarViewController: UITabBarController, UIGestureRecognizerDelegate
audioViewController?.prepareAudioView(audioTracks: audioTracks, selectedTrack: selectedAudioTrack, delegate: delegate)
subtitleViewController?.prepareSubtitleView(subtitleTracks: subtitleTracks, selectedTrack: selectedSubtitleTrack, delegate: delegate)
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
if let index = tabBar.items?.firstIndex(of: item),
let tabViewController = viewControllers?[index] as? InfoTabViewController,
let width = videoPlayer?.infoPanelContainerView.frame.width {

View File

@ -50,11 +50,11 @@ struct MediaInfoView: View {
if item.type == "Episode" {
Text(item.seriesName ?? "Series")
.fontWeight(.bold)
HStack {
Text(item.name ?? "Episode")
.foregroundColor(.secondary)
Text(item.getEpisodeLocator())
if let date = item.premiereDate {
@ -67,7 +67,7 @@ struct MediaInfoView: View {
}
HStack(spacing: 10) {
if(item.type != "Episode") {
if item.type != "Episode" {
if let year = item.productionYear {
Text(String(year))
}

View File

@ -227,7 +227,7 @@ class VideoPlayerViewController: UIViewController, VideoPlayerSettingsDelegate,
if let rawStartTicks = manifest.userData?.playbackPositionTicks {
mediaPlayer.jumpForward(Int32(rawStartTicks / 10_000_000))
}
subtitleTrackArray.forEach { sub in
if sub.id != -1 && sub.delivery == .external {
mediaPlayer.addPlaybackSlave(sub.url!, type: .subtitle, enforce: false)
@ -247,13 +247,13 @@ class VideoPlayerViewController: UIViewController, VideoPlayerSettingsDelegate,
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.playCommand.isEnabled = true
commandCenter.pauseCommand.isEnabled = true
commandCenter.skipBackwardCommand.isEnabled = true
commandCenter.skipBackwardCommand.preferredIntervals = [15]
commandCenter.skipForwardCommand.isEnabled = true
commandCenter.skipForwardCommand.preferredIntervals = [30]
commandCenter.changePlaybackPositionCommand.isEnabled = true
commandCenter.enableLanguageOptionCommand.isEnabled = true
@ -275,14 +275,14 @@ class VideoPlayerViewController: UIViewController, VideoPlayerSettingsDelegate,
}
// Add handler for FF command
commandCenter.skipForwardCommand.addTarget { skipEvent in
commandCenter.skipForwardCommand.addTarget { _ in
self.mediaPlayer.jumpForward(30)
self.sendProgressReport(eventName: "timeupdate")
return .success
}
// Add handler for RW command
commandCenter.skipBackwardCommand.addTarget { skipEvent in
commandCenter.skipBackwardCommand.addTarget { _ in
self.mediaPlayer.jumpBackward(15)
self.sendProgressReport(eventName: "timeupdate")
return .success
@ -324,7 +324,7 @@ class VideoPlayerViewController: UIViewController, VideoPlayerSettingsDelegate,
var nowPlayingInfo = [String: Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = manifest.name ?? "Jellyfin Video"
if(manifest.type == "Episode") {
if manifest.type == "Episode" {
nowPlayingInfo[MPMediaItemPropertyArtist] = "\(manifest.seriesName ?? manifest.name ?? "")\(manifest.getEpisodeLocator())"
}
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 0.0
@ -421,26 +421,26 @@ class VideoPlayerViewController: UIViewController, VideoPlayerSettingsDelegate,
UIView.animate(withDuration: 0.4, delay: 0, options: .curveEaseOut) { [self] in
let size = infoPanelContainerView.frame.size
let y : CGFloat = showingInfoPanel ? 87 : -size.height
let y: CGFloat = showingInfoPanel ? 87 : -size.height
infoPanelContainerView.frame = CGRect(x: 88, y: y, width: size.width, height: size.height)
}
}
// MARK: Gestures
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
for item in presses {
if(item.type == .select) {
if item.type == .select {
selectButtonTapped()
}
}
}
func setupGestures() {
self.becomeFirstResponder()
//vlc crap
// vlc crap
videoContentView.gestureRecognizers?.forEach { gr in
videoContentView.removeGestureRecognizer(gr)
}
@ -449,17 +449,17 @@ class VideoPlayerViewController: UIViewController, VideoPlayerSettingsDelegate,
sv.removeGestureRecognizer(gr)
}
}
let playPauseGesture = UITapGestureRecognizer(target: self, action: #selector(self.selectButtonTapped))
let playPauseType = UIPress.PressType.playPause
playPauseGesture.allowedPressTypes = [NSNumber(value: playPauseType.rawValue)]
view.addGestureRecognizer(playPauseGesture)
let backTapGesture = UITapGestureRecognizer(target: self, action: #selector(self.backButtonPressed(tap:)))
let backPress = UIPress.PressType.menu
backTapGesture.allowedPressTypes = [NSNumber(value: backPress.rawValue)]
view.addGestureRecognizer(backTapGesture)
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.userPanned(panGestureRecognizer:)))
view.addGestureRecognizer(panGestureRecognizer)
}
@ -497,7 +497,7 @@ class VideoPlayerViewController: UIViewController, VideoPlayerSettingsDelegate,
let translation = panGestureRecognizer.translation(in: view)
let velocity = panGestureRecognizer.velocity(in: view)
// Swiped up - Handle dismissing info panel
if translation.y < -200 && (focusedOnTabBar && showingInfoPanel) {
toggleInfoContainer()
@ -580,7 +580,7 @@ class VideoPlayerViewController: UIViewController, VideoPlayerSettingsDelegate,
// MARK: Jellyfin Playstate updates
func sendProgressReport(eventName: String) {
updateNowPlayingCenter(time: nil, playing: mediaPlayer.state == .playing)
if (eventName == "timeupdate" && mediaPlayer.state == .playing) || eventName != "timeupdate" {
let progressInfo = PlaybackProgressInfo(canSeek: true, item: manifest, itemId: manifest.id, sessionId: playSessionId, mediaSourceId: manifest.id, audioStreamIndex: Int(selectedAudioTrack), subtitleStreamIndex: Int(selectedCaptionTrack), isPaused: (!playing), isMuted: false, positionTicks: Int64(mediaPlayer.position * Float(manifest.runTimeTicks!)), playbackStartTimeTicks: Int64(startTime), volumeLevel: 100, brightness: 100, aspectRatio: nil, playMethod: playbackItem.videoType, liveStreamId: nil, playSessionId: playSessionId, repeatMode: .repeatNone, nowPlayingQueue: [], playlistItemId: "playlistItem0")

View File

@ -11,7 +11,7 @@ import SwiftUI
import JellyfinAPI
struct PortraitItemView: View {
var item: BaseItemDto
var body: some View {
NavigationLink(destination: LazyView { ItemView(item: item) }) {
VStack(alignment: .leading) {
@ -39,8 +39,7 @@ struct PortraitItemView: View {
}
.padding(.leading, 2)
.padding(.bottom, item.userData?.playedPercentage == nil ? 2 : 9)
.opacity(1)
, alignment: .bottomLeading)
.opacity(1), alignment: .bottomLeading)
.overlay(
ZStack {
if item.userData?.played ?? false {
@ -49,7 +48,7 @@ struct PortraitItemView: View {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(Color(.systemBlue))
} else {
if(item.userData?.unplayedItemCount != nil) {
if item.userData?.unplayedItemCount != nil {
Image(systemName: "circle.fill")
.foregroundColor(Color(.systemBlue))
Text(String(item.userData!.unplayedItemCount ?? 0))
@ -64,12 +63,12 @@ struct PortraitItemView: View {
.fontWeight(.semibold)
.foregroundColor(.primary)
.lineLimit(1)
if(item.type == "Movie" || item.type == "Series") {
if item.type == "Movie" || item.type == "Series" {
Text("\(String(item.productionYear ?? 0))\(item.officialRating ?? "N/A")")
.foregroundColor(.secondary)
.font(.caption)
.fontWeight(.medium)
} else if(item.type == "Season") {
} else if item.type == "Season" {
Text("\(item.name ?? "")\(String(item.productionYear ?? 0))")
.foregroundColor(.secondary)
.font(.caption)

View File

@ -56,7 +56,7 @@ struct LibraryListView: View {
.shadow(radius: 5)
.padding(.bottom, 15)
if(!viewModel.isLoading) {
if !viewModel.isLoading {
ForEach(viewModel.libraries, id: \.id) { library in
if library.collectionType ?? "" == "movies" || library.collectionType ?? "" == "tvshows" {
NavigationLink(destination: LazyView {
@ -67,7 +67,7 @@ struct LibraryListView: View {
.opacity(0.4)
HStack {
Spacer()
VStack() {
VStack {
Text(library.name ?? "")
.foregroundColor(.white)
.font(.title2)

View File

@ -34,7 +34,7 @@ struct LibraryView: View {
Spacer().frame(height: 16)
LazyVGrid(columns: tracks) {
ForEach(viewModel.items, id: \.id) { item in
if(item.type != "Folder") {
if item.type != "Folder" {
PortraitItemView(item: item)
}
}

View File

@ -89,8 +89,7 @@ struct SeasonItemView: View {
}
.padding(.leading, 2)
.padding(.bottom, episode.userData?.playedPercentage == nil ? 2 : 9)
.opacity(1)
, alignment: .bottomLeading)
.opacity(1), alignment: .bottomLeading)
.overlay(
ZStack {
if episode.userData?.played ?? false {

View File

@ -68,21 +68,21 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
}
var hasSentRemoteSeek: Bool = false
var selectedPlaybackSpeedIndex : Int = 3
var selectedPlaybackSpeedIndex: Int = 3
var selectedAudioTrack: Int32 = -1
var selectedCaptionTrack: Int32 = -1
var playSessionId: String = ""
var lastProgressReportTime: Double = 0
var subtitleTrackArray: [Subtitle] = []
var audioTrackArray: [AudioTrack] = []
let playbackSpeeds : [Float] = [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0]
let playbackSpeeds: [Float] = [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0]
var manifest: BaseItemDto = BaseItemDto()
var playbackItem = PlaybackItem()
var remoteTimeUpdateTimer: Timer?
var upNextViewModel: UpNextViewModel = UpNextViewModel()
var lastOri: UIDeviceOrientation!
// MARK: IBActions
@IBAction func seekSliderStart(_ sender: Any) {
if playerDestination == .local {
@ -348,34 +348,34 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
}
}
var nowPlayingInfo = [String : Any]()
var nowPlayingInfo = [String: Any]()
var runTicks = 0
var playbackTicks = 0
if let ticks = manifest.runTimeTicks {
runTicks = Int(ticks / 10_000_000)
}
if let ticks = manifest.userData?.playbackPositionTicks {
playbackTicks = Int(ticks / 10_000_000)
}
nowPlayingInfo[MPMediaItemPropertyTitle] = manifest.name ?? "Jellyfin Video"
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = AVMediaType.video
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = runTicks
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = playbackTicks
if let imageData = NSData(contentsOf: manifest.getPrimaryImage(maxWidth: 200)) {
if let artworkImage = UIImage(data: imageData as Data) {
let artwork = MPMediaItemArtwork.init(boundsSize: artworkImage.size, requestHandler: { (size) -> UIImage in
let artwork = MPMediaItemArtwork.init(boundsSize: artworkImage.size, requestHandler: { (_) -> UIImage in
return artworkImage
})
nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork
}
}
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
UIApplication.shared.beginReceivingRemoteControlEvents()
@ -387,11 +387,11 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
titleLabel.text = manifest.name ?? ""
} else {
titleLabel.text = "S\(String(manifest.parentIndexNumber ?? 0)):E\(String(manifest.indexNumber ?? 0))\(manifest.name ?? "")"
setupNextUpView()
upNextViewModel.delegate = self
}
lastOri = UIDevice.current.orientation
if !UIDevice.current.orientation.isLandscape || UIDevice.current.orientation.isFlat {
@ -454,12 +454,12 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
mediaPlayer.delegate = self
mediaPlayer.drawable = videoContentView
setupMediaPlayer()
}
func setupMediaPlayer() {
// Fetch max bitrate from UserDefaults depending on current connection mode
let maxBitrate = Defaults[.inNetworkBandwidth]
print(maxBitrate)
@ -580,8 +580,8 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
self.sendPlayReport()
playbackItem = item
//self.setupNowPlayingCC()
// self.setupNowPlayingCC()
}
startLocalPlaybackEngine(true)
@ -678,21 +678,21 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
selectedAudioTrack = newTrackID
mediaPlayer.currentAudioTrackIndex = newTrackID
}
func playbackSpeedChanged(index: Int) {
selectedPlaybackSpeedIndex = index
mediaPlayer.rate = playbackSpeeds[index]
}
func smallNextUpView() {
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseIn) { [self] in
upNextViewModel.largeView = false
}
}
func setupNextUpView() {
getNextEpisode()
// Create the swiftUI view
let contentView = UIHostingController(rootView: VideoUpNextView(viewModel: upNextViewModel))
self.upNextView.addSubview(contentView.view)
@ -703,7 +703,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
contentView.view.leftAnchor.constraint(equalTo: upNextView.leftAnchor).isActive = true
contentView.view.rightAnchor.constraint(equalTo: upNextView.rightAnchor).isActive = true
}
func getNextEpisode() {
TvShowsAPI.getEpisodes(seriesId: manifest.seriesId!, userId: SessionManager.current.user.user_id!, startItemId: manifest.id, limit: 2)
.sink(receiveCompletion: { completion in
@ -717,22 +717,21 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
})
.store(in: &cancellables)
}
func setPlayerToNextUp() {
mediaPlayer.stop()
ssTargetValueOffset = 0
ssStartValue = 0
paused = true
lastTime = 0.0
startTime = 0
controlsAppearTime = 0
isSeeking = false
remotePositionTicks = 0
selectedPlaybackSpeedIndex = 3
selectedAudioTrack = -1
selectedCaptionTrack = -1
@ -740,22 +739,22 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
lastProgressReportTime = 0
subtitleTrackArray = []
audioTrackArray = []
manifest = upNextViewModel.item!
playbackItem = PlaybackItem()
upNextViewModel.item = nil
upNextView.isHidden = true
shouldShowLoadingScreen = true
videoControlsView.isHidden = true
titleLabel.text = "S\(String(manifest.parentIndexNumber ?? 0)):E\(String(manifest.indexNumber ?? 0))\(manifest.name ?? "")"
setupMediaPlayer()
getNextEpisode()
}
}
// MARK: - GCKGenericChannelDelegate
@ -951,8 +950,8 @@ extension PlayerViewController: VLCMediaPlayerDelegate {
mainActionButton.setImage(UIImage(systemName: "pause"), for: .normal)
seekSlider.setValue(mediaPlayer.position, animated: true)
delegate?.hideLoadingView(self)
if manifest.type == "Episode" && upNextViewModel.item != nil{
if manifest.type == "Episode" && upNextViewModel.item != nil {
if time > 0.96 {
upNextView.isHidden = false
self.jumpForwardButton.isHidden = true
@ -961,7 +960,7 @@ extension PlayerViewController: VLCMediaPlayerDelegate {
self.jumpForwardButton.isHidden = false
}
}
timeText.text = String(mediaPlayer.remainingTime.stringValue.dropFirst())
if CACurrentMediaTime() - controlsAppearTime > 5 {

View File

@ -37,8 +37,8 @@ struct VideoPlayerSettings: View {
weak var delegate: PlayerViewController!
@State var captionTrack: Int32 = -99
@State var audioTrack: Int32 = -99
@State var playbackSpeedSelection : Int = 3
@State var playbackSpeedSelection: Int = 3
init(delegate: PlayerViewController) {
self.delegate = delegate
}
@ -66,8 +66,7 @@ struct VideoPlayerSettings: View {
let speed = delegate.playbackSpeeds[speedIndex]
if floor(speed) == speed {
Text(String(format: "%.0fx", speed)).tag(speedIndex)
}
else {
} else {
Text(String(format: "%.2fx", speed)).tag(speedIndex)
}
}

View File

@ -12,9 +12,9 @@ import JellyfinAPI
class UpNextViewModel: ObservableObject {
@Published var largeView: Bool = false
@Published var item: BaseItemDto? = nil
var delegate: PlayerViewController?
@Published var item: BaseItemDto?
weak var delegate: PlayerViewController?
func nextUp() {
if delegate != nil {
delegate?.setPlayerToNextUp()
@ -23,9 +23,9 @@ class UpNextViewModel: ObservableObject {
}
struct VideoUpNextView: View {
@ObservedObject var viewModel: UpNextViewModel
var body: some View {
Button {
viewModel.nextUp()

View File

@ -73,7 +73,7 @@ extension BaseItemDto {
let urlString = "\(ServerEnvironment.current.server.baseURI!)/Items/\(imageItemId)/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)"
return URL(string: urlString)!
}
func getEpisodeLocator() -> String {
if let seasonNo = self.parentIndexNumber, let episodeNo = self.indexNumber {
return "S\(seasonNo):E\(episodeNo)"
@ -111,7 +111,7 @@ extension BaseItemDto {
let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
let urlString = "\(ServerEnvironment.current.server.baseURI!)/Items/\(imageItemId)/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)"
//print(urlString)
// print(urlString)
return URL(string: urlString)!
}

View File

@ -54,17 +54,17 @@ final class SessionManager {
var deviceName = UIDevice.current.name
deviceName = deviceName.folding(options: .diacriticInsensitive, locale: .current)
deviceName = String(deviceName.unicodeScalars.filter {CharacterSet.urlQueryAllowed.contains($0) })
var header = "MediaBrowser "
#if os(tvOS)
header.append("Client=\"Jellyfin tvOS\", ")
#else
header.append("Client=\"SwiftFin iOS\", ")
#endif
header.append("Device=\"\(deviceName)\", ")
if(devID == nil) {
if devID == nil {
#if os(tvOS)
header.append("DeviceId=\"tvOS_\(UIDevice.current.identifierForVendor!.uuidString)_\(String(Date().timeIntervalSince1970))\", ")
deviceID = "tvOS_\(UIDevice.current.identifierForVendor!.uuidString)_\(String(Date().timeIntervalSince1970))"
@ -78,7 +78,7 @@ final class SessionManager {
header.append("DeviceId=\"\(devID!)\", ")
deviceID = devID!
}
header.append("Version=\"\(appVersion ?? "0.0.1")\", ")
if authToken != nil {
@ -116,8 +116,8 @@ final class SessionManager {
func loginWithSavedSession(user: SignedInUser) {
let accessToken = getAuthToken(userID: user.user_id!)
print("logging in with saved session");
print("logging in with saved session")
self.user = user
generateAuthHeader(with: accessToken, deviceID: user.device_uuid)
print(JellyfinAPI.customHeaders)
@ -134,7 +134,7 @@ final class SessionManager {
user.username = response.user?.name
user.user_id = response.user?.id
user.device_uuid = self.deviceID
#if os(tvOS)
// user.appletv_id = tvUserManager.currentUserIdentifier ?? ""
#endif

View File

@ -14,7 +14,7 @@ import JellyfinAPI
class DetailItemViewModel: ViewModel {
@Published var item: BaseItemDto
@Published var similarItems: [BaseItemDto] = []
@Published var isWatched = false
@Published var isFavorited = false
@ -23,10 +23,10 @@ class DetailItemViewModel: ViewModel {
isFavorited = item.userData?.isFavorite ?? false
isWatched = item.userData?.played ?? false
super.init()
getRelatedItems()
}
func getRelatedItems() {
LibraryAPI.getSimilarItems(itemId: item.id!, userId: SessionManager.current.user.user_id!, limit: 20, fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people])
.trackActivity(loading)

View File

@ -39,7 +39,7 @@ final class LibraryFilterViewModel: ViewModel {
var selectedSortOrder: APISortOrder = .descending
@Published
var selectedSortBy: SortBy = .name
var parentId: String = ""
func updateModifiedFilter() {

View File

@ -87,7 +87,7 @@ final class LibraryViewModel: ViewModel {
})
.store(in: &cancellables)
}
func requestItemsAsync(with filters: LibraryFilters) {
let personIDs: [String] = [person].compactMap(\.?.id)
let studioIDs: [String] = [studio].compactMap(\.?.id)
@ -121,7 +121,7 @@ final class LibraryViewModel: ViewModel {
currentPage += 1
requestItems(with: filters)
}
func requestNextPageAsync() {
currentPage += 1
requestItemsAsync(with: filters)

View File

@ -13,11 +13,11 @@ import JellyfinAPI
final class SeasonItemViewModel: DetailItemViewModel {
@Published var episodes = [BaseItemDto]()
override init(item: BaseItemDto) {
super.init(item: item)
self.item = item
requestEpisodes()
}

View File

@ -14,15 +14,15 @@ import JellyfinAPI
final class SeriesItemViewModel: DetailItemViewModel {
@Published var seasons = [BaseItemDto]()
@Published var nextUpItem: BaseItemDto?
override init(item: BaseItemDto) {
super.init(item: item)
self.item = item
requestSeasons()
getNextUp()
}
func getNextUp() {
TvShowsAPI.getNextUp(userId: SessionManager.current.user.user_id!, fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], seriesId: self.item.id!, enableUserData: true)
.trackActivity(loading)
@ -33,22 +33,22 @@ final class SeriesItemViewModel: DetailItemViewModel {
})
.store(in: &cancellables)
}
func getRunYears() -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy"
var startYear: String? = nil
var endYear: String? = nil
if(item.premiereDate != nil) {
var startYear: String?
var endYear: String?
if item.premiereDate != nil {
startYear = dateFormatter.string(from: item.premiereDate!)
}
if(item.endDate != nil) {
if item.endDate != nil {
endYear = dateFormatter.string(from: item.endDate!)
}
return "\(startYear ?? "Unknown") - \(endYear ?? "Present")"
}