parent
7d545b0e6b
commit
2b3714cd8f
|
@ -20,12 +20,12 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: maxim-lobanov/setup-xcode@v1
|
- uses: maxim-lobanov/setup-xcode@v1
|
||||||
with:
|
with:
|
||||||
xcode-version: '13.3'
|
xcode-version: '13.4.1'
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
id: carthage-cache
|
id: carthage-cache
|
||||||
with:
|
with:
|
||||||
path: Carthage
|
path: Carthage
|
||||||
|
@ -37,18 +37,12 @@ jobs:
|
||||||
run: carthage update --use-xcframeworks --cache-builds
|
run: carthage update --use-xcframeworks --cache-builds
|
||||||
|
|
||||||
- name: Cache Swift packages
|
- name: Cache Swift packages
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: .build
|
path: .build
|
||||||
key: ${{ runner.os }}-${{ matrix.scheme }}-spm-${{ hashFiles('**/Package.resolved') }}
|
key: ${{ runner.os }}-${{ matrix.scheme }}-spm-${{ hashFiles('**/Package.resolved') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-${{ matrix.scheme }}-spm2-
|
${{ runner.os }}-${{ matrix.scheme }}-spm-
|
||||||
|
|
||||||
- name: Cache DerivedData folder
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: "~/Library/Developer/Xcode/DerivedData"
|
|
||||||
key: ${{ runner.os }}-${{ matrix.scheme }}-deriveddata
|
|
||||||
|
|
||||||
- name: xcodebuild!
|
- name: xcodebuild!
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -22,18 +22,18 @@ extension BaseItemDto {
|
||||||
builder.setMaxBitrate(bitrate: tempOverkillBitrate)
|
builder.setMaxBitrate(bitrate: tempOverkillBitrate)
|
||||||
let profile = builder.buildProfile()
|
let profile = builder.buildProfile()
|
||||||
|
|
||||||
let playbackInfo = PlaybackInfoDto(userId: SessionManager.main.currentLogin.user.id,
|
let getPostedPlaybackInfoRequest = GetPostedPlaybackInfoRequest(userId: SessionManager.main.currentLogin.user.id,
|
||||||
maxStreamingBitrate: tempOverkillBitrate,
|
maxStreamingBitrate: tempOverkillBitrate,
|
||||||
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
||||||
deviceProfile: profile,
|
deviceProfile: profile,
|
||||||
autoOpenLiveStream: true)
|
autoOpenLiveStream: true)
|
||||||
|
|
||||||
return MediaInfoAPI.getPostedPlaybackInfo(itemId: self.id!,
|
return MediaInfoAPI.getPostedPlaybackInfo(itemId: self.id!,
|
||||||
userId: SessionManager.main.currentLogin.user.id,
|
userId: SessionManager.main.currentLogin.user.id,
|
||||||
maxStreamingBitrate: tempOverkillBitrate,
|
maxStreamingBitrate: tempOverkillBitrate,
|
||||||
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
||||||
autoOpenLiveStream: true,
|
autoOpenLiveStream: true,
|
||||||
playbackInfoDto: playbackInfo)
|
getPostedPlaybackInfoRequest: getPostedPlaybackInfoRequest)
|
||||||
.map { response -> [VideoPlayerViewModel] in
|
.map { response -> [VideoPlayerViewModel] in
|
||||||
let mediaSources = response.mediaSources!
|
let mediaSources = response.mediaSources!
|
||||||
|
|
||||||
|
@ -177,18 +177,18 @@ extension BaseItemDto {
|
||||||
builder.setMaxBitrate(bitrate: tempOverkillBitrate)
|
builder.setMaxBitrate(bitrate: tempOverkillBitrate)
|
||||||
let profile = builder.buildProfile()
|
let profile = builder.buildProfile()
|
||||||
|
|
||||||
let playbackInfo = PlaybackInfoDto(userId: SessionManager.main.currentLogin.user.id,
|
let getPostedPlaybackInfoRequest = GetPostedPlaybackInfoRequest(userId: SessionManager.main.currentLogin.user.id,
|
||||||
maxStreamingBitrate: tempOverkillBitrate,
|
maxStreamingBitrate: tempOverkillBitrate,
|
||||||
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
||||||
deviceProfile: profile,
|
deviceProfile: profile,
|
||||||
autoOpenLiveStream: true)
|
autoOpenLiveStream: true)
|
||||||
|
|
||||||
return MediaInfoAPI.getPostedPlaybackInfo(itemId: self.id!,
|
return MediaInfoAPI.getPostedPlaybackInfo(itemId: self.id!,
|
||||||
userId: SessionManager.main.currentLogin.user.id,
|
userId: SessionManager.main.currentLogin.user.id,
|
||||||
maxStreamingBitrate: tempOverkillBitrate,
|
maxStreamingBitrate: tempOverkillBitrate,
|
||||||
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
||||||
autoOpenLiveStream: true,
|
autoOpenLiveStream: true,
|
||||||
playbackInfoDto: playbackInfo)
|
getPostedPlaybackInfoRequest: getPostedPlaybackInfoRequest)
|
||||||
.map { response -> [VideoPlayerViewModel] in
|
.map { response -> [VideoPlayerViewModel] in
|
||||||
let mediaSources = response.mediaSources!
|
let mediaSources = response.mediaSources!
|
||||||
|
|
||||||
|
|
|
@ -266,7 +266,7 @@ public extension BaseItemDto {
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemType: ItemType {
|
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
|
return knownType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class DeviceProfileBuilder {
|
||||||
self.bitrate = bitrate
|
self.bitrate = bitrate
|
||||||
}
|
}
|
||||||
|
|
||||||
public func buildProfile() -> DeviceProfile {
|
public func buildProfile() -> ClientCapabilitiesDeviceProfile {
|
||||||
let maxStreamingBitrate = bitrate
|
let maxStreamingBitrate = bitrate
|
||||||
let maxStaticBitrate = bitrate
|
let maxStaticBitrate = bitrate
|
||||||
let musicStreamingTranscodingBitrate = bitrate
|
let musicStreamingTranscodingBitrate = bitrate
|
||||||
|
@ -147,10 +147,12 @@ class DeviceProfileBuilder {
|
||||||
|
|
||||||
let responseProfiles: [ResponseProfile] = [ResponseProfile(container: "m4v", type: .video, mimeType: "video/mp4")]
|
let responseProfiles: [ResponseProfile] = [ResponseProfile(container: "m4v", type: .video, mimeType: "video/mp4")]
|
||||||
|
|
||||||
let profile = DeviceProfile(maxStreamingBitrate: maxStreamingBitrate, maxStaticBitrate: maxStaticBitrate,
|
let profile = ClientCapabilitiesDeviceProfile(maxStreamingBitrate: maxStreamingBitrate, maxStaticBitrate: maxStaticBitrate,
|
||||||
musicStreamingTranscodingBitrate: musicStreamingTranscodingBitrate,
|
musicStreamingTranscodingBitrate: musicStreamingTranscodingBitrate,
|
||||||
directPlayProfiles: directPlayProfiles, transcodingProfiles: transcodingProfiles, containerProfiles: [],
|
directPlayProfiles: directPlayProfiles, transcodingProfiles: transcodingProfiles,
|
||||||
codecProfiles: codecProfiles, responseProfiles: responseProfiles, subtitleProfiles: subtitleProfiles)
|
containerProfiles: [],
|
||||||
|
codecProfiles: codecProfiles, responseProfiles: responseProfiles,
|
||||||
|
subtitleProfiles: subtitleProfiles)
|
||||||
|
|
||||||
return profile
|
return profile
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ final class SessionManager {
|
||||||
let accessToken = user.accessToken else { fatalError("No associated server or access token for last user?") }
|
let accessToken = user.accessToken else { fatalError("No associated server or access token for last user?") }
|
||||||
guard let existingServer = SwiftfinStore.dataStack.fetchExisting(server) else { return }
|
guard let existingServer = SwiftfinStore.dataStack.fetchExisting(server) else { return }
|
||||||
|
|
||||||
JellyfinAPI.basePath = server.currentURI
|
JellyfinAPIAPI.basePath = server.currentURI
|
||||||
setAuthHeader(with: accessToken.value)
|
setAuthHeader(with: accessToken.value)
|
||||||
currentLogin = (server: existingServer.state, user: user.state)
|
currentLogin = (server: existingServer.state, user: user.state)
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ final class SessionManager {
|
||||||
uri = String(uri.dropLast())
|
uri = String(uri.dropLast())
|
||||||
}
|
}
|
||||||
|
|
||||||
JellyfinAPI.basePath = uri
|
JellyfinAPIAPI.basePath = uri
|
||||||
|
|
||||||
return SystemAPI.getPublicSystemInfo()
|
return SystemAPI.getPublicSystemInfo()
|
||||||
.tryMap { response -> (SwiftfinStore.Models.StoredServer, UnsafeDataTransaction) in
|
.tryMap { response -> (SwiftfinStore.Models.StoredServer, UnsafeDataTransaction) in
|
||||||
|
@ -188,9 +188,9 @@ final class SessionManager {
|
||||||
{
|
{
|
||||||
setAuthHeader(with: "")
|
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
|
.tryMap { response -> (SwiftfinStore.Models.StoredServer, SwiftfinStore.Models.StoredUser, UnsafeDataTransaction) in
|
||||||
|
|
||||||
guard let accessToken = response.accessToken else { throw JellyfinAPIError("Access token missing from network call") }
|
guard let accessToken = response.accessToken else { throw JellyfinAPIError("Access token missing from network call") }
|
||||||
|
@ -251,7 +251,7 @@ final class SessionManager {
|
||||||
// MARK: loginUser
|
// MARK: loginUser
|
||||||
|
|
||||||
func loginUser(server: SwiftfinStore.State.Server, user: SwiftfinStore.State.User) {
|
func loginUser(server: SwiftfinStore.State.Server, user: SwiftfinStore.State.User) {
|
||||||
JellyfinAPI.basePath = server.currentURI
|
JellyfinAPIAPI.basePath = server.currentURI
|
||||||
Defaults[.lastServerUserID] = user.id
|
Defaults[.lastServerUserID] = user.id
|
||||||
setAuthHeader(with: user.accessToken)
|
setAuthHeader(with: user.accessToken)
|
||||||
currentLogin = (server: server, user: user)
|
currentLogin = (server: server, user: user)
|
||||||
|
@ -262,7 +262,7 @@ final class SessionManager {
|
||||||
|
|
||||||
func logout() {
|
func logout() {
|
||||||
currentLogin = nil
|
currentLogin = nil
|
||||||
JellyfinAPI.basePath = ""
|
JellyfinAPIAPI.basePath = ""
|
||||||
setAuthHeader(with: "")
|
setAuthHeader(with: "")
|
||||||
Defaults[.lastServerUserID] = nil
|
Defaults[.lastServerUserID] = nil
|
||||||
Notifications[.didSignOut].post()
|
Notifications[.didSignOut].post()
|
||||||
|
@ -339,6 +339,6 @@ final class SessionManager {
|
||||||
header.append("Version=\"\(appVersion ?? "0.0.1")\", ")
|
header.append("Version=\"\(appVersion ?? "0.0.1")\", ")
|
||||||
header.append("Token=\"\(accessToken)\"")
|
header.append("Token=\"\(accessToken)\"")
|
||||||
|
|
||||||
JellyfinAPI.customHeaders["X-Emby-Authorization"] = header
|
JellyfinAPIAPI.customHeaders["X-Emby-Authorization"] = header
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ final class HomeViewModel: ViewModel {
|
||||||
.people,
|
.people,
|
||||||
.chapters,
|
.chapters,
|
||||||
],
|
],
|
||||||
includeItemTypes: ["Movie", "Series"],
|
includeItemTypes: [.movie, .series],
|
||||||
enableImageTypes: [.primary, .backdrop, .thumb],
|
enableImageTypes: [.primary, .backdrop, .thumb],
|
||||||
enableUserData: true,
|
enableUserData: true,
|
||||||
limit: 8)
|
limit: 8)
|
||||||
|
|
|
@ -36,7 +36,7 @@ final class LatestMediaViewModel: ViewModel {
|
||||||
.genres,
|
.genres,
|
||||||
.people,
|
.people,
|
||||||
],
|
],
|
||||||
includeItemTypes: ["Series", "Movie"],
|
includeItemTypes: [.series, .movie],
|
||||||
enableUserData: true, limit: 12)
|
enableUserData: true, limit: 12)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.sink(receiveCompletion: { [weak self] completion in
|
.sink(receiveCompletion: { [weak self] completion in
|
||||||
|
|
|
@ -94,7 +94,7 @@ final class LibrarySearchViewModel: ViewModel {
|
||||||
limit: 20,
|
limit: 20,
|
||||||
recursive: true,
|
recursive: true,
|
||||||
parentId: parentID,
|
parentId: parentID,
|
||||||
includeItemTypes: ["Movie", "Series"],
|
includeItemTypes: [.movie, .series],
|
||||||
sortBy: ["IsFavoriteOrLiked", "Random"],
|
sortBy: ["IsFavoriteOrLiked", "Random"],
|
||||||
imageTypeLimit: 0,
|
imageTypeLimit: 0,
|
||||||
enableTotalRecordCount: false,
|
enableTotalRecordCount: false,
|
||||||
|
@ -113,7 +113,7 @@ final class LibrarySearchViewModel: ViewModel {
|
||||||
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query,
|
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query,
|
||||||
sortOrder: [.ascending], parentId: parentID,
|
sortOrder: [.ascending], parentId: parentID,
|
||||||
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
||||||
includeItemTypes: [ItemType.movie.rawValue], sortBy: ["SortName"], enableUserData: true,
|
includeItemTypes: [.movie], sortBy: ["SortName"], enableUserData: true,
|
||||||
enableImages: true)
|
enableImages: true)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.receive(on: DispatchQueue.main)
|
.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,
|
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query,
|
||||||
sortOrder: [.ascending], parentId: parentID,
|
sortOrder: [.ascending], parentId: parentID,
|
||||||
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
||||||
includeItemTypes: [ItemType.series.rawValue], sortBy: ["SortName"], enableUserData: true,
|
includeItemTypes: [.series], sortBy: ["SortName"], enableUserData: true,
|
||||||
enableImages: true)
|
enableImages: true)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.receive(on: DispatchQueue.main)
|
.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,
|
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query,
|
||||||
sortOrder: [.ascending], parentId: parentID,
|
sortOrder: [.ascending], parentId: parentID,
|
||||||
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
||||||
includeItemTypes: [ItemType.episode.rawValue], sortBy: ["SortName"], enableUserData: true,
|
includeItemTypes: [.episode], sortBy: ["SortName"], enableUserData: true,
|
||||||
enableImages: true)
|
enableImages: true)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
|
|
|
@ -99,18 +99,18 @@ final class LibraryViewModel: ViewModel {
|
||||||
self.person != nil ||
|
self.person != nil ||
|
||||||
self.genre != nil ||
|
self.genre != nil ||
|
||||||
self.studio != nil
|
self.studio != nil
|
||||||
let includeItemTypes: [String]
|
let includeItemTypes: [BaseItemKind]
|
||||||
if filters.filters.contains(.isFavorite) {
|
if filters.filters.contains(.isFavorite) {
|
||||||
includeItemTypes = ["Movie", "Series", "Season", "Episode", "BoxSet"]
|
includeItemTypes = [.movie, .series, .season, .episode, .boxSet]
|
||||||
} else {
|
} 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,
|
ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, startIndex: currentPage * pageItemSize,
|
||||||
limit: pageItemSize,
|
limit: pageItemSize,
|
||||||
recursive: queryRecursive,
|
recursive: queryRecursive,
|
||||||
searchTerm: nil,
|
searchTerm: nil,
|
||||||
sortOrder: filters.sortOrder,
|
sortOrder: filters.sortOrder.compactMap { SortOrder(rawValue: $0.rawValue) },
|
||||||
parentId: parentID,
|
parentId: parentID,
|
||||||
fields: [
|
fields: [
|
||||||
.primaryImageAspectRatio,
|
.primaryImageAspectRatio,
|
||||||
|
|
|
@ -106,18 +106,18 @@ 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)
|
||||||
|
|
||||||
let getProgramsDto = GetProgramsDto(channelIds: channelIds,
|
let getProgramsRequest = GetProgramsRequest(channelIds: channelIds,
|
||||||
userId: SessionManager.main.currentLogin.user.id,
|
userId: SessionManager.main.currentLogin.user.id,
|
||||||
maxStartDate: maxStartDate,
|
maxStartDate: maxStartDate,
|
||||||
minEndDate: minEndDate,
|
minEndDate: minEndDate,
|
||||||
sortBy: ["StartDate"],
|
sortBy: ["StartDate"],
|
||||||
enableImages: true,
|
enableImages: true,
|
||||||
enableTotalRecordCount: false,
|
enableTotalRecordCount: false,
|
||||||
imageTypeLimit: 1,
|
imageTypeLimit: 1,
|
||||||
enableImageTypes: [.primary],
|
enableImageTypes: [.primary],
|
||||||
enableUserData: false)
|
enableUserData: false)
|
||||||
|
|
||||||
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
|
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.sink(receiveCompletion: { [weak self] completion in
|
.sink(receiveCompletion: { [weak self] completion in
|
||||||
self?.handleAPIRequestError(completion: completion)
|
self?.handleAPIRequestError(completion: completion)
|
||||||
|
|
|
@ -86,19 +86,19 @@ final class LiveTVProgramsViewModel: ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getSeries() {
|
private func getSeries() {
|
||||||
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
|
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
|
||||||
hasAired: false,
|
hasAired: false,
|
||||||
isMovie: false,
|
isMovie: false,
|
||||||
isSeries: true,
|
isSeries: true,
|
||||||
isNews: false,
|
isNews: false,
|
||||||
isKids: false,
|
isKids: false,
|
||||||
isSports: false,
|
isSports: false,
|
||||||
limit: 9,
|
limit: 9,
|
||||||
enableTotalRecordCount: false,
|
enableTotalRecordCount: false,
|
||||||
enableImageTypes: [.primary, .thumb],
|
enableImageTypes: [.primary, .thumb],
|
||||||
fields: [.channelInfo, .primaryImageAspectRatio])
|
fields: [.channelInfo, .primaryImageAspectRatio])
|
||||||
|
|
||||||
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
|
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.sink(receiveCompletion: { [weak self] completion in
|
.sink(receiveCompletion: { [weak self] completion in
|
||||||
self?.handleAPIRequestError(completion: completion)
|
self?.handleAPIRequestError(completion: completion)
|
||||||
|
@ -111,19 +111,19 @@ final class LiveTVProgramsViewModel: ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getMovies() {
|
private func getMovies() {
|
||||||
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
|
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
|
||||||
hasAired: false,
|
hasAired: false,
|
||||||
isMovie: true,
|
isMovie: true,
|
||||||
isSeries: false,
|
isSeries: false,
|
||||||
isNews: false,
|
isNews: false,
|
||||||
isKids: false,
|
isKids: false,
|
||||||
isSports: false,
|
isSports: false,
|
||||||
limit: 9,
|
limit: 9,
|
||||||
enableTotalRecordCount: false,
|
enableTotalRecordCount: false,
|
||||||
enableImageTypes: [.primary, .thumb],
|
enableImageTypes: [.primary, .thumb],
|
||||||
fields: [.channelInfo, .primaryImageAspectRatio])
|
fields: [.channelInfo, .primaryImageAspectRatio])
|
||||||
|
|
||||||
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
|
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.sink(receiveCompletion: { [weak self] completion in
|
.sink(receiveCompletion: { [weak self] completion in
|
||||||
self?.handleAPIRequestError(completion: completion)
|
self?.handleAPIRequestError(completion: completion)
|
||||||
|
@ -136,15 +136,15 @@ final class LiveTVProgramsViewModel: ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getSports() {
|
private func getSports() {
|
||||||
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
|
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
|
||||||
hasAired: false,
|
hasAired: false,
|
||||||
isSports: true,
|
isSports: true,
|
||||||
limit: 9,
|
limit: 9,
|
||||||
enableTotalRecordCount: false,
|
enableTotalRecordCount: false,
|
||||||
enableImageTypes: [.primary, .thumb],
|
enableImageTypes: [.primary, .thumb],
|
||||||
fields: [.channelInfo, .primaryImageAspectRatio])
|
fields: [.channelInfo, .primaryImageAspectRatio])
|
||||||
|
|
||||||
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
|
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.sink(receiveCompletion: { [weak self] completion in
|
.sink(receiveCompletion: { [weak self] completion in
|
||||||
self?.handleAPIRequestError(completion: completion)
|
self?.handleAPIRequestError(completion: completion)
|
||||||
|
@ -157,15 +157,15 @@ final class LiveTVProgramsViewModel: ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getKids() {
|
private func getKids() {
|
||||||
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
|
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
|
||||||
hasAired: false,
|
hasAired: false,
|
||||||
isKids: true,
|
isKids: true,
|
||||||
limit: 9,
|
limit: 9,
|
||||||
enableTotalRecordCount: false,
|
enableTotalRecordCount: false,
|
||||||
enableImageTypes: [.primary, .thumb],
|
enableImageTypes: [.primary, .thumb],
|
||||||
fields: [.channelInfo, .primaryImageAspectRatio])
|
fields: [.channelInfo, .primaryImageAspectRatio])
|
||||||
|
|
||||||
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
|
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.sink(receiveCompletion: { [weak self] completion in
|
.sink(receiveCompletion: { [weak self] completion in
|
||||||
self?.handleAPIRequestError(completion: completion)
|
self?.handleAPIRequestError(completion: completion)
|
||||||
|
@ -178,15 +178,15 @@ final class LiveTVProgramsViewModel: ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getNews() {
|
private func getNews() {
|
||||||
let getProgramsDto = GetProgramsDto(userId: SessionManager.main.currentLogin.user.id,
|
let getProgramsRequest = GetProgramsRequest(userId: SessionManager.main.currentLogin.user.id,
|
||||||
hasAired: false,
|
hasAired: false,
|
||||||
isNews: true,
|
isNews: true,
|
||||||
limit: 9,
|
limit: 9,
|
||||||
enableTotalRecordCount: false,
|
enableTotalRecordCount: false,
|
||||||
enableImageTypes: [.primary, .thumb],
|
enableImageTypes: [.primary, .thumb],
|
||||||
fields: [.channelInfo, .primaryImageAspectRatio])
|
fields: [.channelInfo, .primaryImageAspectRatio])
|
||||||
|
|
||||||
LiveTvAPI.getPrograms(getProgramsDto: getProgramsDto)
|
LiveTvAPI.getPrograms(getProgramsRequest: getProgramsRequest)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.sink(receiveCompletion: { [weak self] completion in
|
.sink(receiveCompletion: { [weak self] completion in
|
||||||
self?.handleAPIRequestError(completion: completion)
|
self?.handleAPIRequestError(completion: completion)
|
||||||
|
|
|
@ -206,7 +206,7 @@ final class VideoPlayerViewModel: ViewModel {
|
||||||
// During scrubbing, many progress reports were spammed
|
// During scrubbing, many progress reports were spammed
|
||||||
// Send only the current report after a delay
|
// Send only the current report after a delay
|
||||||
private var progressReportTimer: Timer?
|
private var progressReportTimer: Timer?
|
||||||
private var lastProgressReport: PlaybackProgressInfo?
|
private var lastProgressReport: ReportPlaybackProgressRequest?
|
||||||
|
|
||||||
// MARK: init
|
// MARK: init
|
||||||
|
|
||||||
|
@ -474,28 +474,27 @@ extension VideoPlayerViewModel {
|
||||||
|
|
||||||
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
|
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
|
||||||
|
|
||||||
let startInfo = PlaybackStartInfo(canSeek: true,
|
let reportPlaybackStartRequest = ReportPlaybackStartRequest(canSeek: true,
|
||||||
item: item,
|
itemId: item.id,
|
||||||
itemId: item.id,
|
sessionId: response.playSessionId,
|
||||||
sessionId: response.playSessionId,
|
mediaSourceId: item.id,
|
||||||
mediaSourceId: item.id,
|
audioStreamIndex: selectedAudioStreamIndex,
|
||||||
audioStreamIndex: selectedAudioStreamIndex,
|
subtitleStreamIndex: subtitleStreamIndex,
|
||||||
subtitleStreamIndex: subtitleStreamIndex,
|
isPaused: false,
|
||||||
isPaused: false,
|
isMuted: false,
|
||||||
isMuted: false,
|
positionTicks: item.userData?.playbackPositionTicks,
|
||||||
positionTicks: item.userData?.playbackPositionTicks,
|
playbackStartTimeTicks: startTimeTicks,
|
||||||
playbackStartTimeTicks: startTimeTicks,
|
volumeLevel: 100,
|
||||||
volumeLevel: 100,
|
brightness: 100,
|
||||||
brightness: 100,
|
aspectRatio: nil,
|
||||||
aspectRatio: nil,
|
playMethod: .directPlay,
|
||||||
playMethod: .directPlay,
|
liveStreamId: nil,
|
||||||
liveStreamId: nil,
|
playSessionId: response.playSessionId,
|
||||||
playSessionId: response.playSessionId,
|
repeatMode: .repeatNone,
|
||||||
repeatMode: .repeatNone,
|
nowPlayingQueue: nil,
|
||||||
nowPlayingQueue: nil,
|
playlistItemId: "playlistItem0")
|
||||||
playlistItemId: "playlistItem0")
|
|
||||||
|
|
||||||
PlaystateAPI.reportPlaybackStart(playbackStartInfo: startInfo)
|
PlaystateAPI.reportPlaybackStart(reportPlaybackStartRequest: reportPlaybackStartRequest)
|
||||||
.sink { completion in
|
.sink { completion in
|
||||||
self.handleAPIRequestError(completion: completion)
|
self.handleAPIRequestError(completion: completion)
|
||||||
} receiveValue: { _ in
|
} receiveValue: { _ in
|
||||||
|
@ -509,28 +508,27 @@ extension VideoPlayerViewModel {
|
||||||
func sendPauseReport(paused: Bool) {
|
func sendPauseReport(paused: Bool) {
|
||||||
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
|
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
|
||||||
|
|
||||||
let pauseInfo = PlaybackStartInfo(canSeek: true,
|
let reportPlaybackStartRequest = ReportPlaybackStartRequest(canSeek: true,
|
||||||
item: item,
|
itemId: item.id,
|
||||||
itemId: item.id,
|
sessionId: response.playSessionId,
|
||||||
sessionId: response.playSessionId,
|
mediaSourceId: item.id,
|
||||||
mediaSourceId: item.id,
|
audioStreamIndex: selectedAudioStreamIndex,
|
||||||
audioStreamIndex: selectedAudioStreamIndex,
|
subtitleStreamIndex: subtitleStreamIndex,
|
||||||
subtitleStreamIndex: subtitleStreamIndex,
|
isPaused: paused,
|
||||||
isPaused: paused,
|
isMuted: false,
|
||||||
isMuted: false,
|
positionTicks: currentSecondTicks,
|
||||||
positionTicks: currentSecondTicks,
|
playbackStartTimeTicks: startTimeTicks,
|
||||||
playbackStartTimeTicks: startTimeTicks,
|
volumeLevel: 100,
|
||||||
volumeLevel: 100,
|
brightness: 100,
|
||||||
brightness: 100,
|
aspectRatio: nil,
|
||||||
aspectRatio: nil,
|
playMethod: .directPlay,
|
||||||
playMethod: .directPlay,
|
liveStreamId: nil,
|
||||||
liveStreamId: nil,
|
playSessionId: response.playSessionId,
|
||||||
playSessionId: response.playSessionId,
|
repeatMode: .repeatNone,
|
||||||
repeatMode: .repeatNone,
|
nowPlayingQueue: nil,
|
||||||
nowPlayingQueue: nil,
|
playlistItemId: "playlistItem0")
|
||||||
playlistItemId: "playlistItem0")
|
|
||||||
|
|
||||||
PlaystateAPI.reportPlaybackStart(playbackStartInfo: pauseInfo)
|
PlaystateAPI.reportPlaybackStart(reportPlaybackStartRequest: reportPlaybackStartRequest)
|
||||||
.sink { completion in
|
.sink { completion in
|
||||||
self.handleAPIRequestError(completion: completion)
|
self.handleAPIRequestError(completion: completion)
|
||||||
} receiveValue: { _ in
|
} receiveValue: { _ in
|
||||||
|
@ -544,26 +542,25 @@ extension VideoPlayerViewModel {
|
||||||
func sendProgressReport() {
|
func sendProgressReport() {
|
||||||
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
|
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
|
||||||
|
|
||||||
let progressInfo = PlaybackProgressInfo(canSeek: true,
|
let progressInfo = ReportPlaybackProgressRequest(canSeek: true,
|
||||||
item: item,
|
itemId: item.id,
|
||||||
itemId: item.id,
|
sessionId: response.playSessionId,
|
||||||
sessionId: response.playSessionId,
|
mediaSourceId: item.id,
|
||||||
mediaSourceId: item.id,
|
audioStreamIndex: selectedAudioStreamIndex,
|
||||||
audioStreamIndex: selectedAudioStreamIndex,
|
subtitleStreamIndex: subtitleStreamIndex,
|
||||||
subtitleStreamIndex: subtitleStreamIndex,
|
isPaused: false,
|
||||||
isPaused: false,
|
isMuted: false,
|
||||||
isMuted: false,
|
positionTicks: currentSecondTicks,
|
||||||
positionTicks: currentSecondTicks,
|
playbackStartTimeTicks: startTimeTicks,
|
||||||
playbackStartTimeTicks: startTimeTicks,
|
volumeLevel: nil,
|
||||||
volumeLevel: nil,
|
brightness: nil,
|
||||||
brightness: nil,
|
aspectRatio: nil,
|
||||||
aspectRatio: nil,
|
playMethod: .directPlay,
|
||||||
playMethod: .directPlay,
|
liveStreamId: nil,
|
||||||
liveStreamId: nil,
|
playSessionId: response.playSessionId,
|
||||||
playSessionId: response.playSessionId,
|
repeatMode: .repeatNone,
|
||||||
repeatMode: .repeatNone,
|
nowPlayingQueue: nil,
|
||||||
nowPlayingQueue: nil,
|
playlistItemId: "playlistItem0")
|
||||||
playlistItemId: "playlistItem0")
|
|
||||||
|
|
||||||
lastProgressReport = progressInfo
|
lastProgressReport = progressInfo
|
||||||
|
|
||||||
|
@ -574,7 +571,7 @@ extension VideoPlayerViewModel {
|
||||||
private func _sendProgressReport() {
|
private func _sendProgressReport() {
|
||||||
guard let lastProgressReport = lastProgressReport else { return }
|
guard let lastProgressReport = lastProgressReport else { return }
|
||||||
|
|
||||||
PlaystateAPI.reportPlaybackProgress(playbackProgressInfo: lastProgressReport)
|
PlaystateAPI.reportPlaybackProgress(reportPlaybackProgressRequest: lastProgressReport)
|
||||||
.sink { completion in
|
.sink { completion in
|
||||||
self.handleAPIRequestError(completion: completion)
|
self.handleAPIRequestError(completion: completion)
|
||||||
} receiveValue: { _ in
|
} receiveValue: { _ in
|
||||||
|
@ -588,19 +585,18 @@ extension VideoPlayerViewModel {
|
||||||
// MARK: sendStopReport
|
// MARK: sendStopReport
|
||||||
|
|
||||||
func sendStopReport() {
|
func sendStopReport() {
|
||||||
let stopInfo = PlaybackStopInfo(item: item,
|
let reportPlaybackStoppedRequest = ReportPlaybackStoppedRequest(itemId: item.id,
|
||||||
itemId: item.id,
|
sessionId: response.playSessionId,
|
||||||
sessionId: response.playSessionId,
|
mediaSourceId: item.id,
|
||||||
mediaSourceId: item.id,
|
positionTicks: currentSecondTicks,
|
||||||
positionTicks: currentSecondTicks,
|
liveStreamId: nil,
|
||||||
liveStreamId: nil,
|
playSessionId: response.playSessionId,
|
||||||
playSessionId: response.playSessionId,
|
failed: nil,
|
||||||
failed: nil,
|
nextMediaType: nil,
|
||||||
nextMediaType: nil,
|
playlistItemId: "playlistItem0",
|
||||||
playlistItemId: "playlistItem0",
|
nowPlayingQueue: nil)
|
||||||
nowPlayingQueue: nil)
|
|
||||||
|
|
||||||
PlaystateAPI.reportPlaybackStopped(playbackStopInfo: stopInfo)
|
PlaystateAPI.reportPlaybackStopped(reportPlaybackStoppedRequest: reportPlaybackStoppedRequest)
|
||||||
.sink { completion in
|
.sink { completion in
|
||||||
self.handleAPIRequestError(completion: completion)
|
self.handleAPIRequestError(completion: completion)
|
||||||
} receiveValue: { _ in
|
} receiveValue: { _ in
|
||||||
|
|
|
@ -46,9 +46,9 @@ struct LandscapeItemElement: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
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),
|
.getBackdropImage(maxWidth: 445),
|
||||||
blurHash: item.type == "Episode" ? item.getSeriesBackdropImageBlurHash() : item.getBackdropImageBlurHash())
|
blurHash: item.type == .episode ? item.getSeriesBackdropImageBlurHash() : item.getBackdropImageBlurHash())
|
||||||
.frame(width: 445, height: 250)
|
.frame(width: 445, height: 250)
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
|
@ -97,7 +97,7 @@ struct LandscapeItemElement: View {
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.frame(width: 445)
|
.frame(width: 445)
|
||||||
} else {
|
} else {
|
||||||
Text(item.type == "Episode" ? "\(item.seriesName ?? "") • \(item.getEpisodeLocator() ?? "")" : item.name ?? "")
|
Text(item.type == .episode ? "\(item.seriesName ?? "") • \(item.getEpisodeLocator() ?? "")" : item.name ?? "")
|
||||||
.font(.callout)
|
.font(.callout)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
|
|
|
@ -21,8 +21,8 @@ struct PortraitItemElement: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
ImageView(item.type == "Episode" ? item.getSeriesPrimaryImage(maxWidth: 200) : item.getPrimaryImage(maxWidth: 200),
|
ImageView(item.type == .episode ? item.getSeriesPrimaryImage(maxWidth: 200) : item.getPrimaryImage(maxWidth: 200),
|
||||||
blurHash: item.type == "Episode" ? item.getSeriesPrimaryImageBlurHash() : item.getPrimaryImageBlurHash())
|
blurHash: item.type == .episode ? item.getSeriesPrimaryImageBlurHash() : item.getPrimaryImageBlurHash())
|
||||||
.frame(width: 200, height: 300)
|
.frame(width: 200, height: 300)
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
.shadow(radius: focused ? 10.0 : 0)
|
.shadow(radius: focused ? 10.0 : 0)
|
||||||
|
@ -58,12 +58,12 @@ struct PortraitItemElement: View {
|
||||||
.opacity(1), alignment: .topTrailing).opacity(1)
|
.opacity(1), alignment: .topTrailing).opacity(1)
|
||||||
Text(item.title)
|
Text(item.title)
|
||||||
.frame(width: 200, height: 30, alignment: .center)
|
.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")")
|
Text("\(String(item.productionYear ?? 0)) • \(item.officialRating ?? "N/A")")
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.fontWeight(.medium)
|
.fontWeight(.medium)
|
||||||
} else if item.type == "Season" {
|
} else if item.type == .season {
|
||||||
Text("\(item.name ?? "") • \(String(item.productionYear ?? 0))")
|
Text("\(item.name ?? "") • \(String(item.productionYear ?? 0))")
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct MovieLibrariesView: View {
|
||||||
} cell: { _, cell in
|
} cell: { _, cell in
|
||||||
GeometryReader { _ in
|
GeometryReader { _ in
|
||||||
if let item = cell.item {
|
if let item = cell.item {
|
||||||
if item.type != "Folder" {
|
if item.type != .folder {
|
||||||
Button {
|
Button {
|
||||||
self.movieLibrariesRouter.route(to: \.library, item)
|
self.movieLibrariesRouter.route(to: \.library, item)
|
||||||
} label: {
|
} label: {
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct TVLibrariesView: View {
|
||||||
} cell: { _, cell in
|
} cell: { _, cell in
|
||||||
GeometryReader { _ in
|
GeometryReader { _ in
|
||||||
if let item = cell.item {
|
if let item = cell.item {
|
||||||
if item.type != "Folder" {
|
if item.type != .folder {
|
||||||
Button {
|
Button {
|
||||||
self.tvLibrariesRouter.route(to: \.library, item)
|
self.tvLibrariesRouter.route(to: \.library, item)
|
||||||
} label: {
|
} label: {
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/Flight-School/AnyCodable",
|
"location" : "https://github.com/Flight-School/AnyCodable",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "11423ef0c756e8a1f6b4bb576dab9d97bc016c70",
|
"revision" : "f9fda69a7b704d46fb5123005f2f7e43dbb8a0fa",
|
||||||
"version" : "0.6.4"
|
"version" : "0.6.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -32,8 +32,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/CombineCommunity/CombineExt",
|
"location" : "https://github.com/CombineCommunity/CombineExt",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "0880829102152185190064fd17847a7c681d2127",
|
"revision" : "38a4d4cb01f8c7750671c786d33dfbea00cbd131",
|
||||||
"version" : "1.5.1"
|
"version" : "1.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -50,8 +50,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/sindresorhus/Defaults",
|
"location" : "https://github.com/sindresorhus/Defaults",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "119f654d44f7b90f00dc11f7dd1c94a36f12576b",
|
"revision" : "981ccb0a01c54abbe3c12ccb8226108527bbf115",
|
||||||
"version" : "6.2.1"
|
"version" : "6.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -78,16 +78,16 @@
|
||||||
"location" : "https://github.com/jellyfin/jellyfin-sdk-swift",
|
"location" : "https://github.com/jellyfin/jellyfin-sdk-swift",
|
||||||
"state" : {
|
"state" : {
|
||||||
"branch" : "main",
|
"branch" : "main",
|
||||||
"revision" : "f315671ced976a7ec75ce6a1f37e00b4880cbf4b"
|
"revision" : "9d6e46b94d2178116ee3546b03dfb67e19e3a93a"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identity" : "nuke",
|
"identity" : "nuke",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/kean/Nuke.git",
|
"location" : "https://github.com/kean/Nuke",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "0ea7545b5c918285aacc044dc75048625c8257cc",
|
"revision" : "a002b7fd786f2df2ed4333fe73a9727499fd9d97",
|
||||||
"version" : "10.8.0"
|
"version" : "10.11.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -95,8 +95,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/kean/NukeUI",
|
"location" : "https://github.com/kean/NukeUI",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "17f26c07e6b1d3b9258287f99f528111fcd7b7ad",
|
"revision" : "ebfed3c9a4e97e310b0ff8ee0fffe5579887a825",
|
||||||
"version" : "0.8.1"
|
"version" : "0.8.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -122,8 +122,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/rundfunk47/stinsen",
|
"location" : "https://github.com/rundfunk47/stinsen",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "36d97964075dc770046ddef9346a29bfa8982d6d",
|
"revision" : "add05384b65ae3e39474f51ab5b9281abd238c60",
|
||||||
"version" : "2.0.7"
|
"version" : "2.0.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
"location" : "https://github.com/spacenation/swiftui-sliders",
|
"location" : "https://github.com/spacenation/swiftui-sliders",
|
||||||
"state" : {
|
"state" : {
|
||||||
"branch" : "master",
|
"branch" : "master",
|
||||||
"revision" : "538e16b35ad7a066a8f5624da9ecee6327886bf7"
|
"revision" : "5ba8614462a7ed4bd47a93fbca6c281599f74337"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,7 +32,7 @@ struct NextUpWidgetProvider: TimelineProvider {
|
||||||
let savedUser = currentLogin.user
|
let savedUser = currentLogin.user
|
||||||
var tempCancellables = Set<AnyCancellable>()
|
var tempCancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
JellyfinAPI.basePath = server.currentURI
|
JellyfinAPIAPI.basePath = server.currentURI
|
||||||
TvShowsAPI.getNextUp(userId: savedUser.id, limit: 3,
|
TvShowsAPI.getNextUp(userId: savedUser.id, limit: 3,
|
||||||
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
||||||
imageTypeLimit: 1, enableImageTypes: [.primary, .backdrop, .thumb])
|
imageTypeLimit: 1, enableImageTypes: [.primary, .backdrop, .thumb])
|
||||||
|
@ -77,7 +77,7 @@ struct NextUpWidgetProvider: TimelineProvider {
|
||||||
|
|
||||||
var tempCancellables = Set<AnyCancellable>()
|
var tempCancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
JellyfinAPI.basePath = server.currentURI
|
JellyfinAPIAPI.basePath = server.currentURI
|
||||||
TvShowsAPI.getNextUp(userId: savedUser.id, limit: 3,
|
TvShowsAPI.getNextUp(userId: savedUser.id, limit: 3,
|
||||||
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
||||||
imageTypeLimit: 1, enableImageTypes: [.primary, .backdrop, .thumb])
|
imageTypeLimit: 1, enableImageTypes: [.primary, .backdrop, .thumb])
|
||||||
|
|
Loading…
Reference in New Issue