Skip to content

Commit 60a9717

Browse files
authored
Merge pull request #612 from session-foundation/dev
Release 2.14.5
2 parents 7dc430e + 36e8d5a commit 60a9717

File tree

118 files changed

+6546
-1160
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+6546
-1160
lines changed

Session.xcodeproj/project.pbxproj

Lines changed: 77 additions & 27 deletions
Large diffs are not rendered by default.

Session.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Session/Calls/CallVC.swift

Lines changed: 95 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,13 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel
380380
UIView.animate(withDuration: 0.25) {
381381
let remoteVideoView: RemoteVideoView = self.floatingViewVideoSource == .remote ? self.floatingRemoteVideoView : self.fullScreenRemoteVideoView
382382
remoteVideoView.alpha = isEnabled ? 1 : 0
383+
384+
// Retain floating view visibility if any of the video feeds are enabled
385+
let isAnyVideoFeedEnabled: Bool = (isEnabled || self.call.isVideoEnabled)
386+
387+
// Shows floating camera to allow user to switch to fullscreen or floating
388+
// even if the other party has not yet turned on their video feed.
389+
self.floatingViewContainer.isHidden = !isAnyVideoFeedEnabled
383390
}
384391

385392
if self.callInfoLabelStackView.alpha < 0.5 {
@@ -464,9 +471,8 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel
464471
setUpViewHierarchy()
465472
setUpProfilePictureImage()
466473

467-
if shouldRestartCamera { cameraManager.prepare() }
468-
469474
_ = call.videoCapturer // Force the lazy var to instantiate
475+
470476
titleLabel.text = self.call.contactName
471477
if self.call.hasConnected {
472478
callDurationLabel.isHidden = false
@@ -659,14 +665,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel
659665
self.callInfoLabelStackView.alpha = 1
660666
}
661667

662-
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
663-
DispatchQueue.main.async {
664-
self?.dismiss(animated: true, completion: {
665-
self?.conversationVC?.becomeFirstResponder()
666-
self?.conversationVC?.showInputAccessoryView()
667-
})
668-
}
669-
}
668+
self.shouldHandleCallDismiss(delay: 2)
670669
}
671670

672671
@objc private func answerCall() {
@@ -680,21 +679,14 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel
680679
}
681680
}
682681

683-
@objc private func endCall() {
682+
@objc private func endCall(presentCameraRequestDialog: Bool = false) {
684683
dependencies[singleton: .callManager].endCall(call) { [weak self, dependencies] error in
684+
self?.shouldHandleCallDismiss(delay: 1, presentCameraRequestDialog: presentCameraRequestDialog)
685+
685686
if let _ = error {
686687
self?.call.endSessionCall()
687688
dependencies[singleton: .callManager].reportCurrentCallEnded(reason: .declinedElsewhere)
688689
}
689-
690-
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { [weak self] _ in
691-
DispatchQueue.main.async {
692-
self?.dismiss(animated: true, completion: {
693-
self?.conversationVC?.becomeFirstResponder()
694-
self?.conversationVC?.showInputAccessoryView()
695-
})
696-
}
697-
}
698690
}
699691
}
700692

@@ -721,43 +713,88 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel
721713
// MARK: - Video and Audio
722714

723715
@objc private func operateCamera() {
716+
724717
if (call.isVideoEnabled) {
725-
floatingViewContainer.isHidden = true
718+
// Hides local video feed
719+
(floatingViewVideoSource == .local
720+
? floatingLocalVideoView
721+
: fullScreenLocalVideoView).alpha = 0
722+
723+
floatingViewContainer.isHidden = !call.isRemoteVideoEnabled
724+
726725
cameraManager.stop()
727726
videoButton.themeTintColor = .textPrimary
728727
videoButton.themeBackgroundColor = .backgroundSecondary
729728
switchCameraButton.isEnabled = false
730729
call.isVideoEnabled = false
731730
}
732731
else {
733-
guard Permissions.requestCameraPermissionIfNeeded(using: dependencies) else {
734-
let confirmationModal: ConfirmationModal = ConfirmationModal(
735-
info: ConfirmationModal.Info(
736-
title: "permissionsRequired".localized(),
737-
body: .text("permissionsCameraAccessRequiredCallsIos".localized()),
738-
showCondition: .disabled,
739-
confirmTitle: "sessionSettings".localized(),
740-
onConfirm: { _ in
741-
UIApplication.shared.openSystemSettings()
742-
}
743-
)
744-
)
732+
733+
// Added delay of preview due to permission dialog alert dismissal on allow.
734+
// It causes issue on `VideoPreviewVC` presentation animation,
735+
// If camera permission is already allowed no animation delay is needed
736+
let previewDelay = Permissions.camera == .undetermined ? 0.5 : 0
737+
738+
Permissions.requestCameraPermissionIfNeeded(
739+
useCustomDeniedAlert: true,
740+
using: dependencies
741+
) { [weak self, dependencies] isAuthorized in
745742

746-
self.navigationController?.present(confirmationModal, animated: true, completion: nil)
747-
return
743+
let status = Permissions.camera
744+
745+
switch (isAuthorized, status) {
746+
case (false, .denied):
747+
guard let presentingViewController: UIViewController = (self?.navigationController ?? dependencies[singleton: .appContext].frontMostViewController)
748+
else { return }
749+
750+
DispatchQueue.main.async {
751+
let confirmationModal: ConfirmationModal = ConfirmationModal(
752+
info: ConfirmationModal.Info(
753+
title: "cameraAccessRequired".localized(),
754+
body: .attributedText(
755+
"cameraAccessDeniedMessage"
756+
.put(key: "app_name", value: Constants.app_name)
757+
.localizedFormatted(),
758+
scrollMode: .never
759+
),
760+
confirmTitle: "endCallToEnable".localized(),
761+
confirmStyle: .danger,
762+
cancelTitle: "remindMeLater".localized(),
763+
cancelStyle: .alert_text,
764+
onConfirm: { _ in
765+
self?.endCall(presentCameraRequestDialog: true)
766+
},
767+
onCancel: { modal in
768+
dependencies[defaults: .standard, key: .shouldRemindGrantingCameraPermissionForCalls] = true
769+
modal.dismiss(animated: true)
770+
}
771+
)
772+
)
773+
presentingViewController.present(confirmationModal, animated: true, completion: nil)
774+
}
775+
case (true, _):
776+
DispatchQueue.main.asyncAfter(deadline: .now() + previewDelay) { [weak self] in
777+
let previewVC = VideoPreviewVC()
778+
previewVC.delegate = self
779+
self?.present(previewVC, animated: true, completion: nil)
780+
}
781+
break
782+
default: break
783+
}
748784
}
749-
let previewVC = VideoPreviewVC()
750-
previewVC.delegate = self
751-
present(previewVC, animated: true, completion: nil)
752785
}
753786
}
754-
787+
755788
func cameraDidConfirmTurningOn() {
756789
floatingViewContainer.isHidden = false
790+
757791
let localVideoView: LocalVideoView = self.floatingViewVideoSource == .local ? self.floatingLocalVideoView : self.fullScreenLocalVideoView
758792
localVideoView.alpha = 1
793+
794+
// Camera preparation
759795
cameraManager.prepare()
760796
cameraManager.start()
797+
761798
videoButton.themeTintColor = .backgroundSecondary
762799
videoButton.themeBackgroundColor = .textPrimary
763800
switchCameraButton.isEnabled = true
@@ -874,13 +911,26 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel
874911
}
875912
}
876913

914+
private func shouldHandleCallDismiss(delay: TimeInterval, presentCameraRequestDialog: Bool = false) {
915+
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(Int(delay))) { [weak self, dependencies] in
916+
guard self?.presentingViewController != nil else { return }
917+
918+
self?.dismiss(animated: true, completion: {
919+
self?.conversationVC?.becomeFirstResponder()
920+
self?.conversationVC?.showInputAccessoryView()
921+
922+
if presentCameraRequestDialog {
923+
Permissions.showEnableCameraAccessInstructions(using: dependencies)
924+
} else {
925+
Permissions.remindCameraAccessRequirement(using: dependencies)
926+
}
927+
})
928+
}
929+
}
930+
877931
// MARK: - AVRoutePickerViewDelegate
878932

879-
func routePickerViewWillBeginPresentingRoutes(_ routePickerView: AVRoutePickerView) {
880-
881-
}
933+
func routePickerViewWillBeginPresentingRoutes(_ routePickerView: AVRoutePickerView) {}
882934

883-
func routePickerViewDidEndPresentingRoutes(_ routePickerView: AVRoutePickerView) {
884-
885-
}
935+
func routePickerViewDidEndPresentingRoutes(_ routePickerView: AVRoutePickerView) {}
886936
}

Session/Calls/Views & Modals/CallMissedTipsModal.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ final class CallMissedTipsModal: Modal {
2828
result.text = "callsMissedCallFrom"
2929
.put(key: "name", value: caller)
3030
.localized()
31+
result.accessibilityIdentifier = "Modal heading"
3132
result.themeTextColor = .textPrimary
3233
result.textAlignment = .center
3334

@@ -44,6 +45,7 @@ final class CallMissedTipsModal: Modal {
4445
result.themeAttributedText = "callsYouMissedCallPermissions"
4546
.put(key: "name", value: caller)
4647
.localizedFormatted(in: result)
48+
result.accessibilityIdentifier = "Modal description"
4749

4850
return result
4951
}()

Session/Closed Groups/EditGroupViewModel.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,10 @@ class EditGroupViewModel: SessionTableViewModel, NavigatableStateHolder, Observa
193193
),
194194
styling: SessionCell.StyleInfo(
195195
alignment: .centerHugging,
196-
customPadding: SessionCell.Padding(bottom: Values.smallSpacing),
196+
customPadding: SessionCell.Padding(
197+
leading: 0,
198+
bottom: Values.smallSpacing
199+
),
197200
backgroundStyle: .noBackground
198201
),
199202
accessibility: Accessibility(

0 commit comments

Comments
 (0)