Luminate/Sources/LuminatePlayer/PlayerView.swift

89 lines
2.6 KiB
Swift

import Foundation
import Adwaita
import LuminateCore
public struct PlayerView: View {
public var item: Components.Schemas.BaseItemDto
public var client: JellyfinClient
public var userId: String
public var mediaSourceId: String
public var playSessionId: String
public var streamURL: URL
@State private var isPlaying = true
@State private var position: Double = 0
@State private var duration: Double = 0
@State private var showControls = true
public var onClose: () -> Void
public init(
item: Components.Schemas.BaseItemDto,
client: JellyfinClient,
userId: String,
mediaSourceId: String,
playSessionId: String,
streamURL: URL,
onClose: @escaping () -> Void
) {
self.item = item
self.client = client
self.userId = userId
self.mediaSourceId = mediaSourceId
self.playSessionId = playSessionId
self.streamURL = streamURL
self.onClose = onClose
}
public var view: Body {
VStack {
VideoPlayerWidget(
url: streamURL.absoluteString,
isPlaying: $isPlaying,
position: $position,
duration: $duration
)
.hexpand(true)
.vexpand(true)
if showControls {
PlayerControls(
isPlaying: $isPlaying,
position: $position,
duration: $duration,
onTogglePlay: { isPlaying.toggle() },
onSeekBack: { position = max(0, position - 10) },
onSeekForward: { position = min(duration, position + 10) },
onFullscreen: { },
onClose: {
stopPlayback()
onClose()
}
)
}
}
}
private func startPlayback() {
Task {
try? await client.reportPlaybackStart(
info: .init(
ItemId: item.Id,
MediaSourceId: mediaSourceId,
PlaySessionId: playSessionId
)
)
}
}
private func stopPlayback() {
Task {
try? await client.reportPlaybackStopped(
info: .init(
ItemId: item.Id,
MediaSourceId: mediaSourceId,
PositionTicks: Int64(position * 10_000_000),
PlaySessionId: playSessionId
)
)
}
}
}