From a005e98ff3a287566ca5af3442b7130e502f8cc8 Mon Sep 17 00:00:00 2001 From: TSI-amrutwaghmare <96108296+TSI-amrutwaghmare@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:03:55 +0530 Subject: [PATCH] NMC 1971 - Launch screen and Intro screen UI Customisation --- Brand/Intro/NCIntro.storyboard | 114 +++++++------ Brand/Intro/NCIntroCollectionViewCell.xib | 43 ++--- Brand/Intro/NCIntroViewController.swift | 97 +++++++---- Brand/LaunchScreen.storyboard | 33 +++- .../OnboardingTestCase.swift | 158 ++++++++++++++++++ iOSClient/AppDelegate.swift | 8 + iOSClient/AppUtility.swift | 21 +++ 7 files changed, 362 insertions(+), 112 deletions(-) create mode 100644 Tests/NextcloudUnitTests/OnboardingTestCase.swift create mode 100644 iOSClient/AppUtility.swift diff --git a/Brand/Intro/NCIntro.storyboard b/Brand/Intro/NCIntro.storyboard index 5e14cab3fa..c17b6df339 100644 --- a/Brand/Intro/NCIntro.storyboard +++ b/Brand/Intro/NCIntro.storyboard @@ -1,111 +1,123 @@ - + - + + - + - - + + - - + + - - - - + - - + + - - + - - - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + - + + + + + + - - - - - + + + + + + - + + + + + + diff --git a/Brand/Intro/NCIntroCollectionViewCell.xib b/Brand/Intro/NCIntroCollectionViewCell.xib index 7eed66d3ba..ab7c53a1de 100644 --- a/Brand/Intro/NCIntroCollectionViewCell.xib +++ b/Brand/Intro/NCIntroCollectionViewCell.xib @@ -1,56 +1,57 @@ - + - + - + - - + - - - - - - + + + + + + + + - - + + - + diff --git a/Brand/Intro/NCIntroViewController.swift b/Brand/Intro/NCIntroViewController.swift index fb5cc511ed..ee2b816af6 100644 --- a/Brand/Intro/NCIntroViewController.swift +++ b/Brand/Intro/NCIntroViewController.swift @@ -24,6 +24,7 @@ // import UIKit +import NextcloudKit class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { @IBOutlet weak var buttonLogin: UIButton! @@ -31,20 +32,26 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol @IBOutlet weak var buttonHost: UIButton! @IBOutlet weak var introCollectionView: UICollectionView! @IBOutlet weak var pageControl: UIPageControl! + @IBOutlet weak var contstraintBottomLoginButton: NSLayoutConstraint! - weak var delegate: NCIntroViewController? - + @objc weak var delegate: NCIntroViewController? private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! - private let titles = [NSLocalizedString("_intro_1_title_", comment: ""), NSLocalizedString("_intro_2_title_", comment: ""), NSLocalizedString("_intro_3_title_", comment: ""), NSLocalizedString("_intro_4_title_", comment: "")] - private let images = [UIImage(named: "intro1"), UIImage(named: "intro2"), UIImage(named: "intro3"), UIImage(named: "intro4")] + private let titles = [NSLocalizedString("", comment: ""), NSLocalizedString("", comment: ""), NSLocalizedString("", comment: "")] + private var images:[UIImage?] = [] private var timerAutoScroll: Timer? private var textColor: UIColor = .white private var textColorOpponent: UIColor = .black + private let imagesLandscape = [UIImage(named: "introSlideLand1"), UIImage(named: "introSlideLand2"), UIImage(named: "introSlideLand3")] + private let imagesPortrait = [UIImage(named: "introSlide1"), UIImage(named: "introSlide2"), UIImage(named: "introSlide3")] + private let imagesEightPortrait = [UIImage(named: "introSlideEight1"), UIImage(named: "introSlideEight2"), UIImage(named: "introSlideEight3")] // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() + + let isEightPlusDevice = UIScreen.main.bounds.height == 736 + images = UIDevice.current.orientation.isLandscape ? imagesLandscape : (isEightPlusDevice ? imagesEightPortrait : imagesPortrait) let isTooLight = NCBrandColor.shared.customer.isTooLight() let isTooDark = NCBrandColor.shared.customer.isTooDark() @@ -71,7 +78,7 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol pageControl.currentPageIndicatorTintColor = textColor pageControl.pageIndicatorTintColor = .lightGray - buttonLogin.layer.cornerRadius = 20 + buttonLogin.layer.cornerRadius = 4 buttonLogin.setTitleColor(NCBrandColor.shared.customer, for: .normal) buttonLogin.backgroundColor = textColor buttonLogin.setTitle(NSLocalizedString("_log_in_", comment: ""), for: .normal) @@ -97,28 +104,7 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol view.backgroundColor = NCBrandColor.shared.customer timerAutoScroll = Timer.scheduledTimer(timeInterval: 5, target: self, selector: (#selector(NCIntroViewController.autoScroll)), userInfo: nil, repeats: true) - - NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeUser), object: nil, queue: nil) { notification in - if let userInfo = notification.userInfo, - let account = userInfo["account"] as? String { - let window = UIApplication.shared.firstWindow - if let controller = window?.rootViewController as? NCMainTabBarController { - controller.account = account - self.dismiss(animated: true) - } else { - if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController { - controller.account = account - controller.modalPresentationStyle = .fullScreen - controller.view.alpha = 0 - window?.rootViewController = controller - window?.makeKeyAndVisible() - UIView.animate(withDuration: 0.5) { - controller.view.alpha = 1 - } - } - } - } - } + NotificationCenter.default.addObserver(self, selector: #selector(resetPageController(_:)), name: UIApplication.willEnterForegroundNotification, object: nil) } override var preferredStatusBarStyle: UIStatusBarStyle { @@ -129,17 +115,38 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol } } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + if (UIDevice.current.userInterfaceIdiom != .pad){ + AppUtility.lockOrientation(UIInterfaceOrientationMask.portrait, andRotateTo: UIInterfaceOrientation.portrait) + } + navigationController?.setNavigationBarHidden(true, animated: animated) + } + + override func viewDidLayoutSubviews() { + if UIScreen.main.bounds.width < 350 || UIScreen.main.bounds.height > 800 { + contstraintBottomLoginButton.constant = 15 + } + } + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) timerAutoScroll?.invalidate() + AppUtility.lockOrientation(UIInterfaceOrientationMask.all) + navigationController?.setNavigationBarHidden(false, animated: animated) } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { - super.viewWillTransition(to: size, with: coordinator) - coordinator.animate(alongsideTransition: nil) { _ in - self.pageControl?.currentPage = 0 - self.introCollectionView?.collectionViewLayout.invalidateLayout() - } + let isEightPlusDevice = UIScreen.main.bounds.height == 736 + images = UIDevice.current.orientation.isLandscape ? imagesLandscape : (isEightPlusDevice ? imagesEightPortrait : imagesPortrait) + pageControl.currentPage = 0 + introCollectionView.collectionViewLayout.invalidateLayout() + self.introCollectionView.reloadData() + } + + @objc func resetPageController(_ notification: NSNotification){ + pageControl.currentPage = 0 + introCollectionView.scrollToItem(at: IndexPath(row: pageControl.currentPage, section: 0), at: .centeredHorizontally, animated: true) } @objc func autoScroll() { @@ -166,6 +173,7 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol cell.titleLabel.textColor = textColor cell.titleLabel.text = titles[indexPath.row] cell.imageView.image = images[indexPath.row] + cell.imageView.contentMode = .scaleAspectFill return cell } @@ -175,7 +183,13 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { timerAutoScroll = Timer.scheduledTimer(timeInterval: 5, target: self, selector: (#selector(NCIntroViewController.autoScroll)), userInfo: nil, repeats: true) - pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width) + let page = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width) + if pageControl.currentPage == (images.count - 1), pageControl.currentPage <= page { + pageControl.currentPage = 0 + introCollectionView.scrollToItem(at: IndexPath(row: pageControl.currentPage, section: 0), at: .centeredHorizontally, animated: false) + } else { + pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width) + } } func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { @@ -183,7 +197,22 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol } @IBAction func login(_ sender: Any) { - appDelegate.openLogin(selector: NCGlobal.shared.introLogin) + if NCBrandOptions.shared.use_AppConfig { + let loginViewPage = UIStoryboard(name: "NCLogin", bundle: Bundle.main).instantiateViewController(identifier: "NCLogin") + navigationController?.pushViewController(loginViewPage, animated: true) + } else { + if NextcloudKit.shared.isNetworkReachable() { + appDelegate.openLogin(selector: NCGlobal.shared.introLogin) + } else { + showNoInternetAlert() + } + } + } + + func showNoInternetAlert(){ + let alertController = UIAlertController(title: NSLocalizedString("_no_internet_alert_title_", comment: ""), message: NSLocalizedString("_no_internet_alert_message_", comment: ""), preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { action in })) + self.present(alertController, animated: true) } @IBAction func signup(_ sender: Any) { diff --git a/Brand/LaunchScreen.storyboard b/Brand/LaunchScreen.storyboard index 26840f6195..29059fe902 100755 --- a/Brand/LaunchScreen.storyboard +++ b/Brand/LaunchScreen.storyboard @@ -1,9 +1,9 @@ - + - + @@ -17,16 +17,37 @@ - + + + + + + + + + + + + - - + - + + diff --git a/Tests/NextcloudUnitTests/OnboardingTestCase.swift b/Tests/NextcloudUnitTests/OnboardingTestCase.swift new file mode 100644 index 0000000000..161b3a9258 --- /dev/null +++ b/Tests/NextcloudUnitTests/OnboardingTestCase.swift @@ -0,0 +1,158 @@ +// +// OnboardingTestCase.swift +// NextcloudTests +// +// Created by A200073704 on 21/04/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit + + class OnboardingTestCase: XCTestCase { + + var viewController = NCIntroViewController() + + + var images:[UIImage?] = [] + let imagesLandscape = [UIImage(named: "introSlideLand1"), UIImage(named: "introSlideLand2"), UIImage(named: "introSlideLand3")] + let imagesPortrait = [UIImage(named: "introSlide1"), UIImage(named: "introSlide2"), UIImage(named: "introSlide3")] + let imagesEightPortrait = [UIImage(named: "introSlideEight1"), UIImage(named: "introSlideEight2"), UIImage(named: "introSlideEight3")] + + + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + + func testValidImage() { + + // onscreen images should not be nill + let image = [UIImage(named: "introSlideLand1"), UIImage(named: "introSlideLand2"), UIImage(named: "introSlideLand3")] + XCTAssertNotNil(image, "Image should not be nil") + + } + + func testImageDimensionsLandscape() { + + // testing height and width of the image + let introCollectionView = UIImage(named: "introSlideLand1") + XCTAssertEqual(introCollectionView?.size.width, 390, "Image width should be 390") + XCTAssertEqual(introCollectionView?.size.height, 844.3333333333334, "Image height should be 844.3333333333334") + } + + func testImageDimensionsPortrait() { + + // testing height and width of the image + let introCollectionView = UIImage(named: "introSlide1") + + XCTAssertEqual(introCollectionView?.size.width, 390, "Image width should be 390") + XCTAssertEqual(introCollectionView?.size.height, 844.3333333333334, "Image height should be 844.3333333333334") + } + + + func testImageDimentionsNotEqual() { + + // testing width and height if not equal + let introCollectionView = UIImage(named: "introSlide2") + + XCTAssertNotEqual(introCollectionView?.size.width, 100, "Image width should be 390") + XCTAssertNotEqual(introCollectionView?.size.height, 820, "Image height should be 844.3333333333334") + + } + + + func testImageContentMode() { + + // imageview content mode should be scaleAspectFill + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFill + imageView.image = UIImage(named: "introSlideLand2") + XCTAssertEqual(imageView.contentMode, .scaleAspectFill, "Image content mode should be scaleAspectFill") + + } + + + // Background color of view should be customer + func testBackgroundcolor() { + + let backgroundColor = NCBrandColor.shared.customer + XCTAssertNotNil(backgroundColor, "NCBrandColor.shared.customer should not be nil") + + } + + + // Button login text color shouyld be white + func testButtonLoginTextColor() { + + let textColor: UIColor = .white + viewController.buttonLogin?.backgroundColor = textColor + + XCTAssertEqual(textColor, textColor) + + } + + // images at loginscreen should not be empty + func testImagesNotEmpty() { + + let isEightPlusDevice = UIScreen.main.bounds.height == 736 + images = UIDevice.current.orientation.isLandscape ? imagesLandscape : (isEightPlusDevice ? imagesEightPortrait : imagesPortrait) + + XCTAssertFalse(images.isEmpty) + } + + + // Status bar and navigation bar color should not be blue color + func testStatueBarColorNotEqualToCustomer() { + + + let view = NCLoginWeb() + var color = view.navigationController?.navigationBar.backgroundColor + let navigationBarColor: UIColor = NCBrandColor.shared.customer + color = .systemBlue + + XCTAssertNotEqual(navigationBarColor, color) + + } + + //NavigationBar and status Bar color should be equal + func testNavigationBarColorEqualToCustomer() { + + let statusBarColor = NCBrandColor.shared.customer + let navigationBarColor: UIColor = NCBrandColor.shared.customer + + XCTAssertEqual(navigationBarColor, statusBarColor) + } + + func testEightPlusDeviceHeight() { + + let eightPlusDevice = UIScreen.main.bounds.height >= 736 + + XCTAssertTrue(eightPlusDevice) + + } + + func testLoginButtonTapped() { + + let viewController = NCIntroViewController() + + let loginButton = UIButton() + loginButton.addTarget(nil, action: #selector(viewController.login(_:)), for: .touchUpInside) + loginButton.sendActions(for: .touchUpInside) + + viewController.login(loginButton) + + XCTAssertNotNil(loginButton) + } + + + + +} diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift index 350f474d3c..67fa88b74b 100644 --- a/iOSClient/AppDelegate.swift +++ b/iOSClient/AppDelegate.swift @@ -38,6 +38,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD var activeLogin: NCLogin? var activeLoginWeb: NCLoginProvider? var taskAutoUploadDate: Date = Date() + var orientationLock = UIInterfaceOrientationMask.all var isUiTestingEnabled: Bool { return ProcessInfo.processInfo.arguments.contains("UI_TESTING") } @@ -435,3 +436,10 @@ extension AppDelegate: NCCreateFormUploadConflictDelegate { NCNetworkingProcess.shared.createProcessUploads(metadatas: metadatas) } } + +//MARK: NMC Customisation +extension AppDelegate { + func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { + return self.orientationLock + } +} diff --git a/iOSClient/AppUtility.swift b/iOSClient/AppUtility.swift new file mode 100644 index 0000000000..bb7c625e53 --- /dev/null +++ b/iOSClient/AppUtility.swift @@ -0,0 +1,21 @@ +// +// AppUtility.swift +// Nextcloud +// +// Created by Amrut Waghmare on 17/10/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import Foundation +struct AppUtility { + static func lockOrientation(_ orientation: UIInterfaceOrientationMask) { + if let delegate = UIApplication.shared.delegate as? AppDelegate { + delegate.orientationLock = orientation + } + } + + static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) { + self.lockOrientation(orientation) + UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation") + } +}