From 9b712299b10aa9a32453e2a7770867ad047db64c Mon Sep 17 00:00:00 2001 From: Muhammad Umer Date: Mon, 3 Jul 2023 18:01:51 +0500 Subject: [PATCH 1/7] chore: handle landscape mode for new component screen for videos --- Source/AccessibilityCLButton.swift | 7 ++- Source/CutomePlayer/VideoPlayer.swift | 10 ++- Source/NewCourseContentController.swift | 61 ++++++++++++------- Source/NewCourseDashboardViewController.swift | 5 ++ Source/OEXRouter+Swift.swift | 2 +- Source/UIViewController+CommonAdditions.swift | 10 +++ Source/VideoBlockViewController.swift | 35 ++++++++--- 7 files changed, 93 insertions(+), 37 deletions(-) diff --git a/Source/AccessibilityCLButton.swift b/Source/AccessibilityCLButton.swift index fef2b984b3..37aa97a944 100644 --- a/Source/AccessibilityCLButton.swift +++ b/Source/AccessibilityCLButton.swift @@ -34,9 +34,12 @@ class AccessibilityCLButton: CustomPlayerButton { } public override func draw(_ rect: CGRect) { - let r = UIBezierPath(ovalIn: rect) + let diameter = min(rect.width, rect.height) + let circleRect = CGRect(x: rect.origin.x, y: rect.origin.y, width: diameter, height: diameter) + let path = UIBezierPath(ovalIn: circleRect) UIColor.black.withAlphaComponent(0.65).setFill() - r.fill() + path.fill() + super.draw(rect) } } diff --git a/Source/CutomePlayer/VideoPlayer.swift b/Source/CutomePlayer/VideoPlayer.swift index 87a3599ffd..e503032083 100644 --- a/Source/CutomePlayer/VideoPlayer.swift +++ b/Source/CutomePlayer/VideoPlayer.swift @@ -31,7 +31,7 @@ protocol VideoPlayerDelegate: AnyObject { private var playbackLikelyToKeepUpContext = 0 class VideoPlayer: UIViewController,VideoPlayerControlsDelegate,TranscriptManagerDelegate { - typealias Environment = OEXInterfaceProvider & OEXAnalyticsProvider & OEXStylesProvider + typealias Environment = OEXInterfaceProvider & OEXAnalyticsProvider & OEXStylesProvider & OEXConfigProvider public let environment : Environment fileprivate var controls: VideoPlayerControls? @@ -684,9 +684,13 @@ class VideoPlayer: UIViewController,VideoPlayerControlsDelegate,TranscriptManage func setFullscreen(fullscreen: Bool, animated: Bool, with deviceOrientation: UIInterfaceOrientation, forceRotate rotate: Bool) { if !isVisible { return } isFullScreen = fullscreen + if fullscreen { - - fullScreenContainerView = UIApplication.shared.window?.rootViewController?.view ?? UIApplication.shared.windows[0].rootViewController?.view + if environment.config.isNewComponentNavigationEnabled { + fullScreenContainerView = parent?.findParentViewController(type: NewCourseContentController.self)?.view ?? UIApplication.shared.windows.first?.rootViewController?.view + } else { + fullScreenContainerView = UIApplication.shared.window?.rootViewController?.view ?? UIApplication.shared.windows.first?.rootViewController?.view + } if movieBackgroundView.frame == .zero { movieBackgroundView.frame = movieBackgroundFrame diff --git a/Source/NewCourseContentController.swift b/Source/NewCourseContentController.swift index d5a76a19c0..0f3f3f0533 100644 --- a/Source/NewCourseContentController.swift +++ b/Source/NewCourseContentController.swift @@ -63,21 +63,23 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi private let parentID: CourseBlockID? private let courseID: CourseBlockID private let courseQuerier: CourseOutlineQuerier + private let courseOutlineMode: CourseOutlineMode - init(environment: Environment, blockID: CourseBlockID?, resumeCourseBlockID: CourseBlockID? = nil, parentID: CourseBlockID? = nil, courseID: CourseBlockID) { + init(environment: Environment, blockID: CourseBlockID?, resumeCourseBlockID: CourseBlockID? = nil, parentID: CourseBlockID? = nil, courseID: CourseBlockID, courseOutlineMode: CourseOutlineMode? = .full) { self.environment = environment self.blockID = blockID self.parentID = parentID self.courseID = courseID + self.courseOutlineMode = courseOutlineMode ?? .full courseQuerier = environment.dataManager.courseDataManager.querierForCourseWithID(courseID: courseID, environment: environment) super.init(nibName: nil, bundle: nil) + setStatusBar(color: environment.styles.primaryLightColor()) if let resumeCourseBlockID = resumeCourseBlockID { currentBlock = courseQuerier.blockWithID(id: resumeCourseBlockID).firstSuccess().value } else { findCourseBlockToShow() } - setStatusBar(color: environment.styles.primaryLightColor()) } required init?(coder aDecoder: NSCoder) { @@ -106,6 +108,7 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + setStatusBar(color: environment.styles.primaryLightColor()) navigationController?.setNavigationBarHidden(true, animated: false) } @@ -150,7 +153,7 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi let parent = courseQuerier.parentOfBlockWith(id: currentBlock.blockID).firstSuccess().value else { return } - let courseContentViewController = CourseContentPageViewController(environment: environment, courseID: courseID, rootID: parent.blockID, initialChildID: currentBlock.blockID, forMode: .full) + let courseContentViewController = CourseContentPageViewController(environment: environment, courseID: courseID, rootID: parent.blockID, initialChildID: currentBlock.blockID, forMode: courseOutlineMode) courseContentViewController.navigationDelegate = self let childViewController = ForwardingNavigationController(rootViewController: courseContentViewController) @@ -170,20 +173,15 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi private func setupCompletedBlocksView() { guard let block = currentBlock, - let section = courseQuerier.parentOfBlockWith(id: block.blockID, type: .Section).firstSuccess().value + let section = courseQuerier.parentOfBlockWith(id: block.blockID, type: .Section).firstSuccess().value, + let sectionChildren = courseQuerier.childrenOfBlockWithID(blockID: section.blockID, forMode: courseOutlineMode).value else { return } - let childBlocks: [CourseBlock] = section.children - .compactMap { item -> CourseBlock? in - return courseQuerier.blockWithID(id: item).firstSuccess().value - } - .flatMap { item -> [CourseBlockID] in - return item.children - } - .compactMap { item -> CourseBlock? in - return courseQuerier.blockWithID(id: item).firstSuccess().value - } - + let childBlocks: [CourseBlock] = sectionChildren.children.compactMap { item in + courseQuerier.childrenOfBlockWithID(blockID: item.blockID, forMode: courseOutlineMode) + .firstSuccess().value?.children ?? [] + }.flatMap { $0 } + let childViews: [UIView] = childBlocks.map { block -> UIView in let view = UIView() view.backgroundColor = block.isCompleted ? environment.styles.accentBColor() : environment.styles.neutralDark() @@ -200,15 +198,13 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi .firstSuccess().value?.children.compactMap({ $0 }).filter({ $0.type == .Unit }) else { return } - guard let firstInCompleteBlock = childBlocks.flatMap({ $0.children }) - .compactMap({ courseQuerier.blockWithID(id: $0).value }) - .first(where: { !$0.isCompleted }) - else { - currentBlock = courseQuerier.childrenOfBlockWithID(blockID: childBlocks.last?.blockID, forMode: .full).firstSuccess().value?.children.last - return + let blocks: [CourseBlock] = childBlocks.flatMap { block in + courseQuerier.childrenOfBlockWithID(blockID: block.blockID, forMode: courseOutlineMode).value?.children.compactMap { child in + courseQuerier.blockWithID(id: child.blockID).value + } ?? [] } - - currentBlock = firstInCompleteBlock + + currentBlock = blocks.first(where: { !$0.isCompleted }) ?? blocks.last } private func updateView() { @@ -235,6 +231,11 @@ extension NewCourseContentController: CourseContentPageViewControllerDelegate { if var controller = controller.viewControllers?.first as? ScrollableDelegateProvider { controller.scrollableDelegate = self } + + if let controller = controller.viewControllers?.first as? VideoBlockViewController { + controller.orientationDelegate = self + changeOrientation(orientation: currentOrientation()) + } } } @@ -299,6 +300,20 @@ extension NewCourseContentController { } } +extension NewCourseContentController: VideoBlockViewControllerOrientationDelegate { + func changeOrientation(orientation: UIInterfaceOrientation) { + if orientation == .portrait { + if headerViewState == .collapsed { + headerViewState = .animating + expandHeaderView() + } + } else if headerViewState == .expanded { + headerViewState = .animating + collapseHeaderView() + } + } +} + fileprivate extension UIStackView { func addArrangedSubviews(_ views: [UIView]) { views.forEach { addArrangedSubview($0) } diff --git a/Source/NewCourseDashboardViewController.swift b/Source/NewCourseDashboardViewController.swift index e7fbeee6d6..798469ee76 100644 --- a/Source/NewCourseDashboardViewController.swift +++ b/Source/NewCourseDashboardViewController.swift @@ -103,6 +103,11 @@ class NewCourseDashboardViewController: UIViewController, InterfaceOrientationOv environment.analytics.trackScreen(withName: OEXAnalyticsScreenCourseDashboard, courseID: courseID, value: nil) } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + expandHeaderView() + } + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) navigationController?.setNavigationBarHidden(false, animated: true) diff --git a/Source/OEXRouter+Swift.swift b/Source/OEXRouter+Swift.swift index e05df5a30d..64b10e75f9 100644 --- a/Source/OEXRouter+Swift.swift +++ b/Source/OEXRouter+Swift.swift @@ -138,7 +138,7 @@ extension OEXRouter { func showContainerForBlockWithID(blockID: CourseBlockID?, type: CourseBlockDisplayType, parentID: CourseBlockID?, courseID: CourseBlockID, fromController controller: UIViewController, forMode mode: CourseOutlineMode? = .full, completion: ((UIViewController) -> Void)? = nil) { if environment.config.isNewComponentNavigationEnabled { - let contentController = NewCourseContentController(environment: environment, blockID: blockID, parentID: parentID, courseID: courseID) + let contentController = NewCourseContentController(environment: environment, blockID: blockID, parentID: parentID, courseID: courseID, courseOutlineMode: mode) controller.navigationController?.pushViewController(contentController, animated: true, completion: completion) } else { showContainerForBlockWithIDOld(blockID: blockID, type: type, parentID: parentID, courseID: courseID, fromController: controller, forMode: mode, completion: completion) diff --git a/Source/UIViewController+CommonAdditions.swift b/Source/UIViewController+CommonAdditions.swift index 02ac2fa1f1..7ad3ee397a 100644 --- a/Source/UIViewController+CommonAdditions.swift +++ b/Source/UIViewController+CommonAdditions.swift @@ -65,4 +65,14 @@ extension UIViewController { } navigationItem.leftBarButtonItem = backItem } + + func findParentViewController(type: T.Type) -> T? { + if let parentViewController = self.parent as? T { + return parentViewController + } else if let parentViewController = self.parent { + return parentViewController.findParentViewController(type: type) + } else { + return nil + } + } } diff --git a/Source/VideoBlockViewController.swift b/Source/VideoBlockViewController.swift index b4e6d144dd..46ec231d84 100644 --- a/Source/VideoBlockViewController.swift +++ b/Source/VideoBlockViewController.swift @@ -10,6 +10,10 @@ import Foundation import MediaPlayer import UIKit +protocol VideoBlockViewControllerOrientationDelegate { + func changeOrientation(orientation: UIInterfaceOrientation) +} + class VideoBlockViewController : OfflineSupportViewController, CourseBlockViewController, StatusBarOverriding, InterfaceOrientationOverriding, VideoTranscriptDelegate, RatingViewControllerDelegate, VideoPlayerDelegate { typealias Environment = DataManagerProvider & OEXInterfaceProvider & ReachabilityProvider & OEXConfigProvider & OEXRouterProvider & OEXAnalyticsProvider & OEXStylesProvider & OEXSessionProvider & NetworkManagerProvider @@ -442,16 +446,31 @@ class VideoBlockViewController : OfflineSupportViewController, CourseBlockViewCo } } - // willTransition only called in case of iPhone because iPhone has regular and compact vertical classes. - // This method is specially for iPad override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { - guard UIDevice.current.userInterfaceIdiom == .pad else { return } + orientationDelegate?.changeOrientation(orientation: currentOrientation()) - if videoPlayer.isFullScreen { - videoPlayer.setFullscreen(fullscreen: !UIDevice.current.orientation.isPortrait, animated: true, with: currentOrientation(), forceRotate: false) - } - else if UIDevice.current.orientation.isLandscape { - videoPlayer.setFullscreen(fullscreen: true, animated: true, with: currentOrientation(), forceRotate: false) + if UIDevice.current.userInterfaceIdiom == .pad { + if videoPlayer.isFullScreen { + videoPlayer.setFullscreen(fullscreen: !UIDevice.current.orientation.isPortrait, animated: true, with: currentOrientation(), forceRotate: false) + } else if UIDevice.current.orientation.isLandscape { + videoPlayer.setFullscreen(fullscreen: true, animated: true, with: currentOrientation(), forceRotate: false) + } + } else { + DispatchQueue.main.async { [weak self] in + if let weakSelf = self { + if weakSelf.chromeCastManager.isMiniPlayerAdded { return } + + if weakSelf.videoPlayer.isFullScreen { + if UITraitCollection.current.verticalSizeClass == .regular { + weakSelf.videoPlayer.setFullscreen(fullscreen: false, animated: true, with: weakSelf.currentOrientation(), forceRotate: false) + } else { + weakSelf.videoPlayer.setFullscreen(fullscreen: true, animated: true, with: weakSelf.currentOrientation(), forceRotate: false) + } + } else if UITraitCollection.current.verticalSizeClass == .compact && !weakSelf.shouldCelebrationAppear { + weakSelf.videoPlayer.setFullscreen(fullscreen: true, animated: true, with: weakSelf.currentOrientation(), forceRotate: false) + } + } + } } } From 5f0c8cff14c9e09ce1dfc15d54f793111be2c2ba Mon Sep 17 00:00:00 2001 From: Muhammad Umer Date: Mon, 3 Jul 2023 18:04:04 +0500 Subject: [PATCH 2/7] chore: handle landscape mode for new component screen for videos --- Source/VideoBlockViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/VideoBlockViewController.swift b/Source/VideoBlockViewController.swift index 46ec231d84..5d8fb068c1 100644 --- a/Source/VideoBlockViewController.swift +++ b/Source/VideoBlockViewController.swift @@ -36,6 +36,8 @@ class VideoBlockViewController : OfflineSupportViewController, CourseBlockViewCo private var overlayLabel: UILabel? var shouldCelebrationAppear: Bool + var orientationDelegate: VideoBlockViewControllerOrientationDelegate? + init(environment : Environment, blockID : CourseBlockID?, courseID: String, shouldCelebrationAppear: Bool = false) { self.blockID = blockID self.environment = environment From 49c2acd055b42175ec0fae5b9bfdfc9434d0e881 Mon Sep 17 00:00:00 2001 From: Muhammad Umer Date: Tue, 4 Jul 2023 16:01:58 +0500 Subject: [PATCH 3/7] chore: address feedback --- Source/NewCourseContentController.swift | 16 +++++++++++--- Source/NewCourseDashboardViewController.swift | 22 ++++++++++++++++++- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Source/NewCourseContentController.swift b/Source/NewCourseContentController.swift index 0f3f3f0533..79eeb8e537 100644 --- a/Source/NewCourseContentController.swift +++ b/Source/NewCourseContentController.swift @@ -73,7 +73,6 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi self.courseOutlineMode = courseOutlineMode ?? .full courseQuerier = environment.dataManager.courseDataManager.querierForCourseWithID(courseID: courseID, environment: environment) super.init(nibName: nil, bundle: nil) - setStatusBar(color: environment.styles.primaryLightColor()) if let resumeCourseBlockID = resumeCourseBlockID { currentBlock = courseQuerier.blockWithID(id: resumeCourseBlockID).firstSuccess().value @@ -101,6 +100,7 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func viewDidLoad() { super.viewDidLoad() + setStatusBar(color: environment.styles.primaryLightColor()) addSubViews() setupComponentView() setupCompletedBlocksView() @@ -108,7 +108,6 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - setStatusBar(color: environment.styles.primaryLightColor()) navigationController?.setNavigationBarHidden(true, animated: false) } @@ -220,7 +219,18 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi } override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { - setStatusBar(color: environment.styles.primaryLightColor()) + + if currentOrientation() == .portrait { + setStatusBar(color: environment.styles.primaryLightColor()) + } else { + removeStatusBar() + } + + if headerViewState == .collapsed { + collapseHeaderView() + } else if headerViewState == .expanded { + expandHeaderView() + } } } diff --git a/Source/NewCourseDashboardViewController.swift b/Source/NewCourseDashboardViewController.swift index 798469ee76..1a539483da 100644 --- a/Source/NewCourseDashboardViewController.swift +++ b/Source/NewCourseDashboardViewController.swift @@ -258,7 +258,18 @@ class NewCourseDashboardViewController: UIViewController, InterfaceOrientationOv override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { setupContentView() - setStatusBar(color: environment.styles.primaryLightColor()) + + if currentOrientation() == .portrait { + setStatusBar(color: environment.styles.primaryLightColor()) + } else { + removeStatusBar() + } + + if headerViewState == .collapsed { + collapseHeaderView() + } else if headerViewState == .expanded { + expandHeaderView() + } } private func prepareTabViewData() { @@ -607,4 +618,13 @@ public extension UIViewController { overView.backgroundColor = color } } + + func removeStatusBar() { + DispatchQueue.main.async { [weak self] in + let tag = 123454321 + if let taggedView = self?.view.viewWithTag(tag) { + taggedView.removeFromSuperview() + } + } + } } From 7ec4757074a6bac81cf91e20e8e9ae4e6f65eb9b Mon Sep 17 00:00:00 2001 From: Muhammad Umer Date: Wed, 5 Jul 2023 17:58:14 +0500 Subject: [PATCH 4/7] chore: address feedback --- Source/CourseDashboardHeaderView.swift | 5 +++ Source/NewCourseContentController.swift | 45 ++++++++++++++++--- Source/NewCourseDashboardViewController.swift | 14 +++++- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/Source/CourseDashboardHeaderView.swift b/Source/CourseDashboardHeaderView.swift index 7994d082c0..789b828390 100644 --- a/Source/CourseDashboardHeaderView.swift +++ b/Source/CourseDashboardHeaderView.swift @@ -16,6 +16,7 @@ protocol CourseDashboardHeaderViewDelegate: AnyObject { } enum HeaderViewState { + case initial case animating case expanded case collapsed @@ -37,6 +38,8 @@ class CourseDashboardHeaderView: UIView { private lazy var datesBannerView = NewCourseDateBannerView() private var bannerInfo: DatesBannerInfo? = nil + var state: HeaderViewState = .initial + private lazy var orgLabel: UILabel = { let label = UILabel() label.accessibilityIdentifier = "CourseDashboardHeaderView:org-label" @@ -245,6 +248,8 @@ class CourseDashboardHeaderView: UIView { make.trailing.equalTo(closeButton.snp.leading).offset(-StandardHorizontalMargin) } + if state == .collapsed { return } + courseInfoContainerView.snp.remakeConstraints { make in make.top.equalTo(closeButton.snp.bottom) make.leading.equalTo(containerView).offset(StandardHorizontalMargin) diff --git a/Source/NewCourseContentController.swift b/Source/NewCourseContentController.swift index 79eeb8e537..36c442598e 100644 --- a/Source/NewCourseContentController.swift +++ b/Source/NewCourseContentController.swift @@ -44,6 +44,7 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi private var courseContentViewController: CourseContentPageViewController? private var headerViewState: HeaderViewState = .expanded + private var statusBarTag = 999999 private var currentBlock: CourseBlock? { willSet { @@ -100,7 +101,6 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func viewDidLoad() { super.viewDidLoad() - setStatusBar(color: environment.styles.primaryLightColor()) addSubViews() setupComponentView() setupCompletedBlocksView() @@ -109,6 +109,14 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(true, animated: false) + updateStatusBarVisibility() + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { [weak self] in + self?.removeStatusBarView() + } } private func addSubViews() { @@ -220,10 +228,8 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { - if currentOrientation() == .portrait { - setStatusBar(color: environment.styles.primaryLightColor()) - } else { - removeStatusBar() + coordinator.animate { [weak self] _ in + self?.updateStatusBarVisibility() } if headerViewState == .collapsed { @@ -232,6 +238,26 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi expandHeaderView() } } + + private func removeStatusBarView() { + if let statusBar = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first?.viewWithTag(statusBarTag) { + statusBar.removeFromSuperview() + } + } + + private func updateStatusBarVisibility() { + let window = UIApplication.shared.windows.first + let topPadding = window?.safeAreaInsets.top + + if currentOrientation() == .portrait { + let statusBar = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: topPadding ?? 0.0)) + statusBar.backgroundColor = environment.styles.primaryLightColor() + statusBar.tag = statusBarTag + UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.addSubview(statusBar) + } else { + removeStatusBarView() + } + } } extension NewCourseContentController: CourseContentPageViewControllerDelegate { @@ -244,7 +270,14 @@ extension NewCourseContentController: CourseContentPageViewControllerDelegate { if let controller = controller.viewControllers?.first as? VideoBlockViewController { controller.orientationDelegate = self - changeOrientation(orientation: currentOrientation()) + + if currentOrientation() != .portrait { + collapseHeaderView() + } else if headerViewState == .collapsed { + collapseHeaderView() + } else if headerViewState == .expanded { + expandHeaderView() + } } } } diff --git a/Source/NewCourseDashboardViewController.swift b/Source/NewCourseDashboardViewController.swift index 1a539483da..37cbc800d2 100644 --- a/Source/NewCourseDashboardViewController.swift +++ b/Source/NewCourseDashboardViewController.swift @@ -64,7 +64,12 @@ class NewCourseDashboardViewController: UIViewController, InterfaceOrientationOv private var error: NSError? private var courseAccessHelper: CourseAccessHelper? private var selectedTabbarItem: TabBarItem? - private var headerViewState: HeaderViewState = .expanded + + private var headerViewState: HeaderViewState = .expanded { + didSet { + headerView.state = headerViewState + } + } private var tabBarItems: [TabBarItem] = [] private var isModalDismissable = true private let courseStream: BackedStream @@ -105,7 +110,12 @@ class NewCourseDashboardViewController: UIViewController, InterfaceOrientationOv override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - expandHeaderView() + + if headerViewState == .collapsed { + collapseHeaderView() + } else if headerViewState == .expanded { + expandHeaderView() + } } override func viewWillDisappear(_ animated: Bool) { From eb7d946ec68153338c5715fbbfc7a6ff343cc9c1 Mon Sep 17 00:00:00 2001 From: Muhammad Umer Date: Fri, 7 Jul 2023 17:04:39 +0500 Subject: [PATCH 5/7] chore: address feedback --- Source/CourseContentPageViewController.swift | 7 +-- Source/NewCourseContentController.swift | 47 +++++++------------ Source/NewCourseDashboardViewController.swift | 14 ++++-- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/Source/CourseContentPageViewController.swift b/Source/CourseContentPageViewController.swift index b982eb652c..4407478af9 100644 --- a/Source/CourseContentPageViewController.swift +++ b/Source/CourseContentPageViewController.swift @@ -425,18 +425,13 @@ public class CourseContentPageViewController : UIPageViewController, UIPageViewC guard let nextController = controllerForBlock(block: block) else { return } - setPageControllers(with: [nextController], direction: direction, animated: true) { [weak self] finished in + setPageControllers(with: [nextController], direction: direction, animated: false) { [weak self] finished in guard let weakSelf = self else { return } weakSelf.updateTransitionState(is: false) if weakSelf.shouldCelebrationAppear { weakSelf.showCelebratoryModal(direction: direction, overController: nextController) } } - - currentPageItemIndex = contentLoader.value?.currentIndex() ?? 0 - - updateNavigationBars() - navigationDelegate?.courseContentPageViewController(controller: self, enteredBlockWithID: cursor.current.block.blockID, parentID: cursor.current.parent) } func controllerForBlock(block : CourseBlock, shouldCelebrationAppear: Bool = false) -> UIViewController? { diff --git a/Source/NewCourseContentController.swift b/Source/NewCourseContentController.swift index 36c442598e..b5639c50b3 100644 --- a/Source/NewCourseContentController.swift +++ b/Source/NewCourseContentController.swift @@ -101,6 +101,7 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func viewDidLoad() { super.viewDidLoad() + setStatusBar(color: environment.styles.primaryLightColor()) addSubViews() setupComponentView() setupCompletedBlocksView() @@ -109,14 +110,6 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(true, animated: false) - updateStatusBarVisibility() - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { [weak self] in - self?.removeStatusBarView() - } } private func addSubViews() { @@ -227,9 +220,15 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi } override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { - coordinator.animate { [weak self] _ in - self?.updateStatusBarVisibility() + guard let weakSelf = self else { return } + if weakSelf.currentOrientation() == .portrait { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + weakSelf.setStatusBar(color: weakSelf.environment.styles.primaryLightColor()) + } + } else { + weakSelf.removeStatusBar() + } } if headerViewState == .collapsed { @@ -238,26 +237,6 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi expandHeaderView() } } - - private func removeStatusBarView() { - if let statusBar = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first?.viewWithTag(statusBarTag) { - statusBar.removeFromSuperview() - } - } - - private func updateStatusBarVisibility() { - let window = UIApplication.shared.windows.first - let topPadding = window?.safeAreaInsets.top - - if currentOrientation() == .portrait { - let statusBar = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: topPadding ?? 0.0)) - statusBar.backgroundColor = environment.styles.primaryLightColor() - statusBar.tag = statusBarTag - UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.addSubview(statusBar) - } else { - removeStatusBarView() - } - } } extension NewCourseContentController: CourseContentPageViewControllerDelegate { @@ -268,6 +247,14 @@ extension NewCourseContentController: CourseContentPageViewControllerDelegate { controller.scrollableDelegate = self } + // header animation is overlapping with UIPageController animation which results in crash + // calling the header animation after a delay of 1 sec to overcome the issue + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in + self?.updateHeaderState(with: controller) + } + } + + private func updateHeaderState(with controller: CourseContentPageViewController) { if let controller = controller.viewControllers?.first as? VideoBlockViewController { controller.orientationDelegate = self diff --git a/Source/NewCourseDashboardViewController.swift b/Source/NewCourseDashboardViewController.swift index 37cbc800d2..4ff6895c83 100644 --- a/Source/NewCourseDashboardViewController.swift +++ b/Source/NewCourseDashboardViewController.swift @@ -269,10 +269,16 @@ class NewCourseDashboardViewController: UIViewController, InterfaceOrientationOv override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { setupContentView() - if currentOrientation() == .portrait { - setStatusBar(color: environment.styles.primaryLightColor()) - } else { - removeStatusBar() + coordinator.animate { [weak self] _ in + guard let weakSelf = self else { return } + + if weakSelf.currentOrientation() == .portrait { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + weakSelf.setStatusBar(color: weakSelf.environment.styles.primaryLightColor()) + } + } else { + weakSelf.removeStatusBar() + } } if headerViewState == .collapsed { From 85466f5f1da0fdac7b1cddd6c1a05819aa8e0f4c Mon Sep 17 00:00:00 2001 From: Muhammad Umer Date: Fri, 7 Jul 2023 18:10:26 +0500 Subject: [PATCH 6/7] chore: address feedback --- Source/NewCourseContentController.swift | 30 +----------- Source/NewCourseDashboardViewController.swift | 47 ++++++++----------- Source/VideoBlockViewController.swift | 12 +---- 3 files changed, 23 insertions(+), 66 deletions(-) diff --git a/Source/NewCourseContentController.swift b/Source/NewCourseContentController.swift index b5639c50b3..ed9fb81504 100644 --- a/Source/NewCourseContentController.swift +++ b/Source/NewCourseContentController.swift @@ -222,20 +222,10 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { coordinator.animate { [weak self] _ in guard let weakSelf = self else { return } - if weakSelf.currentOrientation() == .portrait { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { - weakSelf.setStatusBar(color: weakSelf.environment.styles.primaryLightColor()) - } - } else { - weakSelf.removeStatusBar() + DispatchQueue.main.async { + weakSelf.setStatusBar(color: weakSelf.environment.styles.primaryLightColor()) } } - - if headerViewState == .collapsed { - collapseHeaderView() - } else if headerViewState == .expanded { - expandHeaderView() - } } } @@ -256,8 +246,6 @@ extension NewCourseContentController: CourseContentPageViewControllerDelegate { private func updateHeaderState(with controller: CourseContentPageViewController) { if let controller = controller.viewControllers?.first as? VideoBlockViewController { - controller.orientationDelegate = self - if currentOrientation() != .portrait { collapseHeaderView() } else if headerViewState == .collapsed { @@ -330,20 +318,6 @@ extension NewCourseContentController { } } -extension NewCourseContentController: VideoBlockViewControllerOrientationDelegate { - func changeOrientation(orientation: UIInterfaceOrientation) { - if orientation == .portrait { - if headerViewState == .collapsed { - headerViewState = .animating - expandHeaderView() - } - } else if headerViewState == .expanded { - headerViewState = .animating - collapseHeaderView() - } - } -} - fileprivate extension UIStackView { func addArrangedSubviews(_ views: [UIView]) { views.forEach { addArrangedSubview($0) } diff --git a/Source/NewCourseDashboardViewController.swift b/Source/NewCourseDashboardViewController.swift index 4ff6895c83..e4168bcf4b 100644 --- a/Source/NewCourseDashboardViewController.swift +++ b/Source/NewCourseDashboardViewController.swift @@ -271,13 +271,8 @@ class NewCourseDashboardViewController: UIViewController, InterfaceOrientationOv coordinator.animate { [weak self] _ in guard let weakSelf = self else { return } - - if weakSelf.currentOrientation() == .portrait { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { - weakSelf.setStatusBar(color: weakSelf.environment.styles.primaryLightColor()) - } - } else { - weakSelf.removeStatusBar() + DispatchQueue.main.async { + weakSelf.setStatusBar(color: weakSelf.environment.styles.primaryLightColor()) } } @@ -616,31 +611,27 @@ extension NewCourseDashboardViewController: NewCourseDashboardViewControllerDele public extension UIViewController { func setStatusBar(color: UIColor) { - DispatchQueue.main.async { [weak self] in - let tag = 123454321 - let overView: UIView - if let taggedView = self?.view.viewWithTag(tag) { - overView = taggedView - } - else { - overView = UIView() - overView.tag = tag - self?.view.addSubview(overView) - } - - let height = UIApplication.shared.window?.windowScene?.windows.first?.safeAreaInsets.top ?? 0 - let frame = UIApplication.shared.window?.windowScene?.statusBarManager?.statusBarFrame ?? .zero - overView.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.width, height: height) - overView.backgroundColor = color + let tag = 123454321 + let overView: UIView + if let taggedView = view.viewWithTag(tag) { + overView = taggedView } + else { + overView = UIView() + overView.tag = tag + view.addSubview(overView) + } + + let height = UIApplication.shared.window?.windowScene?.windows.first?.safeAreaInsets.top ?? 0 + let frame = UIApplication.shared.window?.windowScene?.statusBarManager?.statusBarFrame ?? .zero + overView.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.width, height: height) + overView.backgroundColor = color } func removeStatusBar() { - DispatchQueue.main.async { [weak self] in - let tag = 123454321 - if let taggedView = self?.view.viewWithTag(tag) { - taggedView.removeFromSuperview() - } + let tag = 123454321 + if let taggedView = view.viewWithTag(tag) { + taggedView.removeFromSuperview() } } } diff --git a/Source/VideoBlockViewController.swift b/Source/VideoBlockViewController.swift index 5d8fb068c1..4a3d812eb2 100644 --- a/Source/VideoBlockViewController.swift +++ b/Source/VideoBlockViewController.swift @@ -10,10 +10,6 @@ import Foundation import MediaPlayer import UIKit -protocol VideoBlockViewControllerOrientationDelegate { - func changeOrientation(orientation: UIInterfaceOrientation) -} - class VideoBlockViewController : OfflineSupportViewController, CourseBlockViewController, StatusBarOverriding, InterfaceOrientationOverriding, VideoTranscriptDelegate, RatingViewControllerDelegate, VideoPlayerDelegate { typealias Environment = DataManagerProvider & OEXInterfaceProvider & ReachabilityProvider & OEXConfigProvider & OEXRouterProvider & OEXAnalyticsProvider & OEXStylesProvider & OEXSessionProvider & NetworkManagerProvider @@ -35,9 +31,7 @@ class VideoBlockViewController : OfflineSupportViewController, CourseBlockViewCo private var playOverlayButton: UIButton? private var overlayLabel: UILabel? var shouldCelebrationAppear: Bool - - var orientationDelegate: VideoBlockViewControllerOrientationDelegate? - + init(environment : Environment, blockID : CourseBlockID?, courseID: String, shouldCelebrationAppear: Bool = false) { self.blockID = blockID self.environment = environment @@ -448,9 +442,7 @@ class VideoBlockViewController : OfflineSupportViewController, CourseBlockViewCo } } - override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { - orientationDelegate?.changeOrientation(orientation: currentOrientation()) - + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { if UIDevice.current.userInterfaceIdiom == .pad { if videoPlayer.isFullScreen { videoPlayer.setFullscreen(fullscreen: !UIDevice.current.orientation.isPortrait, animated: true, with: currentOrientation(), forceRotate: false) From 5b65306c59155e1e4e9d3c409b42c73f6290de41 Mon Sep 17 00:00:00 2001 From: Muhammad Umer Date: Mon, 10 Jul 2023 10:46:57 +0500 Subject: [PATCH 7/7] chore: remove unsued line --- Source/NewCourseContentController.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/NewCourseContentController.swift b/Source/NewCourseContentController.swift index ed9fb81504..06a30d4e31 100644 --- a/Source/NewCourseContentController.swift +++ b/Source/NewCourseContentController.swift @@ -44,7 +44,6 @@ class NewCourseContentController: UIViewController, InterfaceOrientationOverridi private var courseContentViewController: CourseContentPageViewController? private var headerViewState: HeaderViewState = .expanded - private var statusBarTag = 999999 private var currentBlock: CourseBlock? { willSet {