Adds basic GameSyncStatusViewController to view status of game-related records
This commit is contained in:
parent
5354d779c1
commit
ca4ccfc3ae
@ -99,6 +99,7 @@
|
|||||||
BF7AE80A1C2E8C7600B1B5BC /* UIColor+Delta.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF7AE8091C2E8C7600B1B5BC /* UIColor+Delta.swift */; };
|
BF7AE80A1C2E8C7600B1B5BC /* UIColor+Delta.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF7AE8091C2E8C7600B1B5BC /* UIColor+Delta.swift */; };
|
||||||
BF80E1D21F13117000847008 /* ControllerInputsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF616A121F08184A0077F8B2 /* ControllerInputsViewController.swift */; };
|
BF80E1D21F13117000847008 /* ControllerInputsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF616A121F08184A0077F8B2 /* ControllerInputsViewController.swift */; };
|
||||||
BF8A333421A484A000A42FD4 /* BadgedTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8A333321A484A000A42FD4 /* BadgedTableViewCell.swift */; };
|
BF8A333421A484A000A42FD4 /* BadgedTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8A333321A484A000A42FD4 /* BadgedTableViewCell.swift */; };
|
||||||
|
BF8A334621A4926F00A42FD4 /* GameSyncStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8A334521A4926F00A42FD4 /* GameSyncStatusViewController.swift */; };
|
||||||
BF8CA9361F5F651900499FDD /* PopoverMenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8CA9351F5F651900499FDD /* PopoverMenuController.swift */; };
|
BF8CA9361F5F651900499FDD /* PopoverMenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8CA9351F5F651900499FDD /* PopoverMenuController.swift */; };
|
||||||
BF8DDD241F4F6C880088A21B /* InputCalloutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8DDD231F4F6C880088A21B /* InputCalloutView.swift */; };
|
BF8DDD241F4F6C880088A21B /* InputCalloutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8DDD231F4F6C880088A21B /* InputCalloutView.swift */; };
|
||||||
BF95E2771E4977BF0030E7AD /* GameMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF95E2761E4977BF0030E7AD /* GameMetadata.swift */; };
|
BF95E2771E4977BF0030E7AD /* GameMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF95E2761E4977BF0030E7AD /* GameMetadata.swift */; };
|
||||||
@ -247,6 +248,7 @@
|
|||||||
BF7AE8041C2E858400B1B5BC /* GridMenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridMenuViewController.swift; sourceTree = "<group>"; };
|
BF7AE8041C2E858400B1B5BC /* GridMenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridMenuViewController.swift; sourceTree = "<group>"; };
|
||||||
BF7AE8091C2E8C7600B1B5BC /* UIColor+Delta.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Delta.swift"; sourceTree = "<group>"; };
|
BF7AE8091C2E8C7600B1B5BC /* UIColor+Delta.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Delta.swift"; sourceTree = "<group>"; };
|
||||||
BF8A333321A484A000A42FD4 /* BadgedTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgedTableViewCell.swift; sourceTree = "<group>"; };
|
BF8A333321A484A000A42FD4 /* BadgedTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgedTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
BF8A334521A4926F00A42FD4 /* GameSyncStatusViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameSyncStatusViewController.swift; sourceTree = "<group>"; };
|
||||||
BF8CA9351F5F651900499FDD /* PopoverMenuController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopoverMenuController.swift; sourceTree = "<group>"; };
|
BF8CA9351F5F651900499FDD /* PopoverMenuController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopoverMenuController.swift; sourceTree = "<group>"; };
|
||||||
BF8DDD231F4F6C880088A21B /* InputCalloutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputCalloutView.swift; sourceTree = "<group>"; };
|
BF8DDD231F4F6C880088A21B /* InputCalloutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputCalloutView.swift; sourceTree = "<group>"; };
|
||||||
BF95E2761E4977BF0030E7AD /* GameMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameMetadata.swift; sourceTree = "<group>"; };
|
BF95E2761E4977BF0030E7AD /* GameMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameMetadata.swift; sourceTree = "<group>"; };
|
||||||
@ -375,6 +377,7 @@
|
|||||||
children = (
|
children = (
|
||||||
BF48F74D219A16DA00BC2FC1 /* SyncingServicesViewController.swift */,
|
BF48F74D219A16DA00BC2FC1 /* SyncingServicesViewController.swift */,
|
||||||
BFDB3417219E4B1700595A62 /* SyncStatusViewController.swift */,
|
BFDB3417219E4B1700595A62 /* SyncStatusViewController.swift */,
|
||||||
|
BF8A334521A4926F00A42FD4 /* GameSyncStatusViewController.swift */,
|
||||||
);
|
);
|
||||||
path = Syncing;
|
path = Syncing;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -930,6 +933,7 @@
|
|||||||
BFBAB2E31EB685A2004E0B0E /* DeltaCoreProtocol+Delta.swift in Sources */,
|
BFBAB2E31EB685A2004E0B0E /* DeltaCoreProtocol+Delta.swift in Sources */,
|
||||||
BF3540081C5DAFAD00C1184C /* PauseTransitionCoordinator.swift in Sources */,
|
BF3540081C5DAFAD00C1184C /* PauseTransitionCoordinator.swift in Sources */,
|
||||||
BF525EEA1FF6CD12004AA849 /* DeepLink.swift in Sources */,
|
BF525EEA1FF6CD12004AA849 /* DeepLink.swift in Sources */,
|
||||||
|
BF8A334621A4926F00A42FD4 /* GameSyncStatusViewController.swift in Sources */,
|
||||||
BF59427E1E09BC830051894B /* Game.swift in Sources */,
|
BF59427E1E09BC830051894B /* Game.swift in Sources */,
|
||||||
BFAA1FED1B8AA4FA00495943 /* Settings.swift in Sources */,
|
BFAA1FED1B8AA4FA00495943 /* Settings.swift in Sources */,
|
||||||
BFA0D1271D3AE1F600565894 /* GameViewController.swift in Sources */,
|
BFA0D1271D3AE1F600565894 /* GameViewController.swift in Sources */,
|
||||||
|
|||||||
@ -828,6 +828,9 @@
|
|||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
|
<connections>
|
||||||
|
<segue destination="OnX-sX-bHK" kind="show" identifier="showGame" id="vUN-0T-oaK"/>
|
||||||
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
</prototypes>
|
</prototypes>
|
||||||
<connections>
|
<connections>
|
||||||
@ -840,5 +843,43 @@
|
|||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="3351" y="1872"/>
|
<point key="canvasLocation" x="3351" y="1872"/>
|
||||||
</scene>
|
</scene>
|
||||||
|
<!--Game Sync Status View Controller-->
|
||||||
|
<scene sceneID="iQk-cq-qsQ">
|
||||||
|
<objects>
|
||||||
|
<tableViewController id="OnX-sX-bHK" customClass="GameSyncStatusViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="AFt-Hn-fzR">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||||
|
<prototypes>
|
||||||
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="Cell" textLabel="RWL-4W-NpH" style="IBUITableViewCellStyleDefault" id="q5G-Db-MXt">
|
||||||
|
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="q5G-Db-MXt" id="Ric-Km-AWj">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Game" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RWL-4W-NpH">
|
||||||
|
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
</tableViewCellContentView>
|
||||||
|
</tableViewCell>
|
||||||
|
</prototypes>
|
||||||
|
<sections/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="dataSource" destination="OnX-sX-bHK" id="TuS-hI-T9X"/>
|
||||||
|
<outlet property="delegate" destination="OnX-sX-bHK" id="vII-vu-IIw"/>
|
||||||
|
</connections>
|
||||||
|
</tableView>
|
||||||
|
</tableViewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="FHk-WU-IoC" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="4206" y="1872"/>
|
||||||
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
154
Delta/Settings/Syncing/GameSyncStatusViewController.swift
Normal file
154
Delta/Settings/Syncing/GameSyncStatusViewController.swift
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
//
|
||||||
|
// GameSyncStatusViewController.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 11/20/18.
|
||||||
|
// Copyright © 2018 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
import Roxas
|
||||||
|
import Harmony
|
||||||
|
|
||||||
|
extension GameSyncStatusViewController
|
||||||
|
{
|
||||||
|
private enum Section: Int, CaseIterable
|
||||||
|
{
|
||||||
|
case game
|
||||||
|
case saveStates
|
||||||
|
case cheats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GameSyncStatusViewController: UITableViewController
|
||||||
|
{
|
||||||
|
var game: Game!
|
||||||
|
|
||||||
|
private lazy var dataSource = self.makeDataSource()
|
||||||
|
|
||||||
|
private let dateFormatter: DateFormatter = {
|
||||||
|
let dateFormatter = DateFormatter()
|
||||||
|
dateFormatter.timeStyle = .short
|
||||||
|
dateFormatter.dateStyle = .short
|
||||||
|
|
||||||
|
return dateFormatter
|
||||||
|
}()
|
||||||
|
|
||||||
|
private var recordsByObjectURI = [URL: Record<NSManagedObject>]()
|
||||||
|
|
||||||
|
override func viewDidLoad()
|
||||||
|
{
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
self.title = self.game.name
|
||||||
|
|
||||||
|
self.tableView.dataSource = self.dataSource
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillAppear(_ animated: Bool)
|
||||||
|
{
|
||||||
|
self.fetchRecords()
|
||||||
|
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension GameSyncStatusViewController
|
||||||
|
{
|
||||||
|
private func makeDataSource() -> RSTCompositeTableViewDataSource<NSManagedObject>
|
||||||
|
{
|
||||||
|
func configure(_ cell: UITableViewCell, recordedObject: NSManagedObject)
|
||||||
|
{
|
||||||
|
if let record = self.recordsByObjectURI[recordedObject.objectID.uriRepresentation()], record.isConflicted
|
||||||
|
{
|
||||||
|
cell.textLabel?.textColor = .red
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cell.textLabel?.textColor = .darkText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let gameDataSource = RSTArrayTableViewDataSource<Game>(items: [self.game])
|
||||||
|
gameDataSource.cellConfigurationHandler = { (cell, game, indexPath) in
|
||||||
|
cell.textLabel?.text = game.name
|
||||||
|
|
||||||
|
configure(cell, recordedObject: game)
|
||||||
|
}
|
||||||
|
|
||||||
|
let saveStatesFetchRequest = SaveState.fetchRequest() as NSFetchRequest<SaveState>
|
||||||
|
saveStatesFetchRequest.predicate = NSPredicate(format: "%K == %@", #keyPath(SaveState.game), self.game)
|
||||||
|
saveStatesFetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \SaveState.creationDate, ascending: true)]
|
||||||
|
|
||||||
|
let saveStatesDataSource = RSTFetchedResultsTableViewDataSource(fetchRequest: saveStatesFetchRequest, managedObjectContext: DatabaseManager.shared.viewContext)
|
||||||
|
saveStatesDataSource.cellConfigurationHandler = { (cell, saveState, indexPath) in
|
||||||
|
if let name = saveState.name
|
||||||
|
{
|
||||||
|
cell.textLabel?.text = name
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cell.textLabel?.text = self.dateFormatter.string(from: saveState.modifiedDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
configure(cell, recordedObject: saveState)
|
||||||
|
}
|
||||||
|
|
||||||
|
let cheatsFetchRequest = Cheat.fetchRequest() as NSFetchRequest<Cheat>
|
||||||
|
cheatsFetchRequest.predicate = NSPredicate(format: "%K == %@", #keyPath(Cheat.game), self.game)
|
||||||
|
cheatsFetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Cheat.name, ascending: true)]
|
||||||
|
|
||||||
|
let cheatsDataSource = RSTFetchedResultsTableViewDataSource(fetchRequest: cheatsFetchRequest, managedObjectContext: DatabaseManager.shared.viewContext)
|
||||||
|
cheatsDataSource.cellConfigurationHandler = { (cell, cheat, indexPath) in
|
||||||
|
cell.textLabel?.text = cheat.name
|
||||||
|
|
||||||
|
configure(cell, recordedObject: cheat)
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataSources = [gameDataSource, saveStatesDataSource, cheatsDataSource] as! [RSTArrayTableViewDataSource<NSManagedObject>]
|
||||||
|
|
||||||
|
let dataSource = RSTCompositeTableViewDataSource(dataSources: dataSources)
|
||||||
|
dataSource.proxy = self
|
||||||
|
return dataSource
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchRecords()
|
||||||
|
{
|
||||||
|
var recordsByObjectURI = [URL: Record<NSManagedObject>]()
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let recordedObjects = ([self.game!] + Array(self.game.saveStates) + Array(self.game.cheats)) as! [SyncableManagedObject]
|
||||||
|
let records = try SyncManager.shared.recordController.fetchRecords(for: recordedObjects)
|
||||||
|
|
||||||
|
for record in records
|
||||||
|
{
|
||||||
|
guard let recordedObject = record.recordedObject else { continue }
|
||||||
|
|
||||||
|
recordsByObjectURI[recordedObject.objectID.uriRepresentation()] = record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.recordsByObjectURI = recordsByObjectURI
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension GameSyncStatusViewController
|
||||||
|
{
|
||||||
|
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
|
||||||
|
{
|
||||||
|
guard self.dataSource.tableView(self.tableView, numberOfRowsInSection: section) > 0 else { return nil }
|
||||||
|
|
||||||
|
switch Section.allCases[section]
|
||||||
|
{
|
||||||
|
case .game: return NSLocalizedString("Game", comment: "")
|
||||||
|
case .saveStates: return NSLocalizedString("Save States", comment: "")
|
||||||
|
case .cheats: return NSLocalizedString("Cheats", comment: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -30,6 +30,18 @@ class SyncStatusViewController: UITableViewController
|
|||||||
|
|
||||||
self.fetchConflictedRecords()
|
self.fetchConflictedRecords()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
|
||||||
|
{
|
||||||
|
guard segue.identifier == "showGame" else { return }
|
||||||
|
|
||||||
|
guard let cell = sender as? UITableViewCell, let indexPath = self.tableView.indexPath(for: cell) else { return }
|
||||||
|
|
||||||
|
let game = self.dataSource.item(at: indexPath)
|
||||||
|
|
||||||
|
let gameSyncStatusViewController = segue.destination as! GameSyncStatusViewController
|
||||||
|
gameSyncStatusViewController.game = game
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension SyncStatusViewController
|
private extension SyncStatusViewController
|
||||||
@ -92,7 +104,7 @@ private extension SyncStatusViewController
|
|||||||
for record in records
|
for record in records
|
||||||
{
|
{
|
||||||
guard let recordedObject = record.recordedObject else { continue }
|
guard let recordedObject = record.recordedObject else { continue }
|
||||||
|
recordedObject.managedObjectContext?.performAndWait {
|
||||||
let conflictedGame: Game?
|
let conflictedGame: Game?
|
||||||
|
|
||||||
switch recordedObject
|
switch recordedObject
|
||||||
@ -103,10 +115,11 @@ private extension SyncStatusViewController
|
|||||||
default: conflictedGame = nil
|
default: conflictedGame = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let game = conflictedGame else { continue }
|
guard let game = conflictedGame else { return }
|
||||||
|
|
||||||
gameConflictsCount[game.objectID.uriRepresentation(), default: 0] += 1
|
gameConflictsCount[game.objectID.uriRepresentation(), default: 0] += 1
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.gameConflictsCount = gameConflictsCount
|
self.gameConflictsCount = gameConflictsCount
|
||||||
}
|
}
|
||||||
|
|||||||
2
External/Harmony
vendored
2
External/Harmony
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 6f5dc280077cee8382ccc6622ee8383aadb59d48
|
Subproject commit ef2c685333abe1cce9ee0a43150656634ab06081
|
||||||
Loading…
Reference in New Issue
Block a user