mirror of https://github.com/oxen-io/session-ios
commit
38fc71f54a
@ -0,0 +1,83 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
import WebRTC
|
||||
import Foundation
|
||||
|
||||
// MARK: RemoteVideoView
|
||||
|
||||
class RemoteVideoView: RTCMTLVideoView {
|
||||
|
||||
override func renderFrame(_ frame: RTCVideoFrame?) {
|
||||
super.renderFrame(frame)
|
||||
guard let frame = frame else { return }
|
||||
DispatchMainThreadSafe {
|
||||
let frameRatio = Double(frame.height) / Double(frame.width)
|
||||
let frameRotation = frame.rotation
|
||||
let deviceRotation = UIDevice.current.orientation
|
||||
var rotationOverride: RTCVideoRotation? = nil
|
||||
switch deviceRotation {
|
||||
case .portrait, .portraitUpsideDown:
|
||||
// We don't have to do anything, the renderer will automatically make sure it's right-side-up.
|
||||
break
|
||||
case .landscapeLeft:
|
||||
switch frameRotation {
|
||||
case RTCVideoRotation._0: rotationOverride = RTCVideoRotation._90 // Landscape left
|
||||
case RTCVideoRotation._90: rotationOverride = RTCVideoRotation._180 // Portrait
|
||||
case RTCVideoRotation._180: rotationOverride = RTCVideoRotation._270 // Landscape right
|
||||
case RTCVideoRotation._270: rotationOverride = RTCVideoRotation._0 // Portrait upside-down
|
||||
default: break
|
||||
}
|
||||
case .landscapeRight:
|
||||
switch frameRotation {
|
||||
case RTCVideoRotation._0: rotationOverride = RTCVideoRotation._270 // Landscape left
|
||||
case RTCVideoRotation._90: rotationOverride = RTCVideoRotation._0 // Portrait
|
||||
case RTCVideoRotation._180: rotationOverride = RTCVideoRotation._90 // Landscape right
|
||||
case RTCVideoRotation._270: rotationOverride = RTCVideoRotation._180 // Portrait upside-down
|
||||
default: break
|
||||
}
|
||||
default:
|
||||
// Do nothing if we're face down, up, etc.
|
||||
// Assume we're already setup for the correct orientation.
|
||||
break
|
||||
}
|
||||
|
||||
if let rotationOverride = rotationOverride {
|
||||
self.rotationOverride = NSNumber(value: rotationOverride.rawValue)
|
||||
if [ RTCVideoRotation._0, RTCVideoRotation._180 ].contains(rotationOverride) {
|
||||
self.videoContentMode = .scaleAspectFill
|
||||
} else {
|
||||
self.videoContentMode = .scaleAspectFit
|
||||
}
|
||||
} else {
|
||||
self.rotationOverride = nil
|
||||
if [ RTCVideoRotation._0, RTCVideoRotation._180 ].contains(frameRotation) {
|
||||
self.videoContentMode = .scaleAspectFill
|
||||
} else {
|
||||
self.videoContentMode = .scaleAspectFit
|
||||
}
|
||||
}
|
||||
// if not a mobile ratio, always use .scaleAspectFit
|
||||
if frameRatio < 1.5 {
|
||||
self.videoContentMode = .scaleAspectFit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: LocalVideoView
|
||||
|
||||
class LocalVideoView: RTCMTLVideoView {
|
||||
|
||||
static let width: CGFloat = 80
|
||||
static let height: CGFloat = 173
|
||||
|
||||
override func renderFrame(_ frame: RTCVideoFrame?) {
|
||||
super.renderFrame(frame)
|
||||
DispatchMainThreadSafe {
|
||||
// This is a workaround for a weird issue that
|
||||
// sometimes the rotationOverride is not working
|
||||
// if it is only set once on initialization
|
||||
self.rotationOverride = NSNumber(value: RTCVideoRotation._0.rawValue)
|
||||
self.videoContentMode = .scaleAspectFill
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
extension UIView {
|
||||
|
||||
func makeViewDraggable() {
|
||||
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
|
||||
addGestureRecognizer(panGestureRecognizer)
|
||||
}
|
||||
|
||||
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
|
||||
let location = gesture.location(in: self.superview!)
|
||||
if let draggedView = gesture.view {
|
||||
draggedView.center = location
|
||||
if gesture.state == .ended {
|
||||
if draggedView.frame.midX >= self.superview!.layer.frame.width / 2 {
|
||||
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
|
||||
draggedView.center.x = self.superview!.layer.frame.width - draggedView.width() / 2
|
||||
}, completion: nil)
|
||||
}else{
|
||||
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
|
||||
draggedView.center.x = draggedView.width() / 2
|
||||
}, completion: nil)
|
||||
}
|
||||
let topMargin = UIApplication.shared.keyWindow!.safeAreaInsets.top + Values.veryLargeSpacing
|
||||
if draggedView.frame.minY <= topMargin {
|
||||
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
|
||||
draggedView.center.y = topMargin + draggedView.height() / 2
|
||||
}, completion: nil)
|
||||
}
|
||||
let bottomMargin = UIApplication.shared.keyWindow!.safeAreaInsets.bottom
|
||||
if draggedView.frame.maxY >= self.superview!.layer.frame.height {
|
||||
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
|
||||
draggedView.center.y = self.superview!.layer.frame.height - draggedView.height() / 2 - bottomMargin
|
||||
}, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue