Skip to content

Instantly share code, notes, and snippets.

@nbhasin2
Created June 12, 2020 23:42
Show Gist options
  • Select an option

  • Save nbhasin2/b70548933d37a144daa3308e2ea6cee0 to your computer and use it in GitHub Desktop.

Select an option

Save nbhasin2/b70548933d37a144daa3308e2ea6cee0 to your computer and use it in GitHub Desktop.
diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj
index b0a2f2129..a1345ccc4 100644
--- a/Client.xcodeproj/project.pbxproj
+++ b/Client.xcodeproj/project.pbxproj
@@ -252,6 +252,8 @@
435D7CC02461EFCB0043ACB9 /* IntroScreenWelcomeViewV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435D7CBF2461EFCB0043ACB9 /* IntroScreenWelcomeViewV2.swift */; };
435D7CC32461EFDD0043ACB9 /* IntroScreenSyncViewV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435D7CC22461EFDD0043ACB9 /* IntroScreenSyncViewV2.swift */; };
435D7CC5246209AA0043ACB9 /* IntroViewControllerV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435D7CC4246209AA0043ACB9 /* IntroViewControllerV2.swift */; };
+ 4360D9AC24943AF10041EE16 /* ListSelectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4360D9AB24943AF10041EE16 /* ListSelectionController.swift */; };
+ 4360D9AF24943C220041EE16 /* LoginDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4360D9AE24943C220041EE16 /* LoginDataSource.swift */; };
4390F7F1246C76E700570811 /* IntroWelcomeAndSyncViewV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4390F7F0246C76E700570811 /* IntroWelcomeAndSyncViewV1.swift */; };
4390F7F5246CE04300570811 /* IntroViewModelV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4390F7F4246CE04300570811 /* IntroViewModelV2.swift */; };
4390F7FF246DAFBE00570811 /* FirefoxColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4390F7FE246DAFBE00570811 /* FirefoxColors.swift */; };
@@ -1400,6 +1402,8 @@
435D7CC22461EFDD0043ACB9 /* IntroScreenSyncViewV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroScreenSyncViewV2.swift; sourceTree = "<group>"; };
435D7CC4246209AA0043ACB9 /* IntroViewControllerV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroViewControllerV2.swift; sourceTree = "<group>"; };
435FAB17242404B400AE9310 /* FullscreenHelper.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = FullscreenHelper.js; path = Client/Frontend/UserContent/UserScripts/AllFrames/AtDocumentStart/FullscreenHelper.js; sourceTree = SOURCE_ROOT; };
+ 4360D9AB24943AF10041EE16 /* ListSelectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListSelectionController.swift; sourceTree = "<group>"; };
+ 4360D9AE24943C220041EE16 /* LoginDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginDataSource.swift; sourceTree = "<group>"; };
4390F7F0246C76E700570811 /* IntroWelcomeAndSyncViewV1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroWelcomeAndSyncViewV1.swift; sourceTree = "<group>"; };
4390F7F4246CE04300570811 /* IntroViewModelV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroViewModelV2.swift; sourceTree = "<group>"; };
4390F7FE246DAFBE00570811 /* FirefoxColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirefoxColors.swift; sourceTree = "<group>"; };
@@ -3135,6 +3139,8 @@
E63ED7D71BFCD9990097D08E /* LoginTableViewCell.swift */,
E63ED8E01BFD25580097D08E /* LoginListViewController.swift */,
CA520E7924913C1B00CCAB48 /* LoginListViewModel.swift */,
+ 4360D9AB24943AF10041EE16 /* ListSelectionController.swift */,
+ 4360D9AE24943C220041EE16 /* LoginDataSource.swift */,
E633E2D91C21EAF8001FFF6C /* LoginDetailViewController.swift */,
CA77ABF424772D98005079F9 /* BreachAlertsManager.swift */,
CA03B269247F1D9E00382B62 /* BreachAlertsClient.swift */,
@@ -5123,6 +5129,7 @@
D87F84AC20B891160091F2DA /* TabDisplayManager.swift in Sources */,
D0C95EF6201A55A800E4E51C /* BrowserViewController+UIDropInteractionDelegate.swift in Sources */,
D31CF65C1CC1959A001D0BD0 /* PrivilegedRequest.swift in Sources */,
+ 4360D9AF24943C220041EE16 /* LoginDataSource.swift in Sources */,
D8D33A7D1FBD080300A20A28 /* SnapKitExtensions.swift in Sources */,
E650755C1E37F747006961AC /* Swizzling.m in Sources */,
74821FC51DB56A2500EEEA72 /* OpenWithSettingsViewController.swift in Sources */,
@@ -5171,6 +5178,7 @@
E6927EC01C7B6FB800D03F75 /* ErrorToast.swift in Sources */,
D30B101E1AA7F9C600C01CA3 /* LibraryPanels.swift in Sources */,
F84B22041A0910F600AAB793 /* AppDelegate.swift in Sources */,
+ 4360D9AC24943AF10041EE16 /* ListSelectionController.swift in Sources */,
D8C75DF3207584C400BB8AD0 /* UIImageViewAligned.m in Sources */,
E653422D1C5944F90039DD9E /* BrowserPrompts.swift in Sources */,
2FDE87FE1ABB3817005317B1 /* RemoteTabsPanel.swift in Sources */,
diff --git a/Client/Frontend/Login Management/ListSelectionController.swift b/Client/Frontend/Login Management/ListSelectionController.swift
new file mode 100644
index 000000000..9408abfa5
--- /dev/null
+++ b/Client/Frontend/Login Management/ListSelectionController.swift
@@ -0,0 +1,47 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import Foundation
+
+/// Controller that keeps track of selected indexes
+class ListSelectionController: NSObject {
+ private unowned let tableView: UITableView
+ private(set) var selectedIndexPaths = [IndexPath]()
+
+ var selectedCount: Int {
+ return selectedIndexPaths.count
+ }
+
+ init(tableView: UITableView) {
+ self.tableView = tableView
+ super.init()
+ }
+
+ func selectIndexPath(_ indexPath: IndexPath) {
+ selectedIndexPaths.append(indexPath)
+ }
+
+ func indexPathIsSelected(_ indexPath: IndexPath) -> Bool {
+ return selectedIndexPaths.contains(indexPath) { path1, path2 in
+ return path1.row == path2.row && path1.section == path2.section
+ }
+ }
+
+ func deselectIndexPath(_ indexPath: IndexPath) {
+ guard let foundSelectedPath = (selectedIndexPaths.filter { $0.row == indexPath.row && $0.section == indexPath.section }).first,
+ let indexToRemove = selectedIndexPaths.firstIndex(of: foundSelectedPath) else {
+ return
+ }
+
+ selectedIndexPaths.remove(at: indexToRemove)
+ }
+
+ func deselectAll() {
+ selectedIndexPaths.removeAll()
+ }
+
+ func selectIndexPaths(_ indexPaths: [IndexPath]) {
+ selectedIndexPaths += indexPaths
+ }
+}
diff --git a/Client/Frontend/Login Management/LoginDataSource.swift b/Client/Frontend/Login Management/LoginDataSource.swift
new file mode 100644
index 000000000..06832e6cf
--- /dev/null
+++ b/Client/Frontend/Login Management/LoginDataSource.swift
@@ -0,0 +1,76 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import UIKit
+import Storage
+import Shared
+import Foundation
+
+/// Data source for handling LoginData objects from a Cursor
+class LoginDataSource: NSObject, UITableViewDataSource {
+ fileprivate let emptyStateView = NoLoginsView()
+ fileprivate var viewModel: LoginListViewModel
+
+ let boolSettings: (BoolSetting, BoolSetting)
+
+ init(viewModel: LoginListViewModel) {
+ self.viewModel = viewModel
+ boolSettings = (
+ BoolSetting(prefs: viewModel.profile.prefs, prefKey: PrefsKeys.LoginsSaveEnabled, defaultValue: true, attributedTitleText: NSAttributedString(string: Strings.SettingToSaveLogins)),
+ BoolSetting(prefs: viewModel.profile.prefs, prefKey: PrefsKeys.LoginsShowShortcutMenuItem, defaultValue: true, attributedTitleText: NSAttributedString(string: Strings.SettingToShowLoginsInAppMenu)))
+ super.init()
+ }
+
+ @objc func numberOfSections(in tableView: UITableView) -> Int {
+ if viewModel.dataSourceViewModel.loginRecordSections.isEmpty {
+ tableView.backgroundView = emptyStateView
+ return 1
+ }
+
+ tableView.backgroundView = nil
+ // Add one section for the settings section.
+ return viewModel.dataSourceViewModel.loginRecordSections.count + 1
+ }
+
+ @objc func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ if section == LoginsSettingsSection {
+ return 2
+ }
+ return viewModel.dataSourceViewModel.loginsForSection(section)?.count ?? 0
+ }
+
+ @objc func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ let cell = ThemedTableViewCell(style: .subtitle, reuseIdentifier: CellReuseIdentifier)
+
+ if indexPath.section == LoginsSettingsSection {
+ let hideSettings = viewModel.dataSourceViewModel.searchController?.isActive ?? false || tableView.isEditing
+ let setting = indexPath.row == 0 ? boolSettings.0 : boolSettings.1
+ setting.onConfigureCell(cell)
+ if hideSettings {
+ cell.isHidden = true
+ }
+
+ // Fade in the cell while dismissing the search or the cell showing suddenly looks janky
+ if viewModel.isDuringSearchControllerDismiss {
+ cell.isHidden = false
+ cell.contentView.alpha = 0
+ cell.accessoryView?.alpha = 0
+ UIView.animate(withDuration: 0.6) {
+ cell.contentView.alpha = 1
+ cell.accessoryView?.alpha = 1
+ }
+ }
+ } else {
+ guard let login = viewModel.dataSourceViewModel.loginAtIndexPath(indexPath) else { return cell }
+ cell.textLabel?.text = login.hostname
+ cell.detailTextColor = UIColor.theme.tableView.rowDetailText
+ cell.detailTextLabel?.text = login.username
+ cell.accessoryType = .disclosureIndicator
+ }
+ // Need to override the default background multi-select color to support theming
+ cell.multipleSelectionBackgroundView = UIView()
+ cell.applyTheme()
+ return cell
+ }
+}
diff --git a/Client/Frontend/Login Management/LoginListViewController.swift b/Client/Frontend/Login Management/LoginListViewController.swift
index 89d98b204..5aafa2762 100644
--- a/Client/Frontend/Login Management/LoginListViewController.swift
+++ b/Client/Frontend/Login Management/LoginListViewController.swift
@@ -18,9 +18,9 @@ private extension UITableView {
}
}
-private let CellReuseIdentifier = "cell-reuse-id"
-private let SectionHeaderId = "section-header-id"
-private let LoginsSettingsSection = 0
+let CellReuseIdentifier = "cell-reuse-id"
+let SectionHeaderId = "section-header-id"
+let LoginsSettingsSection = 0
class LoginListViewController: SensitiveViewController {
@@ -241,15 +241,13 @@ extension LoginListViewController: UISearchResultsUpdating {
}
}
-fileprivate var isDuringSearchControllerDismiss = false
-
extension LoginListViewController: UISearchControllerDelegate {
func willDismissSearchController(_ searchController: UISearchController) {
- isDuringSearchControllerDismiss = true
+ viewModel.isDuringSearchControllerDismiss = true
}
func didDismissSearchController(_ searchController: UISearchController) {
- isDuringSearchControllerDismiss = false
+ viewModel.isDuringSearchControllerDismiss = false
}
}
@@ -431,112 +429,3 @@ extension LoginListViewController: SearchInputViewDelegate {
}
}
-/// Controller that keeps track of selected indexes
-fileprivate class ListSelectionController: NSObject {
- private unowned let tableView: UITableView
- private(set) var selectedIndexPaths = [IndexPath]()
-
- var selectedCount: Int {
- return selectedIndexPaths.count
- }
-
- init(tableView: UITableView) {
- self.tableView = tableView
- super.init()
- }
-
- func selectIndexPath(_ indexPath: IndexPath) {
- selectedIndexPaths.append(indexPath)
- }
-
- func indexPathIsSelected(_ indexPath: IndexPath) -> Bool {
- return selectedIndexPaths.contains(indexPath) { path1, path2 in
- return path1.row == path2.row && path1.section == path2.section
- }
- }
-
- func deselectIndexPath(_ indexPath: IndexPath) {
- guard let foundSelectedPath = (selectedIndexPaths.filter { $0.row == indexPath.row && $0.section == indexPath.section }).first,
- let indexToRemove = selectedIndexPaths.firstIndex(of: foundSelectedPath) else {
- return
- }
-
- selectedIndexPaths.remove(at: indexToRemove)
- }
-
- func deselectAll() {
- selectedIndexPaths.removeAll()
- }
-
- func selectIndexPaths(_ indexPaths: [IndexPath]) {
- selectedIndexPaths += indexPaths
- }
-}
-
-/// Data source for handling LoginData objects from a Cursor
-class LoginDataSource: NSObject, UITableViewDataSource {
- fileprivate let emptyStateView = NoLoginsView()
- fileprivate var viewModel: LoginListViewModel
-
- let boolSettings: (BoolSetting, BoolSetting)
-
- init(viewModel: LoginListViewModel) {
- self.viewModel = viewModel
- boolSettings = (
- BoolSetting(prefs: viewModel.profile.prefs, prefKey: PrefsKeys.LoginsSaveEnabled, defaultValue: true, attributedTitleText: NSAttributedString(string: Strings.SettingToSaveLogins)),
- BoolSetting(prefs: viewModel.profile.prefs, prefKey: PrefsKeys.LoginsShowShortcutMenuItem, defaultValue: true, attributedTitleText: NSAttributedString(string: Strings.SettingToShowLoginsInAppMenu)))
- super.init()
- }
-
- @objc func numberOfSections(in tableView: UITableView) -> Int {
- if viewModel.dataSourceViewModel.loginRecordSections.isEmpty {
- tableView.backgroundView = emptyStateView
- return 1
- }
-
- tableView.backgroundView = nil
- // Add one section for the settings section.
- return viewModel.dataSourceViewModel.loginRecordSections.count + 1
- }
-
- @objc func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- if section == LoginsSettingsSection {
- return 2
- }
- return viewModel.dataSourceViewModel.loginsForSection(section)?.count ?? 0
- }
-
- @objc func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let cell = ThemedTableViewCell(style: .subtitle, reuseIdentifier: CellReuseIdentifier)
-
- if indexPath.section == LoginsSettingsSection {
- let hideSettings = viewModel.dataSourceViewModel.searchController?.isActive ?? false || tableView.isEditing
- let setting = indexPath.row == 0 ? boolSettings.0 : boolSettings.1
- setting.onConfigureCell(cell)
- if hideSettings {
- cell.isHidden = true
- }
-
- // Fade in the cell while dismissing the search or the cell showing suddenly looks janky
- if isDuringSearchControllerDismiss {
- cell.isHidden = false
- cell.contentView.alpha = 0
- cell.accessoryView?.alpha = 0
- UIView.animate(withDuration: 0.6) {
- cell.contentView.alpha = 1
- cell.accessoryView?.alpha = 1
- }
- }
- } else {
- guard let login = viewModel.dataSourceViewModel.loginAtIndexPath(indexPath) else { return cell }
- cell.textLabel?.text = login.hostname
- cell.detailTextColor = UIColor.theme.tableView.rowDetailText
- cell.detailTextLabel?.text = login.username
- cell.accessoryType = .disclosureIndicator
- }
- // Need to override the default background multi-select color to support theming
- cell.multipleSelectionBackgroundView = UIView()
- cell.applyTheme()
- return cell
- }
-}
diff --git a/Client/Frontend/Login Management/LoginListViewModel.swift b/Client/Frontend/Login Management/LoginListViewModel.swift
index 83425a6ae..5068c9943 100644
--- a/Client/Frontend/Login Management/LoginListViewModel.swift
+++ b/Client/Frontend/Login Management/LoginListViewModel.swift
@@ -13,6 +13,10 @@ final class LoginListViewModel {
let profile: Profile
fileprivate var activeLoginQuery: Deferred<Maybe<[LoginRecord]>>?
var dataSourceViewModel: LoginListDataSourceViewModel
+// fileprivate lazy var loginSelectionController: ListSelectionController = {
+// return ListSelectionController(tableView: self.tableView)
+// }()
+ var isDuringSearchControllerDismiss = false
init(profile: Profile, searchController: UISearchController) {
self.profile = profile
diff --git a/Client/Frontend/Login Management/NoLoginsView.swift b/Client/Frontend/Login Management/NoLoginsView.swift
index ea6f67eb1..df7929fca 100644
--- a/Client/Frontend/Login Management/NoLoginsView.swift
+++ b/Client/Frontend/Login Management/NoLoginsView.swift
@@ -1,11 +1,6 @@
-//
-// NoLoginsView.swift
-// Client
-//
-// Created by Vanna Phong on 6/11/20.
-// Copyright © 2020 Mozilla. All rights reserved.
-//
-
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
/// Empty state view when there is no logins to display.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment