Improves UI for restoring records/resolving conflicts
This commit is contained in:
parent
7464ce1412
commit
8bc9d02e4c
@ -997,7 +997,7 @@
|
|||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
</cells>
|
</cells>
|
||||||
</tableViewSection>
|
</tableViewSection>
|
||||||
<tableViewSection headerTitle="Local" id="vpJ-Pg-nU9">
|
<tableViewSection headerTitle="On Device" id="vpJ-Pg-nU9">
|
||||||
<cells>
|
<cells>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="Cell" textLabel="npF-wl-PPC" detailTextLabel="SYD-cR-5TY" style="IBUITableViewCellStyleValue1" id="9Dq-cm-tka">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="Cell" textLabel="npF-wl-PPC" detailTextLabel="SYD-cR-5TY" style="IBUITableViewCellStyleValue1" id="9Dq-cm-tka">
|
||||||
<rect key="frame" x="0.0" y="135" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="135" width="375" height="44"/>
|
||||||
@ -1049,7 +1049,7 @@
|
|||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
</cells>
|
</cells>
|
||||||
</tableViewSection>
|
</tableViewSection>
|
||||||
<tableViewSection headerTitle="Remote" id="Bct-0y-ptf">
|
<tableViewSection headerTitle="Cloud" id="Bct-0y-ptf">
|
||||||
<cells>
|
<cells>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="Cell" textLabel="aeh-me-gZl" detailTextLabel="0Rm-b2-HX5" style="IBUITableViewCellStyleValue1" id="djI-O4-xho">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="Cell" textLabel="aeh-me-gZl" detailTextLabel="0Rm-b2-HX5" style="IBUITableViewCellStyleValue1" id="djI-O4-xho">
|
||||||
<rect key="frame" x="0.0" y="279" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="279" width="375" height="44"/>
|
||||||
@ -1218,23 +1218,6 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="gray" indentationWidth="10" reuseIdentifier="ConfirmCell" textLabel="saf-eQ-eJc" style="IBUITableViewCellStyleDefault" id="x0b-KE-P94">
|
|
||||||
<rect key="frame" x="0.0" y="143.5" width="375" height="44"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="x0b-KE-P94" id="ufh-yE-uv2">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<subviews>
|
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Restore Version" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="saf-eQ-eJc">
|
|
||||||
<rect key="frame" x="16" y="0.0" width="343" height="43.5"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
|
||||||
<nil key="textColor"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
</subviews>
|
|
||||||
</tableViewCellContentView>
|
|
||||||
</tableViewCell>
|
|
||||||
</prototypes>
|
</prototypes>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="dataSource" destination="PGW-Yp-czd" id="O27-2u-XUE"/>
|
<outlet property="dataSource" destination="PGW-Yp-czd" id="O27-2u-XUE"/>
|
||||||
@ -1242,12 +1225,21 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<navigationItem key="navigationItem" title="Versions" id="GLC-Lc-6VM">
|
<navigationItem key="navigationItem" title="Versions" id="GLC-Lc-6VM">
|
||||||
<barButtonItem key="rightBarButtonItem" style="done" systemItem="done" id="LMc-KQ-vea">
|
<barButtonItem key="leftBarButtonItem" systemItem="cancel" id="LMc-KQ-vea">
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="oyk-u7-Dn0" kind="unwind" unwindAction="unwindToRecordSyncStatusViewController:" id="JOO-Bj-i1E"/>
|
<segue destination="oyk-u7-Dn0" kind="unwind" unwindAction="unwindToRecordSyncStatusViewController:" id="JOO-Bj-i1E"/>
|
||||||
</connections>
|
</connections>
|
||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
|
<barButtonItem key="rightBarButtonItem" enabled="NO" title="Restore" style="done" id="I8z-cN-A01">
|
||||||
|
<color key="tintColor" red="1" green="0.14901960780000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="restore:" destination="PGW-Yp-czd" id="wQ3-0j-AXC"/>
|
||||||
|
</connections>
|
||||||
|
</barButtonItem>
|
||||||
</navigationItem>
|
</navigationItem>
|
||||||
|
<connections>
|
||||||
|
<outlet property="restoreButton" destination="I8z-cN-A01" id="9Bi-Qg-usS"/>
|
||||||
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="p6Y-9f-cL2" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="p6Y-9f-cL2" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
<exit id="oyk-u7-Dn0" userLabel="Exit" sceneMemberID="exit"/>
|
<exit id="oyk-u7-Dn0" userLabel="Exit" sceneMemberID="exit"/>
|
||||||
|
|||||||
@ -17,7 +17,6 @@ extension RecordVersionsViewController
|
|||||||
{
|
{
|
||||||
case local
|
case local
|
||||||
case remote
|
case remote
|
||||||
case confirm
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum Mode
|
private enum Mode
|
||||||
@ -42,6 +41,7 @@ class RecordVersionsViewController: UITableViewController
|
|||||||
var record: Record<NSManagedObject>! {
|
var record: Record<NSManagedObject>! {
|
||||||
didSet {
|
didSet {
|
||||||
self.mode = self.record.isConflicted ? .resolveConflict : .restoreVersion
|
self.mode = self.record.isConflicted ? .resolveConflict : .restoreVersion
|
||||||
|
self.update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +80,8 @@ class RecordVersionsViewController: UITableViewController
|
|||||||
|
|
||||||
private var _progressObservation: NSKeyValueObservation?
|
private var _progressObservation: NSKeyValueObservation?
|
||||||
|
|
||||||
|
@IBOutlet private var restoreButton: UIBarButtonItem!
|
||||||
|
|
||||||
override func viewDidLoad()
|
override func viewDidLoad()
|
||||||
{
|
{
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
@ -98,6 +100,8 @@ class RecordVersionsViewController: UITableViewController
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.tableView.dataSource = self.dataSource
|
self.tableView.dataSource = self.dataSource
|
||||||
|
|
||||||
|
self.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool)
|
override func viewWillAppear(_ animated: Bool)
|
||||||
@ -164,36 +168,29 @@ private extension RecordVersionsViewController
|
|||||||
let remoteVersionsLoadingDataSource = RSTCompositeTableViewDataSource(dataSources: [loadingDataSource, remoteVersionsDataSource])
|
let remoteVersionsLoadingDataSource = RSTCompositeTableViewDataSource(dataSources: [loadingDataSource, remoteVersionsDataSource])
|
||||||
remoteVersionsLoadingDataSource.shouldFlattenSections = true
|
remoteVersionsLoadingDataSource.shouldFlattenSections = true
|
||||||
|
|
||||||
let restoreVersionDataSource = RSTDynamicTableViewDataSource<Version>()
|
let dataSource = RSTCompositeTableViewDataSource(dataSources: [localVersionsDataSource, remoteVersionsLoadingDataSource])
|
||||||
restoreVersionDataSource.numberOfSectionsHandler = { 1 }
|
|
||||||
restoreVersionDataSource.numberOfItemsHandler = { _ in 1}
|
|
||||||
restoreVersionDataSource.cellIdentifierHandler = { _ in "ConfirmCell" }
|
|
||||||
restoreVersionDataSource.cellConfigurationHandler = { [weak self] (cell, _, indexPath) in
|
|
||||||
guard let `self` = self else { return }
|
|
||||||
|
|
||||||
switch self.mode
|
|
||||||
{
|
|
||||||
case .restoreVersion:
|
|
||||||
cell.textLabel?.text = NSLocalizedString("Restore Version", comment: "")
|
|
||||||
cell.textLabel?.textColor = .deltaPurple
|
|
||||||
|
|
||||||
let isEnabled = (self._selectedVersionIndexPath?.section == Section.remote.rawValue && !self.isSyncingRecord)
|
|
||||||
configure(cell, isSelected: false, isEnabled: isEnabled)
|
|
||||||
|
|
||||||
case .resolveConflict:
|
|
||||||
cell.textLabel?.text = NSLocalizedString("Resolve Conflict", comment: "")
|
|
||||||
cell.textLabel?.textColor = .red
|
|
||||||
|
|
||||||
let isEnabled = (self._selectedVersionIndexPath != nil && !self.isSyncingRecord)
|
|
||||||
configure(cell, isSelected: false, isEnabled: isEnabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let dataSource = RSTCompositeTableViewDataSource(dataSources: [localVersionsDataSource, remoteVersionsLoadingDataSource, restoreVersionDataSource])
|
|
||||||
dataSource.proxy = self
|
dataSource.proxy = self
|
||||||
return dataSource
|
return dataSource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func update()
|
||||||
|
{
|
||||||
|
switch self.mode
|
||||||
|
{
|
||||||
|
case .restoreVersion:
|
||||||
|
self.restoreButton.title = NSLocalizedString("Restore", comment: "")
|
||||||
|
self.restoreButton.tintColor = .deltaPurple
|
||||||
|
|
||||||
|
self.restoreButton.isEnabled = (self._selectedVersionIndexPath?.section == Section.remote.rawValue)
|
||||||
|
|
||||||
|
case .resolveConflict:
|
||||||
|
self.restoreButton.title = NSLocalizedString("Resolve", comment: "")
|
||||||
|
self.restoreButton.tintColor = .red
|
||||||
|
|
||||||
|
self.restoreButton.isEnabled = (self._selectedVersionIndexPath != nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func fetchVersions()
|
func fetchVersions()
|
||||||
{
|
{
|
||||||
SyncManager.shared.coordinator?.fetchVersions(for: self.record) { (result) in
|
SyncManager.shared.coordinator?.fetchVersions(for: self.record) { (result) in
|
||||||
@ -255,11 +252,12 @@ private extension RecordVersionsViewController
|
|||||||
self._progressObservation = nil
|
self._progressObservation = nil
|
||||||
|
|
||||||
self.progressView.setHidden(true, animated: true)
|
self.progressView.setHidden(true, animated: true)
|
||||||
|
self.navigationItem.rightBarButtonItem?.isIndicatingActivity = false
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
|
||||||
self.tableView.reloadData()
|
self.tableView.reloadData()
|
||||||
|
|
||||||
self.navigationItem.rightBarButtonItem?.isIndicatingActivity = false
|
|
||||||
|
|
||||||
switch result
|
switch result
|
||||||
{
|
{
|
||||||
case .success: self.fetchVersions()
|
case .success: self.fetchVersions()
|
||||||
@ -315,8 +313,6 @@ private extension RecordVersionsViewController
|
|||||||
progress = coordinator.resolveConflictedRecord(self.record, resolution: .remote(version.version)) { (result) in
|
progress = coordinator.resolveConflictedRecord(self.record, resolution: .remote(version.version)) { (result) in
|
||||||
finish(result)
|
finish(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
case (.resolveConflict, .confirm): return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.isSyncingRecord = true
|
self.isSyncingRecord = true
|
||||||
@ -335,15 +331,50 @@ private extension RecordVersionsViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension RecordVersionsViewController
|
||||||
|
{
|
||||||
|
@IBAction func restore(_ sender: UIBarButtonItem)
|
||||||
|
{
|
||||||
|
let message: String
|
||||||
|
let actionTitle: String
|
||||||
|
|
||||||
|
switch self.mode
|
||||||
|
{
|
||||||
|
case .restoreVersion:
|
||||||
|
message = NSLocalizedString("Restoring a remote version will cause any local changes to be lost.", comment: "")
|
||||||
|
actionTitle = NSLocalizedString("Restore Version", comment: "")
|
||||||
|
|
||||||
|
case .resolveConflict:
|
||||||
|
if self._selectedVersionIndexPath?.section == Section.local.rawValue
|
||||||
|
{
|
||||||
|
message = NSLocalizedString("The local version will be uploaded and synced to your other devices.", comment: "")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message = NSLocalizedString("Selecting a remote version will cause any local changes to be lost.", comment: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
actionTitle = NSLocalizedString("Resolve Conflict", comment: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
|
||||||
|
alertController.addAction(.cancel)
|
||||||
|
alertController.addAction(UIAlertAction(title: actionTitle, style: .destructive) { (action) in
|
||||||
|
self.restoreVersion()
|
||||||
|
})
|
||||||
|
|
||||||
|
self.present(alertController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension RecordVersionsViewController
|
extension RecordVersionsViewController
|
||||||
{
|
{
|
||||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
|
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
|
||||||
{
|
{
|
||||||
switch Section.allCases[section]
|
switch Section.allCases[section]
|
||||||
{
|
{
|
||||||
case .local: return NSLocalizedString("Local", comment: "")
|
case .local: return NSLocalizedString("On Device", comment: "")
|
||||||
case .remote: return NSLocalizedString("Remote", comment: "")
|
case .remote: return NSLocalizedString("Cloud", comment: "")
|
||||||
case .confirm: return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,44 +384,11 @@ extension RecordVersionsViewController
|
|||||||
|
|
||||||
guard let cell = tableView.cellForRow(at: indexPath), cell.selectionStyle != .none else { return }
|
guard let cell = tableView.cellForRow(at: indexPath), cell.selectionStyle != .none else { return }
|
||||||
|
|
||||||
switch Section.allCases[indexPath.section]
|
let indexPaths = [indexPath, self._selectedVersionIndexPath].compactMap { $0 }
|
||||||
{
|
self._selectedVersionIndexPath = indexPath
|
||||||
case .local, .remote:
|
|
||||||
let indexPaths = [indexPath, self._selectedVersionIndexPath, IndexPath(item: 0, section: Section.confirm.rawValue)].compactMap { $0 }
|
|
||||||
self._selectedVersionIndexPath = indexPath
|
|
||||||
|
|
||||||
tableView.reloadRows(at: indexPaths, with: .none)
|
tableView.reloadRows(at: indexPaths, with: .none)
|
||||||
|
|
||||||
case .confirm:
|
self.update()
|
||||||
let message: String
|
|
||||||
let actionTitle: String
|
|
||||||
|
|
||||||
switch self.mode
|
|
||||||
{
|
|
||||||
case .restoreVersion:
|
|
||||||
message = NSLocalizedString("Restoring a remote version will cause any local changes to be lost.", comment: "")
|
|
||||||
actionTitle = NSLocalizedString("Restore Version", comment: "")
|
|
||||||
|
|
||||||
case .resolveConflict:
|
|
||||||
if self._selectedVersionIndexPath?.section == Section.local.rawValue
|
|
||||||
{
|
|
||||||
message = NSLocalizedString("The local version will be uploaded and synced to your other devices.", comment: "")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message = NSLocalizedString("Selecting a remote version will cause any local changes to be lost.", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
actionTitle = NSLocalizedString("Resolve Conflict", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
|
|
||||||
alertController.addAction(.cancel)
|
|
||||||
alertController.addAction(UIAlertAction(title: actionTitle, style: .destructive) { (action) in
|
|
||||||
self.restoreVersion()
|
|
||||||
})
|
|
||||||
|
|
||||||
self.present(alertController, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user