Skip to content

Commit

Permalink
Glia iOS Widgets Release 0.6.3 (#221)
Browse files Browse the repository at this point in the history
* The video is not correctly shown in landscape mode (#218) (#220)
* Upgrade to two-way video from chat should not have "By default your video will be off" note. (#219)
* Toggle video on by default for 2 way video call
* bump versions to 0.6.3 (#222)
  • Loading branch information
kuldar-daniel authored Jan 27, 2022
1 parent 6c7f597 commit 5a1e7e7
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 56 deletions.
2 changes: 1 addition & 1 deletion GliaWidgets/Coordinator/RootCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class RootCoordinator: SubFlowCoordinator, FlowCoordinator {
case .audioCall, .videoCall:
let kind: CallKind = engagementKind == .audioCall
? .audio
: .video
: .video(direction: .twoWay)

let mediaType: MediaType = engagementKind == .audioCall
? .audio
Expand Down
2 changes: 1 addition & 1 deletion GliaWidgets/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>0.6.2</string>
<string>0.6.3</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
Expand Down
143 changes: 105 additions & 38 deletions GliaWidgets/View/Call/CallView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ class CallView: EngagementView {
private var hideBarsWorkItem: DispatchWorkItem?
private var headerTopConstraint: NSLayoutConstraint!
private var buttonBarBottomConstraint: NSLayoutConstraint!
private var localVideoViewTopConstraint: NSLayoutConstraint!
private var localVideoViewRightConstraint: NSLayoutConstraint!
private var localVideoViewHeightConstraint: NSLayoutConstraint!
private var remoteVideoViewHeightConstraint: NSLayoutConstraint!
private let kLocalVideoViewDefaultHeight: CGFloat = 186
private let kRemoteVideoViewPortraitHeightMultiplier: CGFloat = 0.3
private let kRemoteVideoViewLandscapeHeightMultiplier: CGFloat = 1.0
private var remoteVideoViewWidthConstraint: NSLayoutConstraint!
private let kBarsHideDelay: TimeInterval = 3.2
private var localVideoBounds: CGRect {
let x = safeAreaInsets.left + 10
let y = header.frame.maxY + 10
let width = frame.width - safeAreaInsets.left - safeAreaInsets.right - 2 * 10
let height = buttonBar.frame.minY - header.frame.maxY - 2 * 10

return CGRect(x: x, y: y, width: width, height: height)
}

init(with style: CallStyle) {
self.style = style
Expand All @@ -43,6 +46,7 @@ class CallView: EngagementView {
override func layoutSubviews() {
super.layoutSubviews()
adjustForCurrentOrientation()
adjustLocalVideoFrameAfterLayout()
}

func switchTo(_ mode: Mode) {
Expand Down Expand Up @@ -84,11 +88,17 @@ class CallView: EngagementView {
} else {
showBars(duration: duration)
}

buttonBar.adjustStackConstraints()
}

func didRotate() {
adjustLocalVideoFrameAfterOrientationChange()
}

func checkBarsOrientation() {
guard mode == .video else { return }

if currentOrientation.isLandscape {
hideLandscapeBarsAfterDelay()
} else {
Expand Down Expand Up @@ -132,6 +142,14 @@ class CallView: EngagementView {
action: #selector(tap)
)
addGestureRecognizer(tapRecognizer)

localVideoView.show = { [weak self] in
self?.setLocalVideoFrame(isVisible: $0)
}

localVideoView.pan = { [weak self] in
self?.adjustLocalVideoFrameAfterPanGesture(translation: $0)
}
}

private func layout() {
Expand All @@ -142,18 +160,9 @@ class CallView: EngagementView {

addSubview(remoteVideoView)
remoteVideoView.autoAlignAxis(toSuperviewAxis: .horizontal)
remoteVideoView.autoPinEdge(toSuperviewEdge: .left)
remoteVideoView.autoPinEdge(toSuperviewEdge: .right)
remoteVideoView.autoAlignAxis(toSuperviewAxis: .vertical)
remoteVideoViewHeightConstraint = remoteVideoView.autoSetDimension(.height, toSize: 0)

addSubview(localVideoView)
localVideoViewTopConstraint = localVideoView.autoPinEdge(toSuperviewEdge: .top)
localVideoViewRightConstraint = localVideoView.autoPinEdge(toSuperviewEdge: .right)
localVideoViewHeightConstraint = localVideoView.autoSetDimension(
.height,
toSize: kLocalVideoViewDefaultHeight
)
localVideoView.autoMatch(.width, to: .height, of: localVideoView, withMultiplier: 0.7)
remoteVideoViewWidthConstraint = remoteVideoView.autoSetDimension(.width, toSize: 0)

addSubview(header)
headerTopConstraint = header.autoPinEdge(toSuperviewEdge: .top)
Expand Down Expand Up @@ -183,6 +192,8 @@ class CallView: EngagementView {
bottomLabel.autoMatch(.width, to: .width, of: self, withMultiplier: 0.6)
bottomLabel.autoAlignAxis(toSuperviewAxis: .vertical)

addSubview(localVideoView)

adjustForCurrentOrientation()
switchTo(mode)
}
Expand All @@ -207,30 +218,11 @@ class CallView: EngagementView {

private func adjustVideoViews() {
adjustRemoteVideoView()
adjustLocalVideoView()
}

private func adjustRemoteVideoView() {
let multiplier = currentOrientation.isLandscape
? kRemoteVideoViewLandscapeHeightMultiplier
: kRemoteVideoViewPortraitHeightMultiplier
remoteVideoViewHeightConstraint.constant = frame.size.height * multiplier
}

private func adjustLocalVideoView() {
if currentOrientation.isLandscape {
localVideoViewTopConstraint.constant = 20
localVideoViewRightConstraint.constant = -20
} else {
let kTopInset: CGFloat = 10
let kBottomInset: CGFloat = 10
let kRightInset: CGFloat = -10
let top = header.frame.maxY + kTopInset
let height = remoteVideoView.frame.minY - header.frame.maxY - (kTopInset + kBottomInset)
localVideoViewHeightConstraint.constant = height > 0 ? height : 0
localVideoViewTopConstraint.constant = top
localVideoViewRightConstraint.constant = kRightInset
}
remoteVideoViewHeightConstraint.constant = frame.size.height
remoteVideoViewWidthConstraint.constant = frame.size.width
}

private func showBars(duration: TimeInterval) {
Expand Down Expand Up @@ -275,3 +267,78 @@ class CallView: EngagementView {
}
}
}

// MARK: Local Video

extension CallView {
private func setLocalVideoFrame(isVisible: Bool) {
if isVisible {
let screenSize: CGRect = UIScreen.main.bounds

let size = CGSize(
width: screenSize.width * 0.3,
height: screenSize.height * 0.3
)

localVideoView.frame = CGRect(
origin: CGPoint(
x: localVideoBounds.maxX - size.width,
y: localVideoBounds.maxY - size.height
),
size: size
)
}
}

private func adjustLocalVideoFrameAfterOrientationChange() {
let screenSize: CGRect = UIScreen.main.bounds

let size = CGSize(
width: screenSize.width * 0.3,
height: screenSize.height * 0.3
)

localVideoView.frame = CGRect(
origin: CGPoint(
x: localVideoBounds.maxX - size.width,
y: localVideoBounds.maxY - size.height
),
size: size
)
}

private func adjustLocalVideoFrameAfterPanGesture(translation: CGPoint) {
var frame = localVideoView.frame

frame.origin.x += translation.x
frame.origin.y += translation.y

localVideoView.frame = frame

if localVideoBounds.contains(frame) {
localVideoView.frame = frame
}
}

private func adjustLocalVideoFrameAfterLayout() {
var frame: CGRect = localVideoView.frame

if localVideoView.frame.minX < localVideoBounds.minX {
frame.origin.x = localVideoBounds.minX
}

if localVideoView.frame.minY < localVideoBounds.minY {
frame.origin.y = localVideoBounds.minY
}

if localVideoView.frame.maxX > localVideoBounds.maxX {
frame.origin.x = localVideoBounds.maxX - localVideoView.frame.width
}

if localVideoView.frame.maxY > localVideoBounds.maxY {
frame.origin.y = localVideoBounds.maxY - localVideoView.frame.height
}

localVideoView.frame = frame
}
}
34 changes: 30 additions & 4 deletions GliaWidgets/View/Call/Video/VideoStreamView.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import UIKit
import SalemoveSDK

class VideoStreamView: View {
class VideoStreamView: UIView {
enum Kind {
case local
case remote
}

var pan: ((CGPoint) -> Void)?
var show: ((Bool) -> Void)?

weak var streamView: StreamView? {
didSet {
replace(oldStreamView: oldValue, with: streamView)
Expand All @@ -17,24 +20,47 @@ class VideoStreamView: View {

init(_ kind: Kind) {
self.kind = kind
super.init()

super.init(frame: .zero)

setup()
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func setup() {
clipsToBounds = true
layer.cornerRadius = kind == .local ? 6.0 : 0.0

let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(pan(_:)))
addGestureRecognizer(panRecognizer)
}

private func replace(
oldStreamView: StreamView?,
with streamView: StreamView?
) {
oldStreamView?.removeFromSuperview()
guard let streamView = streamView else { return }
streamView.scale = .aspectFill
guard let streamView = streamView else {
show?(false)
return
}
streamView.scale = kind == .remote ? .aspectFit : .aspectFill
addSubview(streamView)
streamView.autoPinEdgesToSuperviewEdges()
streamView.layoutIfNeeded()
show?(true)
}

@objc
private func pan(_ gesture: UIPanGestureRecognizer) {
guard gesture.view != nil else { return }

let translation = gesture.translation(in: self)
pan?(translation)
gesture.setTranslation(.zero, in: self)
}
}
19 changes: 19 additions & 0 deletions GliaWidgets/ViewController/Call/CallViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,29 @@ class CallViewController: EngagementViewController, MediaUpgradePresenter {
super.init(viewModel: viewModel, viewFactory: viewFactory)
}

deinit {
NotificationCenter.default.removeObserver(self)
}

override public func loadView() {
super.loadView()

let view = viewFactory.makeCallView()
self.view = view

bind(viewModel: viewModel, to: view)
}

override func viewDidLoad() {
super.viewDidLoad()

viewModel.event(.viewDidLoad)

NotificationCenter.default.addObserver(
self,
selector: #selector(CallViewController.deviceDidRotate),
name: UIDevice.orientationDidChangeNotification, object: nil
)
}

override var preferredStatusBarStyle: UIStatusBarStyle { return viewFactory.theme.call.preferredStatusBarStyle }
Expand All @@ -33,6 +46,12 @@ class CallViewController: EngagementViewController, MediaUpgradePresenter {
view.checkBarsOrientation()
}

@objc
private func deviceDidRotate() {
guard let view = view as? CallView else { return }
view.didRotate()
}

private func bind(viewModel: CallViewModel, to view: CallView) {
view.header.showBackButton()
view.header.showCloseButton()
Expand Down
32 changes: 27 additions & 5 deletions GliaWidgets/ViewModel/Call/CallViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,15 @@ class CallViewModel: EngagementViewModel, ViewModel {
case .audio:
action?(.setTitle(Strings.Audio.title))
action?(.setTopTextHidden(true))
case .video:
case .video(let direction):
switch direction {
case .oneWay:
action?(.setTopTextHidden(false))

default:
action?(.setTopTextHidden(true))
}

action?(.setTitle(Strings.Video.title))
}
updateButtons()
Expand All @@ -170,8 +178,15 @@ class CallViewModel: EngagementViewModel, ViewModel {
switch call.kind.value {
case .audio:
action?(.setTopTextHidden(true))
case .video:
action?(.setTopTextHidden(false))

case .video(let direction):
switch direction {
case .oneWay:
action?(.setTopTextHidden(false))

default:
action?(.setTopTextHidden(true))
}
}
}

Expand All @@ -194,8 +209,15 @@ class CallViewModel: EngagementViewModel, ViewModel {
imageUrl: interactor.engagedOperator?.picture?.url
)
)
case .video:
break

case .video(let direction):
switch direction {
case .twoWay:
toggleVideo()

default:
break
}
}
}

Expand Down
Loading

0 comments on commit 5a1e7e7

Please sign in to comment.