video: switch player to use new view model
pass VideoController through containing views Closes: https://github.com/damus-io/damus/pull/1539 Reviewed-by: William Casarin <jb55@jb55.com> Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
William Casarin
parent
f1f3abfb98
commit
3569da5687
@@ -17,79 +17,85 @@ func globalCoordinate(localX x: CGFloat, localY y: CGFloat,
|
||||
}
|
||||
|
||||
struct DamusVideoPlayer: View {
|
||||
var url: URL
|
||||
@ObservedObject var model: VideoPlayerModel
|
||||
@Binding var video_size: CGSize?
|
||||
let url: URL
|
||||
@StateObject var model: DamusVideoPlayerViewModel
|
||||
@EnvironmentObject private var orientationTracker: OrientationTracker
|
||||
|
||||
var mute_icon: String {
|
||||
if model.has_audio == false || model.muted {
|
||||
return "speaker.slash"
|
||||
} else {
|
||||
return "speaker"
|
||||
}
|
||||
}
|
||||
|
||||
var mute_icon_color: Color {
|
||||
switch self.model.has_audio {
|
||||
case .none:
|
||||
return .white
|
||||
case .some(let has_audio):
|
||||
return has_audio ? .white : .red
|
||||
}
|
||||
}
|
||||
|
||||
var MuteIcon: some View {
|
||||
ZStack {
|
||||
Circle()
|
||||
.opacity(0.2)
|
||||
.frame(width: 32, height: 32)
|
||||
.foregroundColor(.black)
|
||||
|
||||
Image(systemName: mute_icon)
|
||||
.padding()
|
||||
.foregroundColor(mute_icon_color)
|
||||
}
|
||||
init(url: URL, video_size: Binding<CGSize?>, controller: VideoController) {
|
||||
self.url = url
|
||||
_model = StateObject(wrappedValue: DamusVideoPlayerViewModel(url: url, video_size: video_size, controller: controller))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geo in
|
||||
let localFrame = geo.frame(in: .local)
|
||||
let centerY = globalCoordinate(localX: 0, localY: localFrame.midY, localGeometry: geo).y
|
||||
let delta = localFrame.height / 2
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
VideoPlayer(url: url, model: model)
|
||||
if model.has_audio == true {
|
||||
MuteIcon
|
||||
.zIndex(11.0)
|
||||
.onTapGesture {
|
||||
self.model.muted = !self.model.muted
|
||||
}
|
||||
ZStack {
|
||||
AVPlayerView(player: model.player)
|
||||
|
||||
if model.is_loading {
|
||||
ProgressView()
|
||||
.progressViewStyle(.circular)
|
||||
.tint(.white)
|
||||
.scaleEffect(CGSize(width: 1.5, height: 1.5))
|
||||
}
|
||||
}
|
||||
.onChange(of: model.size) { size in
|
||||
guard let size else {
|
||||
return
|
||||
|
||||
if model.has_audio {
|
||||
mute_button
|
||||
}
|
||||
video_size = size
|
||||
}
|
||||
.onChange(of: centerY) { _ in
|
||||
/// pause video when it is scrolled beyond visible range
|
||||
let isBelowTop = centerY + delta > 100, /// 100 =~ approx. bottom (y) of ContentView's TabView
|
||||
isAboveBottom = centerY - delta < orientationTracker.deviceMajorAxis
|
||||
if isBelowTop && isAboveBottom {
|
||||
model.start()
|
||||
} else {
|
||||
model.stop()
|
||||
update_is_visible(centerY: centerY)
|
||||
}
|
||||
.onAppear {
|
||||
update_is_visible(centerY: centerY)
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
model.view_did_disappear()
|
||||
}
|
||||
}
|
||||
|
||||
private func update_is_visible(centerY: CGFloat) {
|
||||
let isBelowTop = centerY > 100, /// 100 =~ approx. bottom (y) of ContentView's TabView
|
||||
isAboveBottom = centerY < orientationTracker.deviceMajorAxis
|
||||
model.set_view_is_visible(isBelowTop && isAboveBottom)
|
||||
}
|
||||
|
||||
private var mute_icon: String {
|
||||
!model.has_audio || model.is_muted ? "speaker.slash" : "speaker"
|
||||
}
|
||||
|
||||
private var mute_icon_color: Color {
|
||||
model.has_audio ? .white : .red
|
||||
}
|
||||
|
||||
private var mute_button: some View {
|
||||
HStack {
|
||||
Spacer()
|
||||
VStack {
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
model.did_tap_mute_button()
|
||||
} label: {
|
||||
ZStack {
|
||||
Circle()
|
||||
.opacity(0.2)
|
||||
.frame(width: 32, height: 32)
|
||||
.foregroundColor(.black)
|
||||
|
||||
Image(systemName: mute_icon)
|
||||
.padding()
|
||||
.foregroundColor(mute_icon_color)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
struct DamusVideoPlayer_Previews: PreviewProvider {
|
||||
@StateObject static var model: VideoPlayerModel = VideoPlayerModel()
|
||||
|
||||
static var previews: some View {
|
||||
DamusVideoPlayer(url: URL(string: "http://cdn.jb55.com/s/zaps-build.mp4")!, model: model, video_size: .constant(nil))
|
||||
DamusVideoPlayer(url: URL(string: "http://cdn.jb55.com/s/zaps-build.mp4")!, video_size: .constant(nil), controller: VideoController())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user