Allows explicitly downloading corrupted record versions from RecordVersionsViewController
This commit is contained in:
parent
be047b28a6
commit
061f5abd3e
@ -23,6 +23,12 @@ public class GameSave: _GameSave
|
||||
}
|
||||
}
|
||||
|
||||
extension GameSave
|
||||
{
|
||||
// Hacky, but YOLO I'm under time crunch.
|
||||
public static var ignoredCorruptedIDs = Set<String>()
|
||||
}
|
||||
|
||||
extension GameSave: Syncable
|
||||
{
|
||||
public static var syncablePrimaryKey: AnyKeyPath {
|
||||
@ -71,27 +77,46 @@ extension GameSave: Syncable
|
||||
|
||||
public func awakeFromSync(_ record: AnyRecord) throws
|
||||
{
|
||||
guard let game = self.game else { throw SyncValidationError.incorrectGame(nil) }
|
||||
|
||||
if game.identifier != self.identifier
|
||||
do
|
||||
{
|
||||
let fetchRequest = GameSave.fetchRequest()
|
||||
fetchRequest.predicate = NSPredicate(format: "%K == %@", #keyPath(GameSave.identifier), game.identifier)
|
||||
guard let game = self.game else { throw SyncValidationError.incorrectGame(nil) }
|
||||
|
||||
if let misplacedGameSave = try self.managedObjectContext?.fetch(fetchRequest).first, misplacedGameSave.game == nil
|
||||
if game.identifier != self.identifier
|
||||
{
|
||||
// Relink game with its correct gameSave, in case we accidentally misplaced it.
|
||||
// Otherwise, corrupted records might displace already-downloaded GameSaves
|
||||
// due to automatic Core Data relationship propagation, despite us throwing error.
|
||||
game.gameSave = misplacedGameSave
|
||||
let fetchRequest = GameSave.fetchRequest()
|
||||
fetchRequest.predicate = NSPredicate(format: "%K == %@", #keyPath(GameSave.identifier), game.identifier)
|
||||
|
||||
if let misplacedGameSave = try self.managedObjectContext?.fetch(fetchRequest).first, misplacedGameSave.game == nil
|
||||
{
|
||||
// Relink game with its correct gameSave, in case we accidentally misplaced it.
|
||||
// Otherwise, corrupted records might displace already-downloaded GameSaves
|
||||
// due to automatic Core Data relationship propagation, despite us throwing error.
|
||||
game.gameSave = misplacedGameSave
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either there is no misplacedGameSave, or there is but it's linked to another game somehow.
|
||||
game.gameSave = nil
|
||||
}
|
||||
|
||||
throw SyncValidationError.incorrectGame(game.name)
|
||||
}
|
||||
}
|
||||
catch let error as SyncValidationError
|
||||
{
|
||||
guard GameSave.ignoredCorruptedIDs.contains(self.identifier) else { throw error }
|
||||
|
||||
let fetchRequest = Game.fetchRequest()
|
||||
fetchRequest.predicate = NSPredicate(format: "%K == %@", #keyPath(Game.identifier), self.identifier)
|
||||
|
||||
if let correctGame = try self.managedObjectContext?.fetch(fetchRequest).first
|
||||
{
|
||||
self.game = correctGame
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either there is no misplacedGameSave, or there is but it's linked to another game somehow.
|
||||
game.gameSave = nil
|
||||
throw ValidationError.nilRelationshipObjects(keys: [#keyPath(GameSave.game)])
|
||||
}
|
||||
|
||||
throw SyncValidationError.incorrectGame(game.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,6 +258,8 @@ private extension RecordVersionsViewController
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
|
||||
GameSave.ignoredCorruptedIDs.remove(self.record.recordID.identifier)
|
||||
|
||||
CATransaction.begin()
|
||||
|
||||
CATransaction.setCompletionBlock {
|
||||
@ -287,17 +289,34 @@ private extension RecordVersionsViewController
|
||||
}
|
||||
catch
|
||||
{
|
||||
let title: String
|
||||
|
||||
switch self.mode
|
||||
switch error
|
||||
{
|
||||
case .restoreVersion: title = NSLocalizedString("Failed to Restore Version", comment: "")
|
||||
case .resolveConflict: title = NSLocalizedString("Failed to Resolve Conflict", comment: "")
|
||||
case RecordError.other(let record, let error as SyncValidationError):
|
||||
// Only allow restoring corrupted records with incorrect games.
|
||||
guard case .incorrectGame = error else { fallthrough }
|
||||
|
||||
let message = NSLocalizedString("Would you like to download this version anyway?", comment: "")
|
||||
let alertController = UIAlertController(title: NSLocalizedString("Record Version Corrupted", comment: ""), message: message, preferredStyle: .alert)
|
||||
alertController.addAction(.cancel)
|
||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Download Anyway", comment: ""), style: .destructive) { _ in
|
||||
GameSave.ignoredCorruptedIDs.insert(record.recordID.identifier)
|
||||
self.restoreVersion()
|
||||
})
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
|
||||
default:
|
||||
let title: String
|
||||
|
||||
switch self.mode
|
||||
{
|
||||
case .restoreVersion: title = NSLocalizedString("Failed to Restore Version", comment: "")
|
||||
case .resolveConflict: title = NSLocalizedString("Failed to Resolve Conflict", comment: "")
|
||||
}
|
||||
|
||||
let alertController = UIAlertController(title: title, message: error.localizedDescription, preferredStyle: .alert)
|
||||
alertController.addAction(.ok)
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
let alertController = UIAlertController(title: title, message: error.localizedDescription, preferredStyle: .alert)
|
||||
alertController.addAction(.ok)
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
CATransaction.commit()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user