-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathClearPrivateDataTableViewController.swift
176 lines (142 loc) · 7.05 KB
/
ClearPrivateDataTableViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/* 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 Shared
private let SectionToggles = 0
private let SectionButton = 1
private let NumberOfSections = 2
private let SectionHeaderFooterIdentifier = "SectionHeaderFooterIdentifier"
private let TogglesPrefKey = "clearprivatedata.toggles"
private let log = Logger.browserLogger
private let HistoryClearableIndex = 0
class ClearPrivateDataTableViewController: UITableViewController {
fileprivate var clearButton: UITableViewCell?
var profile: Profile!
var tabManager: TabManager!
fileprivate typealias DefaultCheckedState = Bool
fileprivate lazy var clearables: [(clearable: Clearable, checked: DefaultCheckedState)] = {
return [
(HistoryClearable(profile: self.profile), true),
(CacheClearable(tabManager: self.tabManager), true),
(CookiesClearable(tabManager: self.tabManager), true),
(SiteDataClearable(tabManager: self.tabManager), true),
]
}()
fileprivate lazy var toggles: [Bool] = {
if let savedToggles = self.profile.prefs.arrayForKey(TogglesPrefKey) as? [Bool] {
return savedToggles
}
return self.clearables.map { $0.checked }
}()
fileprivate var clearButtonEnabled = true {
didSet {
clearButton?.textLabel?.textColor = clearButtonEnabled ? UIConstants.DestructiveRed : UIColor.lightGray
}
}
override func viewDidLoad() {
super.viewDidLoad()
title = Strings.SettingsClearPrivateDataTitle
tableView.register(SettingsTableSectionHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: SectionHeaderFooterIdentifier)
tableView.separatorColor = UIConstants.TableViewSeparatorColor
tableView.backgroundColor = UIConstants.TableViewHeaderBackgroundColor
let footer = SettingsTableSectionHeaderFooterView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: UIConstants.TableViewHeaderFooterHeight))
footer.showBottomBorder = false
tableView.tableFooterView = footer
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: nil)
if indexPath.section == SectionToggles {
cell.textLabel?.text = clearables[indexPath.item].clearable.label
let control = UISwitch()
control.onTintColor = UIConstants.ControlTintColor
control.addTarget(self, action: #selector(ClearPrivateDataTableViewController.switchValueChanged(_:)), for: UIControlEvents.valueChanged)
control.isOn = toggles[indexPath.item]
cell.accessoryView = control
cell.selectionStyle = .none
control.tag = indexPath.item
} else {
assert(indexPath.section == SectionButton)
cell.textLabel?.text = Strings.SettingsClearPrivateDataClearButton
cell.textLabel?.textAlignment = NSTextAlignment.center
cell.textLabel?.textColor = UIConstants.DestructiveRed
cell.accessibilityTraits = UIAccessibilityTraitButton
cell.accessibilityIdentifier = "ClearPrivateData"
clearButton = cell
}
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int {
return NumberOfSections
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == SectionToggles {
return clearables.count
}
assert(section == SectionButton)
return 1
}
override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
guard indexPath.section == SectionButton else { return false }
// Highlight the button only if it's enabled.
return clearButtonEnabled
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard indexPath.section == SectionButton else { return }
func clearPrivateData(_ action: UIAlertAction) {
let toggles = self.toggles
self.clearables
.enumerated()
.flatMap { (i, pair) in
guard toggles[i] else {
return nil
}
log.debug("Clearing \(pair.clearable).")
return pair.clearable.clear()
}
.allSucceed()
.upon { result in
assert(result.isSuccess, "Private data cleared successfully")
LeanplumIntegration.sharedInstance.track(eventName: .clearPrivateData)
self.profile.prefs.setObject(self.toggles, forKey: TogglesPrefKey)
DispatchQueue.main.async {
// Disable the Clear Private Data button after it's clicked.
self.clearButtonEnabled = false
self.tableView.deselectRow(at: indexPath, animated: true)
}
}
}
// We have been asked to clear history and we have an account.
// (Whether or not it's in a good state is irrelevant.)
if self.toggles[HistoryClearableIndex] && profile.hasAccount() {
profile.syncManager.hasSyncedHistory().uponQueue(DispatchQueue.main) { yes in
// Err on the side of warning, but this shouldn't fail.
let alert: UIAlertController
if yes.successValue ?? true {
// Our local database contains some history items that have been synced.
// Warn the user before clearing.
alert = UIAlertController.clearSyncedHistoryAlert(okayCallback: clearPrivateData)
} else {
alert = UIAlertController.clearPrivateDataAlert(okayCallback: clearPrivateData)
}
self.present(alert, animated: true, completion: nil)
return
}
} else {
let alert = UIAlertController.clearPrivateDataAlert(okayCallback: clearPrivateData)
self.present(alert, animated: true, completion: nil)
}
tableView.deselectRow(at: indexPath, animated: false)
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return tableView.dequeueReusableHeaderFooterView(withIdentifier: SectionHeaderFooterIdentifier) as! SettingsTableSectionHeaderFooterView
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UIConstants.TableViewHeaderFooterHeight
}
@objc func switchValueChanged(_ toggle: UISwitch) {
toggles[toggle.tag] = toggle.isOn
// Dim the clear button if no clearables are selected.
clearButtonEnabled = toggles.contains(true)
}
}