IOS-1226 merge in default IOS-1226
authorDirk Zimmermann <dirk@pep-project.org>
Thu, 16 Aug 2018 06:37:34 +0200
branchIOS-1226
changeset 5843e8165f5e848f
parent 5827 e5fb78596950
parent 5842 2ecc59e25096
child 5845 20a9d232a083
IOS-1226 merge in default
pEpForiOS/UI/EmailDisplayList/EmailListViewController.swift
     1.1 --- a/pEpForiOS/Base.lproj/Main.storyboard	Wed Aug 15 14:19:50 2018 +0200
     1.2 +++ b/pEpForiOS/Base.lproj/Main.storyboard	Thu Aug 16 06:37:34 2018 +0200
     1.3 @@ -607,7 +607,7 @@
     1.4              <objects>
     1.5                  <tableViewController storyboardIdentifier="emailDetail" title="Show email" id="3bx-34-vLD" customClass="EmailViewController" customModule="pEpForiOS" customModuleProvider="target" sceneMemberID="viewController">
     1.6                      <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="mYV-vz-wEb">
     1.7 -                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
     1.8 +                        <rect key="frame" x="0.0" y="0.0" width="375" height="603"/>
     1.9                          <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
    1.10                          <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
    1.11                          <prototypes>
    1.12 @@ -803,7 +803,7 @@
    1.13                              </connections>
    1.14                          </barButtonItem>
    1.15                      </toolbarItems>
    1.16 -                    <navigationItem key="navigationItem" title="Title" id="PAv-Od-zv3">
    1.17 +                    <navigationItem key="navigationItem" id="PAv-Od-zv3">
    1.18                          <rightBarButtonItems>
    1.19                              <barButtonItem image="arrow-lft-active" id="nCS-Wg-ZJI">
    1.20                                  <connections>
    1.21 @@ -985,7 +985,7 @@
    1.22      <inferredMetricsTieBreakers>
    1.23          <segue reference="RTR-We-Kc1"/>
    1.24          <segue reference="0zl-tV-6Kr"/>
    1.25 -        <segue reference="anx-J8-OKE"/>
    1.26 +        <segue reference="ber-OQ-S16"/>
    1.27          <segue reference="1zD-EW-3fN"/>
    1.28      </inferredMetricsTieBreakers>
    1.29  </document>
     2.1 --- a/pEpForiOS/UI/EmailDisplay/EmailViewController.swift	Wed Aug 15 14:19:50 2018 +0200
     2.2 +++ b/pEpForiOS/UI/EmailDisplay/EmailViewController.swift	Thu Aug 16 06:37:34 2018 +0200
     2.3 @@ -48,21 +48,12 @@
     2.4          configureOKButton()
     2.5  
     2.6          loadDatasource("MessageData")
     2.7 -
     2.8 -        let item = UIBarButtonItem.getpEpButton(action: #selector(self.showSettingsViewController(_:)),
     2.9 -                                                target: self)
    2.10 -        let flexibleSpace: UIBarButtonItem = UIBarButtonItem(
    2.11 -            barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace,
    2.12 -            target: nil,
    2.13 -            action: nil)
    2.14 -        self.toolbarItems?.append(contentsOf: [flexibleSpace,item])
    2.15 +        setuptoolbar()
    2.16  
    2.17          tableView.estimatedRowHeight = 72.0
    2.18          tableView.rowHeight = UITableViewAutomaticDimension
    2.19          tableView.setNeedsLayout()
    2.20          tableView.layoutIfNeeded()
    2.21 -
    2.22 -
    2.23      }
    2.24  
    2.25      override func viewWillAppear(_ animated: Bool) {
    2.26 @@ -115,7 +106,17 @@
    2.27  
    2.28      // MARK: - SETUP
    2.29  
    2.30 -    internal func configureView() {
    2.31 +    private func setuptoolbar() {
    2.32 +        let item = UIBarButtonItem.getpEpButton(action: #selector(self.showSettingsViewController(_:)),
    2.33 +                                                target: self)
    2.34 +        let flexibleSpace: UIBarButtonItem = UIBarButtonItem(
    2.35 +            barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace,
    2.36 +            target: nil,
    2.37 +            action: nil)
    2.38 +        self.toolbarItems?.append(contentsOf: [flexibleSpace,item])
    2.39 +    }
    2.40 +
    2.41 +    func configureView() {
    2.42          // Make sure the NavigationBar is shown, even if the previous view has hidden it.
    2.43          navigationController?.setNavigationBarHidden(false, animated: false)
    2.44  
    2.45 @@ -220,7 +221,7 @@
    2.46                  Log.shared.errorAndCrash(component: #function, errorString: "Cast error")
    2.47                  return SecureWebViewController()
    2.48          }
    2.49 -        vc.scrollingEnabled = false
    2.50 +        vc.zoomingEnabled = true
    2.51          vc.delegate = self
    2.52          vc.urlClickHandler = clickHandler
    2.53          htmlViewerViewControllerExists = true
     3.1 --- a/pEpForiOS/UI/EmailDisplayList/EmailListViewController.swift	Wed Aug 15 14:19:50 2018 +0200
     3.2 +++ b/pEpForiOS/UI/EmailDisplayList/EmailListViewController.swift	Thu Aug 16 06:37:34 2018 +0200
     3.3 @@ -56,52 +56,18 @@
     3.4          action: nil)
     3.5      
     3.6      // MARK: - Life Cycle
     3.7 -    
     3.8 -    fileprivate func setUpTextFilter() {
     3.9 -        self.textFilterButton.isEnabled = false
    3.10 -        self.textFilterButton.action = #selector(self.showFilterOptions(_:))
    3.11 -        self.textFilterButton.target = self
    3.12 -
    3.13 -        let fontSize:CGFloat = 10;
    3.14 -        let font:UIFont = UIFont.boldSystemFont(ofSize: fontSize);
    3.15 -        let attributes = [NSAttributedStringKey.font: font];
    3.16 -
    3.17 -        self.textFilterButton.setTitleTextAttributes(attributes, for: UIControlState.normal)
    3.18 -    }
    3.19  
    3.20      override func viewDidLoad() {
    3.21          super.viewDidLoad()
    3.22  
    3.23          UIHelper.emailListTableHeight(self.tableView)
    3.24  
    3.25 -        configureSearchBar()
    3.26          tableView.allowsMultipleSelectionDuringEditing = true
    3.27 +
    3.28          if #available(iOS 10.0, *) {
    3.29              tableView.prefetchDataSource = self
    3.30          }
    3.31 -        if #available(iOS 11.0, *) {
    3.32 -            searchController.isActive = false
    3.33 -            self.navigationItem.searchController = searchController
    3.34 -            self.navigationItem.hidesSearchBarWhenScrolling = true
    3.35 -        } else {
    3.36 -            addSearchBar10()
    3.37 -
    3.38 -            if tableView.tableHeaderView == nil {
    3.39 -                tableView.tableHeaderView = searchController.searchBar
    3.40 -            }
    3.41 -
    3.42 -            // some notifications to control when the app enter and recover from background
    3.43 -            NotificationCenter.default.addObserver(
    3.44 -                self,
    3.45 -                selector: #selector(didBecomeActiveInstallSearchBar10),
    3.46 -                name: NSNotification.Name.UIApplicationDidBecomeActive,
    3.47 -                object: nil)
    3.48 -            NotificationCenter.default.addObserver(
    3.49 -                self,
    3.50 -                selector: #selector(didBecomeInactiveUninstallSearchbar10),
    3.51 -                name: NSNotification.Name.UIApplicationDidEnterBackground,
    3.52 -                object: nil)
    3.53 -        }
    3.54 +        setupSearchBar()
    3.55          setup()
    3.56      }
    3.57  
    3.58 @@ -125,33 +91,10 @@
    3.59      }
    3.60  
    3.61      deinit {
    3.62 -        NotificationCenter.default.removeObserver(
    3.63 -            self,
    3.64 -            name: NSNotification.Name.UIApplicationDidBecomeActive,
    3.65 -            object: nil)
    3.66 -        NotificationCenter.default.removeObserver(
    3.67 -            self,
    3.68 -            name: NSNotification.Name.UIApplicationDidEnterBackground,
    3.69 -            object: nil)
    3.70 -    }
    3.71 -
    3.72 -    /**
    3.73 -     Showing the search controller in versions iOS 10 and earlier.
    3.74 -     */
    3.75 -    @objc func didBecomeActiveInstallSearchBar10() {
    3.76 -        if tableView.tableHeaderView == nil {
    3.77 -            tableView.tableHeaderView = searchController.searchBar
    3.78 -        }
    3.79 -    }
    3.80 -
    3.81 -    /**
    3.82 -     Hide/remove the search controller in versions iOS 10 and earlier.
    3.83 -     */
    3.84 -    @objc func didBecomeInactiveUninstallSearchbar10() {
    3.85 -        tableView.tableHeaderView = nil
    3.86 +         NotificationCenter.default.removeObserver(self)
    3.87      }
    3.88      
    3.89 -    // MARK: - NavigationBar
    3.90 +    // MARK: - Setup
    3.91      
    3.92      private func resetModel() {
    3.93          if let theFolder = folderToShow {
    3.94 @@ -165,7 +108,7 @@
    3.95              model?.screenComposer =  screenComposer
    3.96          }
    3.97      }
    3.98 -    
    3.99 +
   3.100      private func setup() {
   3.101          if noAccountsExist() {
   3.102              // No account exists. Show account setup.
   3.103 @@ -197,15 +140,47 @@
   3.104              action: nil)
   3.105          self.toolbarItems?.append(contentsOf: [flexibleSpace,item])
   3.106          self.navigationController?.title = title
   3.107 -
   3.108      }
   3.109  
   3.110 -    private func weCameBackFromAPushedView() -> Bool {
   3.111 -        return model != nil
   3.112 +    private func setUpTextFilter() {
   3.113 +        self.textFilterButton.isEnabled = false
   3.114 +        self.textFilterButton.action = #selector(self.showFilterOptions(_:))
   3.115 +        self.textFilterButton.target = self
   3.116 +
   3.117 +        let fontSize:CGFloat = 10;
   3.118 +        let font:UIFont = UIFont.boldSystemFont(ofSize: fontSize);
   3.119 +        let attributes = [NSAttributedStringKey.font: font];
   3.120 +
   3.121 +        self.textFilterButton.setTitleTextAttributes(attributes, for: UIControlState.normal)
   3.122      }
   3.123 -    
   3.124 -    private func noAccountsExist() -> Bool {
   3.125 -        return Account.all().isEmpty
   3.126 +
   3.127 +    // MARK: - Search Bar
   3.128 +
   3.129 +    private func setupSearchBar() {
   3.130 +        configureSearchBar()
   3.131 +        if #available(iOS 11.0, *) {
   3.132 +            searchController.isActive = false
   3.133 +            self.navigationItem.searchController = searchController
   3.134 +            self.navigationItem.hidesSearchBarWhenScrolling = true
   3.135 +        } else {
   3.136 +            addSearchBar10()
   3.137 +
   3.138 +            if tableView.tableHeaderView == nil {
   3.139 +                tableView.tableHeaderView = searchController.searchBar
   3.140 +            }
   3.141 +
   3.142 +            // some notifications to control when the app enter and recover from background
   3.143 +            NotificationCenter.default.addObserver(
   3.144 +                self,
   3.145 +                selector: #selector(didBecomeActiveInstallSearchBar10),
   3.146 +                name: NSNotification.Name.UIApplicationDidBecomeActive,
   3.147 +                object: nil)
   3.148 +            NotificationCenter.default.addObserver(
   3.149 +                self,
   3.150 +                selector: #selector(didBecomeInactiveUninstallSearchbar10),
   3.151 +                name: NSNotification.Name.UIApplicationDidEnterBackground,
   3.152 +                object: nil)
   3.153 +        }
   3.154      }
   3.155  
   3.156      /**
   3.157 @@ -218,6 +193,22 @@
   3.158      }
   3.159  
   3.160      /**
   3.161 +     Showing the search controller in versions iOS 10 and earlier.
   3.162 +     */
   3.163 +    @objc func didBecomeActiveInstallSearchBar10() {
   3.164 +        if tableView.tableHeaderView == nil {
   3.165 +            tableView.tableHeaderView = searchController.searchBar
   3.166 +        }
   3.167 +    }
   3.168 +
   3.169 +    /**
   3.170 +     Hide/remove the search controller in versions iOS 10 and earlier.
   3.171 +     */
   3.172 +    @objc func didBecomeInactiveUninstallSearchbar10() {
   3.173 +        tableView.tableHeaderView = nil
   3.174 +    }
   3.175 +
   3.176 +    /**
   3.177       Add the search bar when running on iOS 10 or earlier.
   3.178       */
   3.179      private func addSearchBar10() {
   3.180 @@ -230,6 +221,14 @@
   3.181      
   3.182      // MARK: - Other
   3.183  
   3.184 +    private func weCameBackFromAPushedView() -> Bool {
   3.185 +        return model != nil
   3.186 +    }
   3.187 +
   3.188 +    private func noAccountsExist() -> Bool {
   3.189 +        return Account.all().isEmpty
   3.190 +    }
   3.191 +
   3.192      private func showComposeView() {
   3.193          self.performSegue(withIdentifier: SegueIdentifier.segueEditDraft, sender: self)
   3.194      }
     4.1 --- a/pEpForiOS/UI/Thread/Cells/FullMessageCell.swift	Wed Aug 15 14:19:50 2018 +0200
     4.2 +++ b/pEpForiOS/UI/Thread/Cells/FullMessageCell.swift	Thu Aug 16 06:37:34 2018 +0200
     4.3 @@ -122,6 +122,7 @@
     4.4                  Log.shared.errorAndCrash(component: #function, errorString: "Cast error")
     4.5                  return SecureWebViewController()
     4.6          }
     4.7 +        vc.zoomingEnabled = false
     4.8          vc.scrollingEnabled = false
     4.9          vc.delegate = self
    4.10          vc.urlClickHandler = clickHandler
     5.1 --- a/pEpForiOS/UI/Thread/ThreadViewController.swift	Wed Aug 15 14:19:50 2018 +0200
     5.2 +++ b/pEpForiOS/UI/Thread/ThreadViewController.swift	Thu Aug 16 06:37:34 2018 +0200
     5.3 @@ -27,6 +27,7 @@
     5.4  
     5.5      override func viewDidLoad() {
     5.6          super.viewDidLoad()
     5.7 +        assureNavigationBarVisible()
     5.8          configureSplitViewBackButton()
     5.9          guard let model = model else {
    5.10              return
    5.11 @@ -36,11 +37,6 @@
    5.12          setUpFlaggedStatus()
    5.13      }
    5.14  
    5.15 -    override func didReceiveMemoryWarning() {
    5.16 -        super.didReceiveMemoryWarning()
    5.17 -        // Dispose of any resources that can be recreated.
    5.18 -    }
    5.19 -
    5.20      @IBAction func segueUnwindEmailDisplayDone(segue:UIStoryboardSegue) {
    5.21          //do nothing
    5.22      }
    5.23 @@ -55,12 +51,18 @@
    5.24          }
    5.25      }
    5.26  
    5.27 +    private func assureNavigationBarVisible() {
    5.28 +        // When pushed from a ViewController with active SearchBar, the navigation bar might be
    5.29 +        // hidden.
    5.30 +        navigationController?.isNavigationBarHidden = false
    5.31 +    }
    5.32 +
    5.33      private func configureSplitViewBackButton() {
    5.34          self.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem
    5.35          self.navigationItem.leftItemsSupplementBackButton = true
    5.36      }
    5.37  
    5.38 -    internal func isSplitViewControllerCollapsed() -> Bool! {
    5.39 +    func isSplitViewControllerCollapsed() -> Bool! {
    5.40          guard let splitViewController = self.splitViewController else {
    5.41              Log.shared.errorAndCrash(component: #function, errorString: "We need a splitViewController here")
    5.42              return nil
     6.1 --- a/pEpForiOS/UI/Util/SecureWebViewController/SecureWebViewController.swift	Wed Aug 15 14:19:50 2018 +0200
     6.2 +++ b/pEpForiOS/UI/Util/SecureWebViewController/SecureWebViewController.swift	Thu Aug 16 06:37:34 2018 +0200
     6.3 @@ -9,7 +9,7 @@
     6.4  import WebKit
     6.5  
     6.6  protocol SecureWebViewControllerDelegate: class {
     6.7 -    /// Called after the webview has finished loadding and layouting its subviews.
     6.8 +    /// Called on content size changes while within loading time.
     6.9      /// - Parameters:
    6.10      ///   - webViewController: calling view controller
    6.11      ///   - sizeChangedTo: webview.scrollview.contentSize after loading html content and layouting
    6.12 @@ -32,18 +32,25 @@
    6.13  /// Note: It is insecure to use this class on iOS < 11. Thus it will intentionally take the
    6.14  /// emergency exit and crash when trying to use it running iOS < 11.
    6.15  class SecureWebViewController: UIViewController {
    6.16 -    private var webView: WKWebView!
    6.17 -    private var sizeChangeObserver: NSKeyValueObservation?
    6.18 +    static let storyboardId = "SecureWebViewController"
    6.19  
    6.20 -    static var isSaveToUseWebView: Bool {
    6.21 -        if #available(iOS 11.0, *) {
    6.22 -            return true
    6.23 +    weak var delegate: SecureWebViewControllerDelegate?
    6.24 +    weak var urlClickHandler: SecureWebViewUrlClickHandlerProtocol?
    6.25 +
    6.26 +    var zoomingEnabled: Bool = true
    6.27 +
    6.28 +    private var _userInteractionEnabled: Bool = true
    6.29 +    var userInteractionEnabled: Bool {
    6.30 +        get {
    6.31 +            return _userInteractionEnabled
    6.32          }
    6.33 -        return false
    6.34 +        set {
    6.35 +            _userInteractionEnabled = newValue
    6.36 +            if let wv = webView {
    6.37 +                wv.scrollView.isUserInteractionEnabled = _userInteractionEnabled
    6.38 +            }
    6.39 +        }
    6.40      }
    6.41 -    static let storyboardId = "SecureWebViewController"
    6.42 -    /// webview.scrollView.contentSize after html has finished loading and layouting
    6.43 -    private(set) var contentSize: CGSize?
    6.44  
    6.45      private var _scrollingEnabled: Bool = true
    6.46      var scrollingEnabled: Bool {
    6.47 @@ -57,8 +64,25 @@
    6.48              }
    6.49          }
    6.50      }
    6.51 -    weak var delegate: SecureWebViewControllerDelegate?
    6.52 -    weak var urlClickHandler: SecureWebViewUrlClickHandlerProtocol?
    6.53 +
    6.54 +    static var isSaveToUseWebView: Bool {
    6.55 +        if #available(iOS 11.0, *) {
    6.56 +            return true
    6.57 +        }
    6.58 +        return false
    6.59 +    }
    6.60 +
    6.61 +    private var webView: WKWebView!
    6.62 +    private var sizeChangeObserver: NSKeyValueObservation?
    6.63 +
    6.64 +    /// webview.scrollView.contentSize after html has finished loading and layouting
    6.65 +    private(set) var contentSize: CGSize?
    6.66 +
    6.67 +    /// Assumed max time it can take to load a page.
    6.68 +    /// After this time content size changes are not reported any more.
    6.69 +    static private let maxLoadingTime: TimeInterval = 0.1
    6.70 +    /// Last time a size change has been reported to
    6.71 +    private var lastReportedSizeUpdate: Date?
    6.72  
    6.73      // MARK: - Life Cycle
    6.74  
    6.75 @@ -90,7 +114,9 @@
    6.76          CidHandler.setup(config: config)
    6.77          webView = WKWebView(frame: .zero, configuration: config)
    6.78          webView.navigationDelegate = self
    6.79 +         webView.scrollView.delegate = self
    6.80          webView.scrollView.isScrollEnabled = scrollingEnabled
    6.81 +        webView.scrollView.isUserInteractionEnabled = userInteractionEnabled
    6.82          view = webView
    6.83      }
    6.84  
    6.85 @@ -186,6 +212,17 @@
    6.86      }
    6.87  
    6.88      // MARK: - Handle Content Size Changes
    6.89 +
    6.90 +    private var isContentLoadedAndLayouted: Bool {
    6.91 +        if let sinceUpdate = lastReportedSizeUpdate?.timeIntervalSinceNow,
    6.92 +            -sinceUpdate > SecureWebViewController.maxLoadingTime {
    6.93 +            // We assuem initial loading is done.
    6.94 +            // The size change must be zooming triggered by user.
    6.95 +            return true
    6.96 +        }
    6.97 +        return false
    6.98 +    }
    6.99 +
   6.100      private func informDelegateAfterLoadingFinished() {
   6.101          // code to run whenever the content(size) changes
   6.102          let handler = {
   6.103 @@ -194,12 +231,20 @@
   6.104                  Log.shared.errorAndCrash(component: #function, errorString: "Lost myself")
   6.105                  return
   6.106              }
   6.107 +
   6.108 +            if me.isContentLoadedAndLayouted {
   6.109 +                // We assuem initial loading is done.
   6.110 +                // The size change must be zooming triggered by user.
   6.111 +                return
   6.112 +            }
   6.113 +
   6.114              guard
   6.115                  let contentSize = change.newValue,
   6.116                  !me.shouldIgnoreContentSizeChange(newSize: contentSize) else {
   6.117                      return
   6.118              }
   6.119              me.contentSize = contentSize
   6.120 +            me.lastReportedSizeUpdate = Date()
   6.121              me.delegate?.secureWebViewController(me, sizeChangedTo: contentSize)
   6.122          }
   6.123          sizeChangeObserver = webView.scrollView.observe(\UIScrollView.contentSize,
   6.124 @@ -225,7 +270,7 @@
   6.125      /// Prepares the html string for displaying.
   6.126      ///
   6.127      /// - Parameter html: html to prepare
   6.128 -    /// - Returns: html ready for diplaying
   6.129 +    /// - Returns: html ready for displaying
   6.130      private func preprocess(html: String) -> String {
   6.131          var result = html
   6.132          result = htmlTagsAssured(html: result)
   6.133 @@ -354,6 +399,14 @@
   6.134      }
   6.135  }
   6.136  
   6.137 +// MARK: - UIScrollViewDelegate
   6.138 +
   6.139 +extension SecureWebViewController: UIScrollViewDelegate {
   6.140 +    func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
   6.141 +        scrollView.pinchGestureRecognizer?.isEnabled = isContentLoadedAndLayouted && zoomingEnabled
   6.142 +    }
   6.143 +}
   6.144 +
   6.145  // MARK: -
   6.146  // MARK: !! EXTREMELY DIRTY HACK !! ( START )
   6.147  
     7.1 --- a/pEpForiOS/de.lproj/Main.strings	Wed Aug 15 14:19:50 2018 +0200
     7.2 +++ b/pEpForiOS/de.lproj/Main.strings	Thu Aug 16 06:37:34 2018 +0200
     7.3 @@ -38,7 +38,7 @@
     7.4  "oWA-cC-IZF.normalTitle" = "Abmelden";
     7.5  
     7.6  /* Class = "UINavigationItem"; title = "Title"; ObjectID = "PAv-Od-zv3"; */
     7.7 -"PAv-Od-zv3.title" = "Titel";
     7.8 +"PAv-Od-zv3.title" = "";
     7.9  
    7.10  /* Class = "UIBarButtonItem"; title = "Cancel"; ObjectID = "RnR-fE-Pxv"; */
    7.11  "RnR-fE-Pxv.title" = "";