mirror of
https://github.com/yattee/yattee.git
synced 2025-08-05 02:04:07 +00:00
Model improvements
This commit is contained in:
@@ -31,19 +31,28 @@ struct ChapterView: View {
|
||||
}
|
||||
|
||||
@ViewBuilder func smallImage(_ chapter: Chapter) -> some View {
|
||||
WebImage(url: chapter.image)
|
||||
.resizable()
|
||||
.placeholder {
|
||||
ProgressView()
|
||||
if #available(iOS 15, macOS 12, *) {
|
||||
AsyncImage(url: chapter.image) { image in
|
||||
image
|
||||
.resizable()
|
||||
} placeholder: {
|
||||
Rectangle().foregroundColor(Color("PlaceholderColor"))
|
||||
}
|
||||
.indicator(.activity)
|
||||
#if os(tvOS)
|
||||
.frame(width: thumbnailWidth, height: 140)
|
||||
.mask(RoundedRectangle(cornerRadius: 12))
|
||||
#else
|
||||
.frame(width: thumbnailWidth, height: 60)
|
||||
.mask(RoundedRectangle(cornerRadius: 6))
|
||||
#endif
|
||||
} else {
|
||||
WebImage(url: chapter.image)
|
||||
.resizable()
|
||||
.placeholder {
|
||||
ProgressView()
|
||||
}
|
||||
.indicator(.activity)
|
||||
#if os(tvOS)
|
||||
.frame(width: thumbnailWidth, height: 140)
|
||||
.mask(RoundedRectangle(cornerRadius: 12))
|
||||
#else
|
||||
.frame(width: thumbnailWidth, height: 60)
|
||||
.mask(RoundedRectangle(cornerRadius: 6))
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private var thumbnailWidth: Double {
|
||||
|
@@ -72,7 +72,7 @@ struct PlayerControls: View {
|
||||
}
|
||||
.offset(y: playerControlsLayout.osdVerticalOffset + 5)
|
||||
|
||||
if model.presentingControls, !model.presentingOverlays {
|
||||
Section {
|
||||
#if !os(tvOS)
|
||||
HStack {
|
||||
seekBackwardButton
|
||||
@@ -160,7 +160,8 @@ struct PlayerControls: View {
|
||||
.offset(y: -playerControlsLayout.timelineHeight - 5)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}.opacity(model.presentingControls && !model.presentingOverlays ? 1 : 0)
|
||||
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
@@ -219,14 +220,23 @@ struct PlayerControls: View {
|
||||
let video = item.video,
|
||||
let url = thumbnails.best(video)
|
||||
{
|
||||
WebImage(url: url)
|
||||
.resizable()
|
||||
.placeholder {
|
||||
Rectangle().fill(Color("PlaceholderColor"))
|
||||
if #available(iOS 15, macOS 12, *) {
|
||||
AsyncImage(url: url) { image in
|
||||
image
|
||||
.resizable()
|
||||
} placeholder: {
|
||||
Rectangle().foregroundColor(Color("PlaceholderColor"))
|
||||
}
|
||||
.retryOnAppear(true)
|
||||
.indicator(.activity)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
} else {
|
||||
WebImage(url: url)
|
||||
.resizable()
|
||||
.placeholder {
|
||||
Rectangle().fill(Color("PlaceholderColor"))
|
||||
}
|
||||
.retryOnAppear(true)
|
||||
.indicator(.activity)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -60,7 +60,7 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
||||
case .veryLarge:
|
||||
return 40
|
||||
case .large:
|
||||
return 30
|
||||
return 25
|
||||
case .medium:
|
||||
return 25
|
||||
case .small:
|
||||
|
@@ -44,9 +44,10 @@ struct TimelineView: View {
|
||||
@Environment(\.verticalSizeClass) private var verticalSizeClass
|
||||
#endif
|
||||
|
||||
@ObservedObject private var playerTime = PlayerTimeModel.shared
|
||||
|
||||
@EnvironmentObject<PlayerModel> private var player
|
||||
@EnvironmentObject<PlayerControlsModel> private var controls
|
||||
@EnvironmentObject<PlayerTimeModel> private var playerTime
|
||||
|
||||
@Default(.playerControlsLayout) private var regularPlayerControlsLayout
|
||||
@Default(.fullScreenPlayerControlsLayout) private var fullScreenPlayerControlsLayout
|
||||
@@ -392,7 +393,7 @@ struct TimelineView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let playerModel = PlayerModel()
|
||||
playerModel.currentItem = .init(Video.fixture)
|
||||
let playerTimeModel = PlayerTimeModel()
|
||||
let playerTimeModel = PlayerTimeModel.shared
|
||||
playerTimeModel.player = playerModel
|
||||
playerTimeModel.currentTime = .secondsInDefaultTimescale(33)
|
||||
playerTimeModel.duration = .secondsInDefaultTimescale(100)
|
||||
@@ -400,7 +401,6 @@ struct TimelineView_Previews: PreviewProvider {
|
||||
TimelineView()
|
||||
}
|
||||
.environmentObject(playerModel)
|
||||
.environmentObject(playerTimeModel)
|
||||
.environmentObject(PlayerControlsModel())
|
||||
.padding()
|
||||
}
|
||||
|
@@ -50,14 +50,20 @@ extension VideoPlayerView {
|
||||
return
|
||||
}
|
||||
|
||||
if orientation.isLandscape {
|
||||
playerControls.presentingControls = false
|
||||
player.enterFullScreen(showControls: false)
|
||||
Orientation.lockOrientation(OrientationTracker.shared.currentInterfaceOrientationMask, andRotateTo: orientation)
|
||||
} else {
|
||||
player.exitFullScreen(showControls: false)
|
||||
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait)
|
||||
orientationDebouncer.callback = {
|
||||
DispatchQueue.main.async {
|
||||
if orientation.isLandscape {
|
||||
playerControls.presentingControls = false
|
||||
player.enterFullScreen(showControls: false)
|
||||
Orientation.lockOrientation(OrientationTracker.shared.currentInterfaceOrientationMask, andRotateTo: orientation)
|
||||
} else {
|
||||
player.exitFullScreen(showControls: false)
|
||||
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
orientationDebouncer.call()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ import AVKit
|
||||
import CoreMotion
|
||||
#endif
|
||||
import Defaults
|
||||
import Repeat
|
||||
import Siesta
|
||||
import SwiftUI
|
||||
|
||||
@@ -41,6 +42,7 @@ struct VideoPlayerView: View {
|
||||
|
||||
@State internal var orientation = UIInterfaceOrientation.portrait
|
||||
@State internal var lastOrientation: UIInterfaceOrientation?
|
||||
@State internal var orientationDebouncer = Debouncer(.milliseconds(300))
|
||||
#elseif os(macOS)
|
||||
var hoverThrottle = Throttle(interval: 0.5)
|
||||
var mouseLocation: CGPoint { NSEvent.mouseLocation }
|
||||
|
Reference in New Issue
Block a user