release 49

This commit is contained in:
Aiden Vigue 2021-06-20 23:18:22 -04:00
parent 571e0c4e8e
commit a7ed08e2b5
No known key found for this signature in database
GPG Key ID: B9A09843AB079D5B
10 changed files with 72 additions and 61 deletions

View File

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string> <string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>43</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UILaunchScreen</key> <key>UILaunchScreen</key>

View File

@ -1002,7 +1002,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "JellyfinPlayer tvOS/JellyfinPlayer tvOS.entitlements"; CODE_SIGN_ENTITLEMENTS = "JellyfinPlayer tvOS/JellyfinPlayer tvOS.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 43; CURRENT_PROJECT_VERSION = 49;
DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer tvOS/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer tvOS/Preview Content\"";
DEVELOPMENT_TEAM = 9R8RREG67J; DEVELOPMENT_TEAM = 9R8RREG67J;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@ -1030,7 +1030,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "JellyfinPlayer tvOS/JellyfinPlayer tvOS.entitlements"; CODE_SIGN_ENTITLEMENTS = "JellyfinPlayer tvOS/JellyfinPlayer tvOS.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 43; CURRENT_PROJECT_VERSION = 49;
DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer tvOS/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer tvOS/Preview Content\"";
DEVELOPMENT_TEAM = 9R8RREG67J; DEVELOPMENT_TEAM = 9R8RREG67J;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@ -1179,7 +1179,7 @@
CODE_SIGN_ENTITLEMENTS = JellyfinPlayer/JellyfinPlayer.entitlements; CODE_SIGN_ENTITLEMENTS = JellyfinPlayer/JellyfinPlayer.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 43; CURRENT_PROJECT_VERSION = 49;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = 9R8RREG67J; DEVELOPMENT_TEAM = 9R8RREG67J;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -1213,7 +1213,7 @@
CODE_SIGN_ENTITLEMENTS = JellyfinPlayer/JellyfinPlayer.entitlements; CODE_SIGN_ENTITLEMENTS = JellyfinPlayer/JellyfinPlayer.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 43; CURRENT_PROJECT_VERSION = 49;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = 9R8RREG67J; DEVELOPMENT_TEAM = 9R8RREG67J;
@ -1245,7 +1245,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 43; CURRENT_PROJECT_VERSION = 49;
DEVELOPMENT_TEAM = 9R8RREG67J; DEVELOPMENT_TEAM = 9R8RREG67J;
INFOPLIST_FILE = WidgetExtension/Info.plist; INFOPLIST_FILE = WidgetExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.1; IPHONEOS_DEPLOYMENT_TARGET = 14.1;
@ -1270,7 +1270,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 43; CURRENT_PROJECT_VERSION = 49;
DEVELOPMENT_TEAM = 9R8RREG67J; DEVELOPMENT_TEAM = 9R8RREG67J;
INFOPLIST_FILE = WidgetExtension/Info.plist; INFOPLIST_FILE = WidgetExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.1; IPHONEOS_DEPLOYMENT_TARGET = 14.1;

View File

@ -80,8 +80,6 @@ struct ContinueWatchingView: View {
Spacer().frame(width: 2) Spacer().frame(width: 2)
}.frame(height: 215) }.frame(height: 215)
.padding(.bottom, 10) .padding(.bottom, 10)
} else {
EmptyView()
} }
} }
} }

View File

@ -12,13 +12,14 @@ import SwiftUI
struct HomeView: View { struct HomeView: View {
@StateObject var viewModel = HomeViewModel() @StateObject var viewModel = HomeViewModel()
@State private var orientation = UIDevice.current.orientation
@Environment(\.horizontalSizeClass) var hSizeClass @Environment(\.horizontalSizeClass) var hSizeClass
@Environment(\.verticalSizeClass) var vSizeClass @Environment(\.verticalSizeClass) var vSizeClass
@State var showingSettings = false @State var showingSettings = false
var body: some View { var body: some View {
ZStack { if(viewModel.isLoading) {
ProgressView()
} else {
ScrollView { ScrollView {
LazyVStack(alignment: .leading) { LazyVStack(alignment: .leading) {
Spacer().frame(height: hSizeClass == .compact && vSizeClass == .regular ? 0 : 16) Spacer().frame(height: hSizeClass == .compact && vSizeClass == .regular ? 0 : 16)
@ -55,25 +56,19 @@ struct HomeView: View {
Spacer().frame(height: UIDevice.current.userInterfaceIdiom == .phone ? 20 : 30) Spacer().frame(height: UIDevice.current.userInterfaceIdiom == .phone ? 20 : 30)
} }
} }
if viewModel.isLoading { .navigationTitle(MainTabView.Tab.home.localized)
ProgressView() .toolbar {
} ToolbarItemGroup(placement: .navigationBarTrailing) {
} Button {
.onRotate { showingSettings = true
orientation = $0 } label: {
} Image(systemName: "gear")
.navigationTitle(MainTabView.Tab.home.localized) }
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
showingSettings = true
} label: {
Image(systemName: "gear")
} }
} }
} .fullScreenCover(isPresented: $showingSettings) {
.fullScreenCover(isPresented: $showingSettings) { SettingsView(viewModel: SettingsViewModel(), close: $showingSettings)
SettingsView(viewModel: SettingsViewModel(), close: $showingSettings) }
} }
} }
} }

View File

@ -19,24 +19,26 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string> <string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>43</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>${PRODUCT_NAME} uses Bluetooth to discover nearby Cast devices.</string>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsForMedia</key> <key>NSAllowsArbitraryLoadsForMedia</key>
<true/> <true/>
<key>NSAllowsArbitraryLoadsInWebContent</key> <key>NSAllowsArbitraryLoadsInWebContent</key>
<true/> <true/>
<key>NSAllowsLocalNetworking</key> <key>NSAllowsLocalNetworking</key>
<true/> <true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict> </dict>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>${PRODUCT_NAME} uses Bluetooth to discover nearby Cast devices.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>${PRODUCT_NAME} uses Bluetooth to discover nearby Cast devices.</string>
<key>NSBonjourServices</key> <key>NSBonjourServices</key>
<array> <array>
<string>_googlecast._tcp</string> <string>_googlecast._tcp</string>
@ -45,6 +47,8 @@
<key>NSLocalNetworkUsageDescription</key> <key>NSLocalNetworkUsageDescription</key>
<string>${PRODUCT_NAME} uses the local network to connect to your Jellyfin server &amp; discover Cast-enabled devices on your WiFi <string>${PRODUCT_NAME} uses the local network to connect to your Jellyfin server &amp; discover Cast-enabled devices on your WiFi
network.</string> network.</string>
<key>NSMicrophoneUsageDescription</key>
<string>${PRODUCT_NAME} uses microphone access to listen for ultrasonic tokens when pairing with nearby Cast devices.</string>
<key>UIApplicationSceneManifest</key> <key>UIApplicationSceneManifest</key>
<dict> <dict>
<key>UIApplicationSupportsMultipleScenes</key> <key>UIApplicationSupportsMultipleScenes</key>

View File

@ -27,31 +27,32 @@ struct LibraryFilterView: View {
MultiSelector(label: "Genres", MultiSelector(label: "Genres",
options: viewModel.possibleGenres, options: viewModel.possibleGenres,
optionToString: { $0.name ?? "" }, optionToString: { $0.name ?? "" },
selected: $viewModel.modifyedFilters.withGenres) selected: $viewModel.modifiedFilters.withGenres)
} }
if viewModel.enabledFilterType.contains(.filter) { if viewModel.enabledFilterType.contains(.filter) {
MultiSelector(label: "Filters", MultiSelector(label: "Filters",
options: viewModel.possibleItemFilters, options: viewModel.possibleItemFilters,
optionToString: { $0.localized }, optionToString: { $0.localized },
selected: $viewModel.modifyedFilters.filters) selected: $viewModel.modifiedFilters.filters)
} }
if viewModel.enabledFilterType.contains(.tag) { if viewModel.enabledFilterType.contains(.tag) {
MultiSelector(label: "Tags", MultiSelector(label: "Tags",
options: viewModel.possibleTags, options: viewModel.possibleTags,
optionToString: { $0 }, optionToString: { $0 },
selected: $viewModel.modifyedFilters.tags) selected: $viewModel.modifiedFilters.tags)
} }
if viewModel.enabledFilterType.contains(.sortBy) { if viewModel.enabledFilterType.contains(.sortBy) {
MultiSelector(label: "Sort by", MultiSelector(label: "Sort by",
options: viewModel.possibleSortBys, options: viewModel.possibleSortBys,
optionToString: { $0.localized }, optionToString: { $0.localized },
selected: $viewModel.modifyedFilters.sortBy) selected: $viewModel.modifiedFilters.sortBy)
} }
if viewModel.enabledFilterType.contains(.sortOrder) { if viewModel.enabledFilterType.contains(.sortOrder) {
MultiSelector(label: "Sort Order", Picker(selection: $viewModel.modifiedFilters.sortOrder, label: Text("Order")) {
options: viewModel.possibleSortOrders, ForEach(viewModel.possibleSortOrders, id: \.self) { so in
optionToString: { $0.localized }, Text("\(so.rawValue)").tag(so.rawValue)
selected: $viewModel.modifyedFilters.sortOrder) }
}
} }
} }
if viewModel.isLoading { if viewModel.isLoading {
@ -69,7 +70,7 @@ struct LibraryFilterView: View {
} }
ToolbarItemGroup(placement: .navigationBarTrailing) { ToolbarItemGroup(placement: .navigationBarTrailing) {
Button { Button {
self.filters = viewModel.modifyedFilters self.filters = viewModel.modifiedFilters
presentationMode.wrappedValue.dismiss() presentationMode.wrappedValue.dismiss()
} label: { } label: {
Text("Apply") Text("Apply")

View File

@ -558,6 +558,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
print("Local playback engine starting.") print("Local playback engine starting.")
mediaPlayer.media = VLCMedia(url: playbackItem.videoUrl) mediaPlayer.media = VLCMedia(url: playbackItem.videoUrl)
mediaPlayer.play() mediaPlayer.play()
sendPlayReport()
// 1 second = 10,000,000 ticks // 1 second = 10,000,000 ticks
var startTicks: Int64 = 0; var startTicks: Int64 = 0;
@ -595,9 +596,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
// Wait for captions to load // Wait for captions to load
delegate?.showLoadingView(self) delegate?.showLoadingView(self)
while mediaPlayer.numberOfSubtitlesTracks != shouldHaveSubtitleTracks { while mediaPlayer.numberOfSubtitlesTracks != shouldHaveSubtitleTracks {}
print("waiting \(String(mediaPlayer.numberOfSubtitlesTracks)) != \(String(shouldHaveSubtitleTracks))")
}
// Select default track & resume playback // Select default track & resume playback
mediaPlayer.currentVideoSubTitleIndex = selectedCaptionTrack mediaPlayer.currentVideoSubTitleIndex = selectedCaptionTrack
@ -643,9 +642,8 @@ extension PlayerViewController: GCKGenericChannelDelegate {
} }
timeText.text = timeTextStr timeText.text = timeTextStr
let playbackProgress = Int64(remotePositionTicks) / manifest.runTimeTicks! let playbackProgress = Float(remotePositionTicks) / Float(manifest.runTimeTicks!)
print(playbackProgress) seekSlider.setValue(playbackProgress, animated: true)
seekSlider.setValue(Float(playbackProgress), animated: true)
} }
} }
@ -654,11 +652,14 @@ extension PlayerViewController: GCKGenericChannelDelegate {
if let json = try? JSON(data: data) { if let json = try? JSON(data: data) {
let messageType = json["type"].string ?? "" let messageType = json["type"].string ?? ""
if(messageType == "playbackprogress") { if(messageType == "playbackprogress") {
if(hasSentRemoteSeek == false) { dump(json)
hasSentRemoteSeek = true; if(remotePositionTicks > 100) {
sendJellyfinCommand(command: "Seek", options: [ if(hasSentRemoteSeek == false) {
"position": Int(Float(manifest.runTimeTicks! / 10_000_000) * mediaPlayer.position) hasSentRemoteSeek = true;
]) sendJellyfinCommand(command: "Seek", options: [
"position": Int(Float(manifest.runTimeTicks! / 10_000_000) * mediaPlayer.position)
])
}
} }
paused = json["data"]["PlayState"]["IsPaused"].boolValue paused = json["data"]["PlayState"]["IsPaused"].boolValue
self.remotePositionTicks = json["data"]["PlayState"]["PositionTicks"].int ?? 0; self.remotePositionTicks = json["data"]["PlayState"]["PositionTicks"].int ?? 0;
@ -687,6 +688,20 @@ extension PlayerViewController: GCKGenericChannelDelegate {
let jsonData = JSON(payload) let jsonData = JSON(payload)
jellyfinCastChannel?.sendTextMessage(jsonData.rawString()!, error: nil) jellyfinCastChannel?.sendTextMessage(jsonData.rawString()!, error: nil)
if(command == "Seek") {
remotePositionTicks = remotePositionTicks + ((options["position"] as! Int) * 10_000_000)
//Send playback report as Jellyfin Chromecast isn't smarter than a rock.
let progressInfo = PlaybackProgressInfo(canSeek: true, item: manifest, itemId: manifest.id, sessionId: playSessionId, mediaSourceId: manifest.id, audioStreamIndex: Int(selectedAudioTrack), subtitleStreamIndex: Int(selectedCaptionTrack), isPaused: paused, isMuted: false, positionTicks: Int64(remotePositionTicks), playbackStartTimeTicks: Int64(startTime), volumeLevel: 100, brightness: 100, aspectRatio: nil, playMethod: playbackItem.videoType, liveStreamId: nil, playSessionId: playSessionId, repeatMode: .repeatNone, nowPlayingQueue: [], playlistItemId: "playlistItem0")
PlaystateAPI.reportPlaybackProgress(playbackProgressInfo: progressInfo)
.sink(receiveCompletion: { result in
print(result)
}, receiveValue: { _ in
print("Playback progress report sent!")
})
.store(in: &cancellables)
}
} }
} }

View File

@ -34,14 +34,14 @@ extension SortBy {
case .name: case .name:
return "Title" return "Title"
case .dateAdded: case .dateAdded:
return "Date added" return "Date Added"
} }
} }
} }
extension ItemFilter { extension ItemFilter {
static var supportedTypes: [ItemFilter] { static var supportedTypes: [ItemFilter] {
[.isUnplayed, isPlayed, .isFavorite, .likes, .isFavoriteOrLikes] [.isUnplayed, isPlayed, .isFavorite, .likes]
} }
var localized: String { var localized: String {
@ -53,9 +53,7 @@ extension ItemFilter {
case .isFavorite: case .isFavorite:
return "Favorites" return "Favorites"
case .likes: case .likes:
return "Liked" return "Liked Items"
case .isFavoriteOrLikes:
return "Favorites or Liked"
default: default:
return "" return ""
} }

View File

@ -21,7 +21,7 @@ enum FilterType {
final class LibraryFilterViewModel: ViewModel { final class LibraryFilterViewModel: ViewModel {
@Published @Published
var modifyedFilters = LibraryFilters() var modifiedFilters = LibraryFilters()
@Published @Published
var possibleGenres = [NameGuidPair]() var possibleGenres = [NameGuidPair]()
@ -41,7 +41,7 @@ final class LibraryFilterViewModel: ViewModel {
self.enabledFilterType = enabledFilterType self.enabledFilterType = enabledFilterType
super.init() super.init()
if let filters = filters { if let filters = filters {
self.modifyedFilters = filters self.modifiedFilters = filters
} }
requestQueryFilters() requestQueryFilters()
} }

View File

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string> <string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>43</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSExtension</key> <key>NSExtension</key>
<dict> <dict>
<key>NSExtensionPointIdentifier</key> <key>NSExtensionPointIdentifier</key>