Correspond to jellyfin 10.8

Update Package
This commit is contained in:
PangMo5 2022-06-18 04:47:37 +09:00
parent 7d545b0e6b
commit 2b3714cd8f
18 changed files with 198 additions and 206 deletions

View File

@ -20,12 +20,12 @@ jobs:
steps:
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '13.3'
xcode-version: '13.4.1'
- name: Checkout
uses: actions/checkout@v1
- uses: actions/cache@v2
- uses: actions/cache@v3
id: carthage-cache
with:
path: Carthage
@ -37,18 +37,12 @@ jobs:
run: carthage update --use-xcframeworks --cache-builds
- name: Cache Swift packages
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .build
key: ${{ runner.os }}-${{ matrix.scheme }}-spm-${{ hashFiles('**/Package.resolved') }}
restore-keys: |
${{ runner.os }}-${{ matrix.scheme }}-spm2-
- name: Cache DerivedData folder
uses: actions/cache@v2
with:
path: "~/Library/Developer/Xcode/DerivedData"
key: ${{ runner.os }}-${{ matrix.scheme }}-deriveddata
${{ runner.os }}-${{ matrix.scheme }}-spm-
- name: xcodebuild!
run: |

View File

@ -22,18 +22,18 @@ extension BaseItemDto {
builder.setMaxBitrate(bitrate: tempOverkillBitrate)
let profile = builder.buildProfile()
let playbackInfo = PlaybackInfoDto(userId: SessionManager.main.currentLogin.user.id,
maxStreamingBitrate: tempOverkillBitrate,
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
deviceProfile: profile,
autoOpenLiveStream: true)
let getPostedPlaybackInfoRequest = GetPostedPlaybackInfoRequest(userId: SessionManager.main.currentLogin.user.id,
maxStreamingBitrate: tempOverkillBitrate,
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
deviceProfile: profile,
autoOpenLiveStream: true)
return MediaInfoAPI.getPostedPlaybackInfo(itemId: self.id!,
userId: SessionManager.main.currentLogin.user.id,
maxStreamingBitrate: tempOverkillBitrate,
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
autoOpenLiveStream: true,
playbackInfoDto: playbackInfo)
getPostedPlaybackInfoRequest: getPostedPlaybackInfoRequest)
.map { response -> [VideoPlayerViewModel] in
let mediaSources = response.mediaSources!
@ -177,18 +177,18 @@ extension BaseItemDto {
builder.setMaxBitrate(bitrate: tempOverkillBitrate)
let profile = builder.buildProfile()
let playbackInfo = PlaybackInfoDto(userId: SessionManager.main.currentLogin.user.id,
maxStreamingBitrate: tempOverkillBitrate,
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
deviceProfile: profile,
autoOpenLiveStream: true)
let getPostedPlaybackInfoRequest = GetPostedPlaybackInfoRequest(userId: SessionManager.main.currentLogin.user.id,
maxStreamingBitrate: tempOverkillBitrate,
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
deviceProfile: profile,
autoOpenLiveStream: true)
return MediaInfoAPI.getPostedPlaybackInfo(itemId: self.id!,
userId: SessionManager.main.currentLogin.user.id,
maxStreamingBitrate: tempOverkillBitrate,
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
autoOpenLiveStream: true,
playbackInfoDto: playbackInfo)
getPostedPlaybackInfoRequest: getPostedPlaybackInfoRequest)
.map { response -> [VideoPlayerViewModel] in
let mediaSources = response.mediaSources!

View File

@ -266,7 +266,7 @@ public extension BaseItemDto {
}
var itemType: ItemType {
guard let originalType = type, let knownType = ItemType(rawValue: originalType) else { return .unknown }
guard let originalType = type, let knownType = ItemType(rawValue: originalType.rawValue) else { return .unknown }
return knownType
}

View File

@ -42,7 +42,7 @@ class DeviceProfileBuilder {
self.bitrate = bitrate
}
public func buildProfile() -> DeviceProfile {
public func buildProfile() -> ClientCapabilitiesDeviceProfile {
let maxStreamingBitrate = bitrate
let maxStaticBitrate = bitrate
let musicStreamingTranscodingBitrate = bitrate
@ -147,10 +147,12 @@ class DeviceProfileBuilder {
let responseProfiles: [ResponseProfile] = [ResponseProfile(container: "m4v", type: .video, mimeType: "video/mp4")]
let profile = DeviceProfile(maxStreamingBitrate: maxStreamingBitrate, maxStaticBitrate: maxStaticBitrate,
musicStreamingTranscodingBitrate: musicStreamingTranscodingBitrate,
directPlayProfiles: directPlayProfiles, transcodingProfiles: transcodingProfiles, containerProfiles: [],
codecProfiles: codecProfiles, responseProfiles: responseProfiles, subtitleProfiles: subtitleProfiles)
let profile = ClientCapabilitiesDeviceProfile(maxStreamingBitrate: maxStreamingBitrate, maxStaticBitrate: maxStaticBitrate,
musicStreamingTranscodingBitrate: musicStreamingTranscodingBitrate,
directPlayProfiles: directPlayProfiles, transcodingProfiles: transcodingProfiles,
containerProfiles: [],
codecProfiles: codecProfiles, responseProfiles: responseProfiles,
subtitleProfiles: subtitleProfiles)
return profile
}

View File

@ -40,7 +40,7 @@ final class SessionManager {
let accessToken = user.accessToken else { fatalError("No associated server or access token for last user?") }
guard let existingServer = SwiftfinStore.dataStack.fetchExisting(server) else { return }
JellyfinAPI.basePath = server.currentURI
JellyfinAPIAPI.basePath = server.currentURI
setAuthHeader(with: accessToken.value)
currentLogin = (server: existingServer.state, user: user.state)
}
@ -78,7 +78,7 @@ final class SessionManager {
uri = String(uri.dropLast())
}
JellyfinAPI.basePath = uri
JellyfinAPIAPI.basePath = uri
return SystemAPI.getPublicSystemInfo()
.tryMap { response -> (SwiftfinStore.Models.StoredServer, UnsafeDataTransaction) in
@ -188,9 +188,9 @@ final class SessionManager {
{
setAuthHeader(with: "")
JellyfinAPI.basePath = server.currentURI
JellyfinAPIAPI.basePath = server.currentURI
return UserAPI.authenticateUserByName(authenticateUserByName: AuthenticateUserByName(username: username, pw: password))
return UserAPI.authenticateUserByName(authenticateUserByNameRequest: .init(username: username, pw: password))
.tryMap { response -> (SwiftfinStore.Models.StoredServer, SwiftfinStore.Models.StoredUser, UnsafeDataTransaction) in
guard let accessToken = response.accessToken else { throw JellyfinAPIError("Access token missing from network call") }
@ -251,7 +251,7 @@ final class SessionManager {
// MARK: loginUser
func loginUser(server: SwiftfinStore.State.Server, user: SwiftfinStore.State.User) {
JellyfinAPI.basePath = server.currentURI
JellyfinAPIAPI.basePath = server.currentURI
Defaults[.lastServerUserID] = user.id
setAuthHeader(with: user.accessToken)
currentLogin = (server: server, user: user)
@ -262,7 +262,7 @@ final class SessionManager {
func logout() {
currentLogin = nil
JellyfinAPI.basePath = ""
JellyfinAPIAPI.basePath = ""
setAuthHeader(with: "")
Defaults[.lastServerUserID] = nil
Notifications[.didSignOut].post()
@ -339,6 +339,6 @@ final class SessionManager {
header.append("Version=\"\(appVersion ?? "0.0.1")\", ")
header.append("Token=\"\(accessToken)\"")
JellyfinAPI.customHeaders["X-Emby-Authorization"] = header
JellyfinAPIAPI.customHeaders["X-Emby-Authorization"] = header
}
}

View File

@ -135,7 +135,7 @@ final class HomeViewModel: ViewModel {
.people,
.chapters,
],
includeItemTypes: ["Movie", "Series"],
includeItemTypes: [.movie, .series],
enableImageTypes: [.primary, .backdrop, .thumb],
enableUserData: true,
limit: 8)

View File

@ -36,7 +36,7 @@ final class LatestMediaViewModel: ViewModel {
.genres,
.people,
],
includeItemTypes: ["Series", "Movie"],
includeItemTypes: [.series, .movie],
enableUserData: true, limit: 12)
.trackActivity(loading)
.sink(receiveCompletion: { [weak self] completion in

View File

@ -94,7 +94,7 @@ final class LibrarySearchViewModel: ViewModel {
limit: 20,
recursive: true,
parentId: parentID,
includeItemTypes: ["Movie", "Series"],
includeItemTypes: [.movie, .series],
sortBy: ["IsFavoriteOrLiked", "Random"],
imageTypeLimit: 0,
enableTotalRecordCount: false,
@ -113,7 +113,7 @@ final class LibrarySearchViewModel: ViewModel {
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query,
sortOrder: [.ascending], parentId: parentID,
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
includeItemTypes: [ItemType.movie.rawValue], sortBy: ["SortName"], enableUserData: true,
includeItemTypes: [.movie], sortBy: ["SortName"], enableUserData: true,
enableImages: true)
.trackActivity(loading)
.receive(on: DispatchQueue.main)
@ -126,7 +126,7 @@ final class LibrarySearchViewModel: ViewModel {
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query,
sortOrder: [.ascending], parentId: parentID,
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
includeItemTypes: [ItemType.series.rawValue], sortBy: ["SortName"], enableUserData: true,
includeItemTypes: [.series], sortBy: ["SortName"], enableUserData: true,
enableImages: true)
.trackActivity(loading)
.receive(on: DispatchQueue.main)
@ -139,7 +139,7 @@ final class LibrarySearchViewModel: ViewModel {
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query,
sortOrder: [.ascending], parentId: parentID,
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
includeItemTypes: [ItemType.episode.rawValue], sortBy: ["SortName"], enableUserData: true,
includeItemTypes: [.episode], sortBy: ["SortName"], enableUserData: true,
enableImages: true)
.trackActivity(loading)
.receive(on: DispatchQueue.main)

View File

@ -99,18 +99,18 @@ final class LibraryViewModel: ViewModel {
self.person != nil ||
self.genre != nil ||
self.studio != nil
let includeItemTypes: [String]
let includeItemTypes: [BaseItemKind]
if filters.filters.contains(.isFavorite) {
includeItemTypes = ["Movie", "Series", "Season", "Episode", "BoxSet"]
includeItemTypes = [.movie, .series, .season, .episode, .boxSet]
} else {
includeItemTypes = ["Movie", "Series", "BoxSet"] + (Defaults[.showFlattenView] ? [] : ["Folder"])
includeItemTypes = [.movie, .series, .boxSet] + (Defaults[.showFlattenView] ? [] : [.folder])
}
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, startIndex: currentPage * pageItemSize,
limit: pageItemSize,
recursive: queryRecursive,
searchTerm: nil,
sortOrder: filters.sortOrder,
sortOrder: filters.sortOrder.compactMap { SortOrder(rawValue: $0.rawValue) },
parentId: parentID,
fields: [
.primaryImageAspectRatio,

View File

@ -106,18 +106,18 @@ final class LiveTVChannelsViewModel: ViewModel {
let minEndDate = Date.now.addComponentsToDate(hours: -1)
let maxStartDate = minEndDate.addComponentsToDate(hours: 6)
let getProgramsDto = GetProgramsDto(channelIds: channelIds,
userId: SessionManager.main.currentLogin.user.id,
maxStartDate: maxStartDate,
minEndDate: minEndDate,
sortBy: ["StartDate"],
enableImages: true,
enableTotalRecordCount: false,
imageTypeLimit: 1,
enableImageTypes: [.primary],
enableUserData: false)
let getProgramsRequest = GetProgramsRequest(channelIds: channelIds,
userId: SessionManager.main.currentLogin.user.id,
maxStartDate: maxStartDate,
minEndDate: minEndDate,
sortBy: ["StartDate"],
enableImages: true,
enableTotalRecordCount: false,
imageTypeLimit: 1,
enableImageTypes: [.primary],
enableUserData: false)
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
.trackActivity(loading)
.sink(receiveCompletion: { [weak self] completion in
self?.handleAPIRequestError(completion: completion)

View File

@ -86,19 +86,19 @@ final class LiveTVProgramsViewModel: ViewModel {
}
private func getSeries() {
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isMovie: false,
isSeries: true,
isNews: false,
isKids: false,
isSports: false,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isMovie: false,
isSeries: true,
isNews: false,
isKids: false,
isSports: false,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
.trackActivity(loading)
.sink(receiveCompletion: { [weak self] completion in
self?.handleAPIRequestError(completion: completion)
@ -111,19 +111,19 @@ final class LiveTVProgramsViewModel: ViewModel {
}
private func getMovies() {
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isMovie: true,
isSeries: false,
isNews: false,
isKids: false,
isSports: false,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isMovie: true,
isSeries: false,
isNews: false,
isKids: false,
isSports: false,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
.trackActivity(loading)
.sink(receiveCompletion: { [weak self] completion in
self?.handleAPIRequestError(completion: completion)
@ -136,15 +136,15 @@ final class LiveTVProgramsViewModel: ViewModel {
}
private func getSports() {
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isSports: true,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isSports: true,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
.trackActivity(loading)
.sink(receiveCompletion: { [weak self] completion in
self?.handleAPIRequestError(completion: completion)
@ -157,15 +157,15 @@ final class LiveTVProgramsViewModel: ViewModel {
}
private func getKids() {
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isKids: true,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isKids: true,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
.trackActivity(loading)
.sink(receiveCompletion: { [weak self] completion in
self?.handleAPIRequestError(completion: completion)
@ -178,15 +178,15 @@ final class LiveTVProgramsViewModel: ViewModel {
}
private func getNews() {
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isNews: true,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
hasAired: false,
isNews: true,
limit: 9,
enableTotalRecordCount: false,
enableImageTypes: [.primary, .thumb],
fields: [.channelInfo, .primaryImageAspectRatio])
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
.trackActivity(loading)
.sink(receiveCompletion: { [weak self] completion in
self?.handleAPIRequestError(completion: completion)

View File

@ -206,7 +206,7 @@ final class VideoPlayerViewModel: ViewModel {
// During scrubbing, many progress reports were spammed
// Send only the current report after a delay
private var progressReportTimer: Timer?
private var lastProgressReport: PlaybackProgressInfo?
private var lastProgressReport: ReportPlaybackProgressRequest?
// MARK: init
@ -474,28 +474,27 @@ extension VideoPlayerViewModel {
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
let startInfo = PlaybackStartInfo(canSeek: true,
item: item,
itemId: item.id,
sessionId: response.playSessionId,
mediaSourceId: item.id,
audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreamIndex,
isPaused: false,
isMuted: false,
positionTicks: item.userData?.playbackPositionTicks,
playbackStartTimeTicks: startTimeTicks,
volumeLevel: 100,
brightness: 100,
aspectRatio: nil,
playMethod: .directPlay,
liveStreamId: nil,
playSessionId: response.playSessionId,
repeatMode: .repeatNone,
nowPlayingQueue: nil,
playlistItemId: "playlistItem0")
let reportPlaybackStartRequest = ReportPlaybackStartRequest(canSeek: true,
itemId: item.id,
sessionId: response.playSessionId,
mediaSourceId: item.id,
audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreamIndex,
isPaused: false,
isMuted: false,
positionTicks: item.userData?.playbackPositionTicks,
playbackStartTimeTicks: startTimeTicks,
volumeLevel: 100,
brightness: 100,
aspectRatio: nil,
playMethod: .directPlay,
liveStreamId: nil,
playSessionId: response.playSessionId,
repeatMode: .repeatNone,
nowPlayingQueue: nil,
playlistItemId: "playlistItem0")
PlaystateAPI.reportPlaybackStart(playbackStartInfo: startInfo)
PlaystateAPI.reportPlaybackStart(reportPlaybackStartRequest: reportPlaybackStartRequest)
.sink { completion in
self.handleAPIRequestError(completion: completion)
} receiveValue: { _ in
@ -509,28 +508,27 @@ extension VideoPlayerViewModel {
func sendPauseReport(paused: Bool) {
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
let pauseInfo = PlaybackStartInfo(canSeek: true,
item: item,
itemId: item.id,
sessionId: response.playSessionId,
mediaSourceId: item.id,
audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreamIndex,
isPaused: paused,
isMuted: false,
positionTicks: currentSecondTicks,
playbackStartTimeTicks: startTimeTicks,
volumeLevel: 100,
brightness: 100,
aspectRatio: nil,
playMethod: .directPlay,
liveStreamId: nil,
playSessionId: response.playSessionId,
repeatMode: .repeatNone,
nowPlayingQueue: nil,
playlistItemId: "playlistItem0")
let reportPlaybackStartRequest = ReportPlaybackStartRequest(canSeek: true,
itemId: item.id,
sessionId: response.playSessionId,
mediaSourceId: item.id,
audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreamIndex,
isPaused: paused,
isMuted: false,
positionTicks: currentSecondTicks,
playbackStartTimeTicks: startTimeTicks,
volumeLevel: 100,
brightness: 100,
aspectRatio: nil,
playMethod: .directPlay,
liveStreamId: nil,
playSessionId: response.playSessionId,
repeatMode: .repeatNone,
nowPlayingQueue: nil,
playlistItemId: "playlistItem0")
PlaystateAPI.reportPlaybackStart(playbackStartInfo: pauseInfo)
PlaystateAPI.reportPlaybackStart(reportPlaybackStartRequest: reportPlaybackStartRequest)
.sink { completion in
self.handleAPIRequestError(completion: completion)
} receiveValue: { _ in
@ -544,26 +542,25 @@ extension VideoPlayerViewModel {
func sendProgressReport() {
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
let progressInfo = PlaybackProgressInfo(canSeek: true,
item: item,
itemId: item.id,
sessionId: response.playSessionId,
mediaSourceId: item.id,
audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreamIndex,
isPaused: false,
isMuted: false,
positionTicks: currentSecondTicks,
playbackStartTimeTicks: startTimeTicks,
volumeLevel: nil,
brightness: nil,
aspectRatio: nil,
playMethod: .directPlay,
liveStreamId: nil,
playSessionId: response.playSessionId,
repeatMode: .repeatNone,
nowPlayingQueue: nil,
playlistItemId: "playlistItem0")
let progressInfo = ReportPlaybackProgressRequest(canSeek: true,
itemId: item.id,
sessionId: response.playSessionId,
mediaSourceId: item.id,
audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreamIndex,
isPaused: false,
isMuted: false,
positionTicks: currentSecondTicks,
playbackStartTimeTicks: startTimeTicks,
volumeLevel: nil,
brightness: nil,
aspectRatio: nil,
playMethod: .directPlay,
liveStreamId: nil,
playSessionId: response.playSessionId,
repeatMode: .repeatNone,
nowPlayingQueue: nil,
playlistItemId: "playlistItem0")
lastProgressReport = progressInfo
@ -574,7 +571,7 @@ extension VideoPlayerViewModel {
private func _sendProgressReport() {
guard let lastProgressReport = lastProgressReport else { return }
PlaystateAPI.reportPlaybackProgress(playbackProgressInfo: lastProgressReport)
PlaystateAPI.reportPlaybackProgress(reportPlaybackProgressRequest: lastProgressReport)
.sink { completion in
self.handleAPIRequestError(completion: completion)
} receiveValue: { _ in
@ -588,19 +585,18 @@ extension VideoPlayerViewModel {
// MARK: sendStopReport
func sendStopReport() {
let stopInfo = PlaybackStopInfo(item: item,
itemId: item.id,
sessionId: response.playSessionId,
mediaSourceId: item.id,
positionTicks: currentSecondTicks,
liveStreamId: nil,
playSessionId: response.playSessionId,
failed: nil,
nextMediaType: nil,
playlistItemId: "playlistItem0",
nowPlayingQueue: nil)
let reportPlaybackStoppedRequest = ReportPlaybackStoppedRequest(itemId: item.id,
sessionId: response.playSessionId,
mediaSourceId: item.id,
positionTicks: currentSecondTicks,
liveStreamId: nil,
playSessionId: response.playSessionId,
failed: nil,
nextMediaType: nil,
playlistItemId: "playlistItem0",
nowPlayingQueue: nil)
PlaystateAPI.reportPlaybackStopped(playbackStopInfo: stopInfo)
PlaystateAPI.reportPlaybackStopped(reportPlaybackStoppedRequest: reportPlaybackStoppedRequest)
.sink { completion in
self.handleAPIRequestError(completion: completion)
} receiveValue: { _ in

View File

@ -46,9 +46,9 @@ struct LandscapeItemElement: View {
var body: some View {
VStack {
ImageView(item.type == "Episode" && !(inSeasonView ?? false) ? item.getSeriesBackdropImage(maxWidth: 445) : item
ImageView(item.type == .episode && !(inSeasonView ?? false) ? item.getSeriesBackdropImage(maxWidth: 445) : item
.getBackdropImage(maxWidth: 445),
blurHash: item.type == "Episode" ? item.getSeriesBackdropImageBlurHash() : item.getBackdropImageBlurHash())
blurHash: item.type == .episode ? item.getSeriesBackdropImageBlurHash() : item.getBackdropImageBlurHash())
.frame(width: 445, height: 250)
.cornerRadius(10)
.ignoresSafeArea()
@ -97,7 +97,7 @@ struct LandscapeItemElement: View {
.lineLimit(1)
.frame(width: 445)
} else {
Text(item.type == "Episode" ? "\(item.seriesName ?? "")\(item.getEpisodeLocator() ?? "")" : item.name ?? "")
Text(item.type == .episode ? "\(item.seriesName ?? "")\(item.getEpisodeLocator() ?? "")" : item.name ?? "")
.font(.callout)
.fontWeight(.semibold)
.lineLimit(1)

View File

@ -21,8 +21,8 @@ struct PortraitItemElement: View {
var body: some View {
VStack {
ImageView(item.type == "Episode" ? item.getSeriesPrimaryImage(maxWidth: 200) : item.getPrimaryImage(maxWidth: 200),
blurHash: item.type == "Episode" ? item.getSeriesPrimaryImageBlurHash() : item.getPrimaryImageBlurHash())
ImageView(item.type == .episode ? item.getSeriesPrimaryImage(maxWidth: 200) : item.getPrimaryImage(maxWidth: 200),
blurHash: item.type == .episode ? item.getSeriesPrimaryImageBlurHash() : item.getPrimaryImageBlurHash())
.frame(width: 200, height: 300)
.cornerRadius(10)
.shadow(radius: focused ? 10.0 : 0)
@ -58,12 +58,12 @@ struct PortraitItemElement: View {
.opacity(1), alignment: .topTrailing).opacity(1)
Text(item.title)
.frame(width: 200, height: 30, alignment: .center)
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

@ -47,7 +47,7 @@ struct MovieLibrariesView: View {
} cell: { _, cell in
GeometryReader { _ in
if let item = cell.item {
if item.type != "Folder" {
if item.type != .folder {
Button {
self.movieLibrariesRouter.route(to: \.library, item)
} label: {

View File

@ -47,7 +47,7 @@ struct TVLibrariesView: View {
} cell: { _, cell in
GeometryReader { _ in
if let item = cell.item {
if item.type != "Folder" {
if item.type != .folder {
Button {
self.tvLibrariesRouter.route(to: \.library, item)
} label: {

View File

@ -14,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/Flight-School/AnyCodable",
"state" : {
"revision" : "11423ef0c756e8a1f6b4bb576dab9d97bc016c70",
"version" : "0.6.4"
"revision" : "f9fda69a7b704d46fb5123005f2f7e43dbb8a0fa",
"version" : "0.6.5"
}
},
{
@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/CombineCommunity/CombineExt",
"state" : {
"revision" : "0880829102152185190064fd17847a7c681d2127",
"version" : "1.5.1"
"revision" : "38a4d4cb01f8c7750671c786d33dfbea00cbd131",
"version" : "1.6.1"
}
},
{
@ -50,8 +50,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/sindresorhus/Defaults",
"state" : {
"revision" : "119f654d44f7b90f00dc11f7dd1c94a36f12576b",
"version" : "6.2.1"
"revision" : "981ccb0a01c54abbe3c12ccb8226108527bbf115",
"version" : "6.3.0"
}
},
{
@ -78,16 +78,16 @@
"location" : "https://github.com/jellyfin/jellyfin-sdk-swift",
"state" : {
"branch" : "main",
"revision" : "f315671ced976a7ec75ce6a1f37e00b4880cbf4b"
"revision" : "9d6e46b94d2178116ee3546b03dfb67e19e3a93a"
}
},
{
"identity" : "nuke",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kean/Nuke.git",
"location" : "https://github.com/kean/Nuke",
"state" : {
"revision" : "0ea7545b5c918285aacc044dc75048625c8257cc",
"version" : "10.8.0"
"revision" : "a002b7fd786f2df2ed4333fe73a9727499fd9d97",
"version" : "10.11.2"
}
},
{
@ -95,8 +95,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/kean/NukeUI",
"state" : {
"revision" : "17f26c07e6b1d3b9258287f99f528111fcd7b7ad",
"version" : "0.8.1"
"revision" : "ebfed3c9a4e97e310b0ff8ee0fffe5579887a825",
"version" : "0.8.2"
}
},
{
@ -122,8 +122,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/rundfunk47/stinsen",
"state" : {
"revision" : "36d97964075dc770046ddef9346a29bfa8982d6d",
"version" : "2.0.7"
"revision" : "add05384b65ae3e39474f51ab5b9281abd238c60",
"version" : "2.0.9"
}
},
{
@ -168,7 +168,7 @@
"location" : "https://github.com/spacenation/swiftui-sliders",
"state" : {
"branch" : "master",
"revision" : "538e16b35ad7a066a8f5624da9ecee6327886bf7"
"revision" : "5ba8614462a7ed4bd47a93fbca6c281599f74337"
}
},
{

View File

@ -32,7 +32,7 @@ struct NextUpWidgetProvider: TimelineProvider {
let savedUser = currentLogin.user
var tempCancellables = Set<AnyCancellable>()
JellyfinAPI.basePath = server.currentURI
JellyfinAPIAPI.basePath = server.currentURI
TvShowsAPI.getNextUp(userId: savedUser.id, limit: 3,
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
imageTypeLimit: 1, enableImageTypes: [.primary, .backdrop, .thumb])
@ -77,7 +77,7 @@ struct NextUpWidgetProvider: TimelineProvider {
var tempCancellables = Set<AnyCancellable>()
JellyfinAPI.basePath = server.currentURI
JellyfinAPIAPI.basePath = server.currentURI
TvShowsAPI.getNextUp(userId: savedUser.id, limit: 3,
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
imageTypeLimit: 1, enableImageTypes: [.primary, .backdrop, .thumb])