videos: improve precision & sensitivity of auto-pause mechanism
Closes: https://github.com/damus-io/damus/pull/1308 Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
William Casarin
parent
c5d8e4a4a1
commit
5caa4a6e97
@@ -7,10 +7,20 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
/// get coordinates in Global reference frame given a Local point & geometry
|
||||||
|
func globalCoordinate(localX x: CGFloat, localY y: CGFloat,
|
||||||
|
localGeometry geo: GeometryProxy) -> CGPoint {
|
||||||
|
let localPoint = CGPoint(x: x, y: y)
|
||||||
|
return geo.frame(in: .global).origin.applying(
|
||||||
|
.init(translationX: localPoint.x, y: localPoint.y)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
struct DamusVideoPlayer: View {
|
struct DamusVideoPlayer: View {
|
||||||
var url: URL
|
var url: URL
|
||||||
@ObservedObject var model: VideoPlayerModel
|
@ObservedObject var model: VideoPlayerModel
|
||||||
@Binding var video_size: CGSize?
|
@Binding var video_size: CGSize?
|
||||||
|
@EnvironmentObject private var orientationTracker: OrientationTracker
|
||||||
|
|
||||||
var mute_icon: String {
|
var mute_icon: String {
|
||||||
if model.has_audio == false || model.muted {
|
if model.has_audio == false || model.muted {
|
||||||
@@ -45,10 +55,8 @@ struct DamusVideoPlayer: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
let localFrame = geo.frame(in: .local)
|
let localFrame = geo.frame(in: .local)
|
||||||
let localCenter = CGPoint(x: localFrame.midX, y: localFrame.midY)
|
let centerY = globalCoordinate(localX: 0, localY: localFrame.midY, localGeometry: geo).y
|
||||||
let globalCenter = geo.frame(in: .global).origin.applying(.init(translationX: localCenter.x, y: localCenter.y))
|
let delta = localFrame.height / 2
|
||||||
let centerY = globalCenter.y
|
|
||||||
|
|
||||||
ZStack(alignment: .bottomTrailing) {
|
ZStack(alignment: .bottomTrailing) {
|
||||||
VideoPlayer(url: url, model: model)
|
VideoPlayer(url: url, model: model)
|
||||||
if model.has_audio == true {
|
if model.has_audio == true {
|
||||||
@@ -66,10 +74,14 @@ struct DamusVideoPlayer: View {
|
|||||||
video_size = size
|
video_size = size
|
||||||
}
|
}
|
||||||
.onChange(of: centerY) { _ in
|
.onChange(of: centerY) { _ in
|
||||||
let screenHeight = UIScreen.main.bounds.height
|
/// pause video when it is scrolled beyond visible range
|
||||||
let screenMidY = screenHeight / 2
|
let isBelowTop = centerY + delta > 100, /// 100 =~ approx. bottom (y) of ContentView's TabView
|
||||||
let tol = 0.20 * screenHeight /// tolerance - can vary to taste ie., % of screen height of a centered box in which video plays
|
isAboveBottom = centerY - delta < orientationTracker.deviceMajorAxis
|
||||||
model.play = centerY > screenMidY - tol && centerY < screenMidY + tol /// video plays when inside tolerance box
|
if isBelowTop && isAboveBottom {
|
||||||
|
model.start()
|
||||||
|
} else {
|
||||||
|
model.stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ struct damusApp: App {
|
|||||||
struct MainView: View {
|
struct MainView: View {
|
||||||
@State var needs_setup = false;
|
@State var needs_setup = false;
|
||||||
@State var keypair: Keypair? = nil;
|
@State var keypair: Keypair? = nil;
|
||||||
|
@StateObject private var orientationTracker = OrientationTracker()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if let kp = keypair, !needs_setup {
|
if let kp = keypair, !needs_setup {
|
||||||
ContentView(keypair: kp)
|
ContentView(keypair: kp)
|
||||||
|
.environmentObject(orientationTracker)
|
||||||
} else {
|
} else {
|
||||||
SetupView()
|
SetupView()
|
||||||
.onReceive(handle_notify(.login)) { notif in
|
.onReceive(handle_notify(.login)) { notif in
|
||||||
@@ -38,7 +40,11 @@ struct MainView: View {
|
|||||||
try? clear_keypair()
|
try? clear_keypair()
|
||||||
keypair = nil
|
keypair = nil
|
||||||
}
|
}
|
||||||
|
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
|
||||||
|
orientationTracker.setDeviceMajorAxis()
|
||||||
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
orientationTracker.setDeviceMajorAxis()
|
||||||
keypair = get_saved_keypair()
|
keypair = get_saved_keypair()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,3 +71,14 @@ class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDele
|
|||||||
completionHandler()
|
completionHandler()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class OrientationTracker: ObservableObject {
|
||||||
|
var deviceMajorAxis: CGFloat = 0
|
||||||
|
func setDeviceMajorAxis() {
|
||||||
|
let bounds = UIScreen.main.bounds
|
||||||
|
let height = max(bounds.height, bounds.width) /// device's longest dimension
|
||||||
|
let width = min(bounds.height, bounds.width) /// device's shortest dimension
|
||||||
|
let orientation = UIDevice.current.orientation
|
||||||
|
deviceMajorAxis = (orientation == .portrait || orientation == .unknown) ? height : width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user