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>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>43</string>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchScreen</key>

View File

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

View File

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

View File

@ -12,13 +12,14 @@ import SwiftUI
struct HomeView: View {
@StateObject var viewModel = HomeViewModel()
@State private var orientation = UIDevice.current.orientation
@Environment(\.horizontalSizeClass) var hSizeClass
@Environment(\.verticalSizeClass) var vSizeClass
@State var showingSettings = false
var body: some View {
ZStack {
if(viewModel.isLoading) {
ProgressView()
} else {
ScrollView {
LazyVStack(alignment: .leading) {
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)
}
}
if viewModel.isLoading {
ProgressView()
}
}
.onRotate {
orientation = $0
}
.navigationTitle(MainTabView.Tab.home.localized)
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
showingSettings = true
} label: {
Image(systemName: "gear")
.navigationTitle(MainTabView.Tab.home.localized)
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
showingSettings = true
} label: {
Image(systemName: "gear")
}
}
}
}
.fullScreenCover(isPresented: $showingSettings) {
SettingsView(viewModel: SettingsViewModel(), close: $showingSettings)
.fullScreenCover(isPresented: $showingSettings) {
SettingsView(viewModel: SettingsViewModel(), close: $showingSettings)
}
}
}
}

View File

@ -19,24 +19,26 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>43</string>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>${PRODUCT_NAME} uses Bluetooth to discover nearby Cast devices.</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsForMedia</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSAllowsLocalNetworking</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</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>
<array>
<string>_googlecast._tcp</string>
@ -45,6 +47,8 @@
<key>NSLocalNetworkUsageDescription</key>
<string>${PRODUCT_NAME} uses the local network to connect to your Jellyfin server &amp; discover Cast-enabled devices on your WiFi
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>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>

View File

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

View File

@ -558,6 +558,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
print("Local playback engine starting.")
mediaPlayer.media = VLCMedia(url: playbackItem.videoUrl)
mediaPlayer.play()
sendPlayReport()
// 1 second = 10,000,000 ticks
var startTicks: Int64 = 0;
@ -595,9 +596,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
// Wait for captions to load
delegate?.showLoadingView(self)
while mediaPlayer.numberOfSubtitlesTracks != shouldHaveSubtitleTracks {
print("waiting \(String(mediaPlayer.numberOfSubtitlesTracks)) != \(String(shouldHaveSubtitleTracks))")
}
while mediaPlayer.numberOfSubtitlesTracks != shouldHaveSubtitleTracks {}
// Select default track & resume playback
mediaPlayer.currentVideoSubTitleIndex = selectedCaptionTrack
@ -643,9 +642,8 @@ extension PlayerViewController: GCKGenericChannelDelegate {
}
timeText.text = timeTextStr
let playbackProgress = Int64(remotePositionTicks) / manifest.runTimeTicks!
print(playbackProgress)
seekSlider.setValue(Float(playbackProgress), animated: true)
let playbackProgress = Float(remotePositionTicks) / Float(manifest.runTimeTicks!)
seekSlider.setValue(playbackProgress, animated: true)
}
}
@ -654,11 +652,14 @@ extension PlayerViewController: GCKGenericChannelDelegate {
if let json = try? JSON(data: data) {
let messageType = json["type"].string ?? ""
if(messageType == "playbackprogress") {
if(hasSentRemoteSeek == false) {
hasSentRemoteSeek = true;
sendJellyfinCommand(command: "Seek", options: [
"position": Int(Float(manifest.runTimeTicks! / 10_000_000) * mediaPlayer.position)
])
dump(json)
if(remotePositionTicks > 100) {
if(hasSentRemoteSeek == false) {
hasSentRemoteSeek = true;
sendJellyfinCommand(command: "Seek", options: [
"position": Int(Float(manifest.runTimeTicks! / 10_000_000) * mediaPlayer.position)
])
}
}
paused = json["data"]["PlayState"]["IsPaused"].boolValue
self.remotePositionTicks = json["data"]["PlayState"]["PositionTicks"].int ?? 0;
@ -687,6 +688,20 @@ extension PlayerViewController: GCKGenericChannelDelegate {
let jsonData = JSON(payload)
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:
return "Title"
case .dateAdded:
return "Date added"
return "Date Added"
}
}
}
extension ItemFilter {
static var supportedTypes: [ItemFilter] {
[.isUnplayed, isPlayed, .isFavorite, .likes, .isFavoriteOrLikes]
[.isUnplayed, isPlayed, .isFavorite, .likes]
}
var localized: String {
@ -53,9 +53,7 @@ extension ItemFilter {
case .isFavorite:
return "Favorites"
case .likes:
return "Liked"
case .isFavoriteOrLikes:
return "Favorites or Liked"
return "Liked Items"
default:
return ""
}

View File

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

View File

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