Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug/ios icloud not syncing #2395

Open
wants to merge 91 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
a33a1b6
added check for L3 and R3 buttons for older controllers
pabloarista Jan 14, 2025
efe7ae6
updated minimum to 16.0
pabloarista Jan 14, 2025
be7da84
updated to use variables for app groups and icloud container
pabloarista Jan 14, 2025
c6224c9
added todo to test without .icloud relative
pabloarista Jan 14, 2025
bd7eb34
added todo to test without .icloud relative
pabloarista Jan 14, 2025
a852aea
fix for icloud URL paths that duplicates the root directories
pabloarista Jan 14, 2025
c5ee69e
added a check for nil
pabloarista Jan 14, 2025
f5fad8b
added comment of encoded space to review
pabloarista Jan 14, 2025
2a8ac49
removed duplicate entry
pabloarista Jan 14, 2025
263da3b
updated project file to use build variables
pabloarista Jan 18, 2025
343d11c
Merge branch 'develop' into bug/ios-icloud-not-syncing
pabloarista Jan 18, 2025
f6c1558
removed TODOs
pabloarista Jan 19, 2025
a788cab
added notification when ROM db finishes initializing; updated cloudsy…
pabloarista Jan 20, 2025
983534c
updated type
pabloarista Jan 21, 2025
002cc14
reverted
pabloarista Jan 21, 2025
880df35
updated to send notiifcations when new icloud files have been downloa…
pabloarista Jan 23, 2025
7b4cafa
updated to use notification name
pabloarista Jan 23, 2025
d2c820a
reverted
pabloarista Jan 23, 2025
cf81ec7
reverted TODOs
pabloarista Jan 24, 2025
c517f8c
added downloading of battery saves, bios and screenshots; added todo …
pabloarista Jan 24, 2025
676d579
refactored notification names to notification.swift and updated namin…
pabloarista Jan 25, 2025
b6443a9
reverted
pabloarista Jan 25, 2025
cfe6e98
updated to use dlog
pabloarista Jan 25, 2025
bf02d64
added more logs; remove tasks that were causing synchronization issue…
pabloarista Jan 25, 2025
c0520d4
added todo; remove task because it was causing crashes when syncing w…
pabloarista Jan 25, 2025
7d7e0bd
removed unused functions; refacored to wait for signal that file fini…
pabloarista Jan 26, 2025
7d090bf
removed unused function
pabloarista Jan 26, 2025
a8931cb
added deleting of ROMs when file is deleted on icloud
pabloarista Jan 26, 2025
82ad54e
added todo for deleting savestate
pabloarista Jan 26, 2025
ed2a2ad
added todo
pabloarista Jan 27, 2025
07f1b58
removed field
pabloarista Jan 27, 2025
e7d416e
refactored to listen for changes on icloud sync switch and init iclou…
pabloarista Jan 27, 2025
96deb54
reverted
pabloarista Jan 27, 2025
15ef275
added TODO
pabloarista Jan 27, 2025
fb8a981
added updating game importer's roms path that was causing issuing whe…
pabloarista Jan 27, 2025
6a8b45e
added TODO for review
pabloarista Jan 27, 2025
92e5400
added check for invalid path on PVImageFile
pabloarista Jan 28, 2025
2b1d62c
Merge branch 'develop' into bug/ios-icloud-not-syncing
pabloarista Feb 2, 2025
0edab03
added todo
pabloarista Feb 3, 2025
1fe056d
updated to use DLOG instead of print; added condition when root is iC…
pabloarista Feb 3, 2025
b5d647f
updated cache to save locally; updated debug log print statement
pabloarista Feb 3, 2025
1757a7f
added todo
pabloarista Feb 3, 2025
254d5ba
updated save path
pabloarista Feb 4, 2025
0de1a03
removed unused code; updated try to not force on Realm in case of db …
pabloarista Feb 4, 2025
cbe334e
removed unused closure onCompleted
pabloarista Feb 4, 2025
bfd7b14
removed commented out code
pabloarista Feb 4, 2025
561be70
added recursive code to move files from local to icloud container
pabloarista Feb 6, 2025
7bbf493
updated to get correct files and tree and to identify directories tha…
pabloarista Feb 7, 2025
957fc53
Finished main code to move files to cloud container
pabloarista Feb 7, 2025
1c0529d
added check if file exists in cloud and deleting local version
pabloarista Feb 7, 2025
ed1eff4
fixed check for directory, added uploader for ROMs
pabloarista Feb 7, 2025
c70e781
added TODO
pabloarista Feb 7, 2025
0827eb9
updated relativeRoot and added todos to check invalid paths
pabloarista Feb 9, 2025
fe25a22
added debug block
pabloarista Feb 9, 2025
aac5da6
reverted returns; updated TODO text
pabloarista Feb 9, 2025
ed86647
moved upload icloud to syncer class; added enumeration status icloud …
pabloarista Feb 9, 2025
e83acf7
updated to use notificationCenter directly and removed unused Notific…
pabloarista Feb 9, 2025
e1e599a
added userdefaults to know when to initially import files from cloud
pabloarista Feb 9, 2025
7f40843
added removal of icloud files when flag is turned off; added todo on …
pabloarista Feb 9, 2025
4803b01
updated to use shared function
pabloarista Feb 9, 2025
2c7cd85
removed finished todo
pabloarista Feb 9, 2025
8f68d4f
updated initializer
pabloarista Feb 9, 2025
46465be
refactored to merge files that do NOT have db entry into a single cla…
pabloarista Feb 9, 2025
390ef40
fixed battery states directory name
pabloarista Feb 9, 2025
441831f
updated to add full error; added check for storage available
pabloarista Feb 10, 2025
7027201
removed unused field
pabloarista Feb 10, 2025
8b39cab
refactored insert code into base class; updated logs; remove unnecess…
pabloarista Feb 10, 2025
c2f97f7
added error queue to store errors when syncing with iCloud
pabloarista Feb 15, 2025
99b490a
refactored move files to reduce nesting; updated to handle the case w…
pabloarista Feb 15, 2025
281b0bf
added deleting of json file when deleting save states; added trying t…
pabloarista Feb 16, 2025
387b539
added confirmation when deleting a ROM
pabloarista Feb 16, 2025
6029c61
added deletion of db items when deleted from icloud; fixed extension …
pabloarista Feb 16, 2025
21d3100
updated alerts
pabloarista Feb 16, 2025
ed04206
fixed bug when deleting file and then re-adding the same file by remo…
pabloarista Feb 16, 2025
5e2c599
fixed deletion of ROM and related files
pabloarista Feb 17, 2025
d110632
removed unused storage code
pabloarista Feb 17, 2025
43e47c4
refactored code to get indexset to fix index out of bounds when multi…
pabloarista Feb 17, 2025
06d6612
refactored to defer instead of duplicating code; updated to check for…
pabloarista Feb 17, 2025
edae4e7
updated localization
pabloarista Feb 17, 2025
c86939a
Merge branch 'develop' into bug/ios-icloud-not-syncing
pabloarista Feb 18, 2025
7909e06
removed unused variable
pabloarista Feb 18, 2025
3d3e2e1
updated to process 10 ROMs at a time.
pabloarista Feb 19, 2025
3459b90
added todo
pabloarista Feb 19, 2025
8a3dc47
Merge branch 'develop' into bug/ios-icloud-not-syncing
pabloarista Feb 22, 2025
0c4da8b
Merge branch 'develop' into bug/ios-icloud-not-syncing
pabloarista Feb 22, 2025
d12cbc8
fixed compilation issues
pabloarista Feb 22, 2025
b12269d
added sending signal on the main queue
pabloarista Feb 23, 2025
3f7911b
removed extra parenthesis
pabloarista Feb 23, 2025
ce2594b
added more logs, change foreach to synchronous to handle the case whe…
pabloarista Feb 23, 2025
71c5e33
added processing of save files in batches;
pabloarista Feb 23, 2025
d11db73
updated error logs to include file and to use correct log function; u…
pabloarista Feb 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cores/Atari800/Sources/PVAtari800Bridge/PVAtari800Bridge.m
Original file line number Diff line number Diff line change
Expand Up @@ -733,10 +733,10 @@ - (void)pollControllers {
} else if (gamepad.rightThumbstick.down.isPressed) {
//4 button
INPUT_key_code = AKEY_5200_4;
} else if (gamepad.leftThumbstickButton.isPressed) {
} else if (gamepad.leftThumbstickButton != nil && gamepad.leftThumbstickButton.isPressed) {
//5 button
INPUT_key_code = AKEY_5200_5;
} else if (gamepad.rightThumbstickButton.isPressed) {
} else if (gamepad.rightThumbstickButton != nil && gamepad.rightThumbstickButton.isPressed) {
//6 button
INPUT_key_code = AKEY_5200_6;
} else if (gamepad.buttonX.isPressed) {
Expand Down
2 changes: 1 addition & 1 deletion Extensions/Spotlight/Spotlight.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.provenance-emu.provenance</string>
<string>$(APP_GROUP_IDENTIFIER)</string>
</array>
<key>com.apple.security.assets.pictures.read-only</key>
<true/>
Expand Down
4 changes: 2 additions & 2 deletions Extensions/TopShelf/TopShelf.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<string>development</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.org.provenance.provenance</string>
<string>$(ICLOUD_CONTAINER_IDENTIFIER)</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
Expand All @@ -16,7 +16,7 @@
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.provenance-emu.provenance</string>
<string>$(APP_GROUP_IDENTIFIER)</string>
</array>
</dict>
</plist>
2 changes: 2 additions & 0 deletions PVLibrary/Sources/PVLibrary/Database/Notifications.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ import Foundation
public extension Notification.Name {
static let DatabaseMigrationStarted = Notification.Name("DatabaseMigrarionStarted")
static let DatabaseMigrationFinished = Notification.Name("DatabaseMigrarionFinished")
static let RomDatabaseInitialized = Notification.Name("RomDatabaseInitialized")
static let RomsFinishedImporting = Notification.Name("RomsFinishedImporting")
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ public extension RomDatabase {
guard let core = realm.object(ofType: PVCore.self, forPrimaryKey: core.coreIdentifier) else {
throw SaveStateError.noCoreFound(core.coreIdentifier ?? "null")
}
let imgFile = PVImageFile(withURL: URL(fileURLWithPath: url.path.replacingOccurrences(of: "svs", with: "jpg")))
let saveFile = PVFile(withURL: url)
let imgFile = PVImageFile(withURL: URL(fileURLWithPath: url.path.replacingOccurrences(of: "svs", with: "jpg")), relativeRoot: .iCloud)
let saveFile = PVFile(withURL: url, relativeRoot: .iCloud)
let newState = PVSaveState(withGame: game, core: core, file: saveFile, image: imgFile, isAutosave: false)
try realm.write {
realm.add(newState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ public final class RomDatabase {

ILOG("Database initialization completed")
databaseInitialized = true
NotificationCenter.default.post(name: .RomDatabaseInitialized, object: nil, userInfo: nil)
} else {
ILOG("Database already initialized")
}
Expand Down Expand Up @@ -762,6 +763,9 @@ public extension RomDatabase {
#if os(iOS)
deleteFromSpotlight(game: game)
#endif
defer {
RomDatabase.reloadGamesCache()
}
do {
deleteRelatedFilesGame(game)
game.saveStates.forEach { try? $0.delete() }
Expand All @@ -771,7 +775,8 @@ public extension RomDatabase {
try game.delete()
} catch {
// Delete the DB entry anyway if any of the above files couldn't be removed
do { try game.delete() } catch {
do { try game.delete()
} catch {
ELOG("\(error.localizedDescription)")
}
ELOG("\(error.localizedDescription)")
Expand Down Expand Up @@ -824,6 +829,15 @@ public extension RomDatabase {
throw RomDeletionError.fileManagerDeletionError(error)
}
}
if let jsonFile = actualSavePath?.pathDecoded.appending(".json"),
FileManager.default.fileExists(atPath: jsonFile) {
do {
try FileManager.default.removeItem(atPath: jsonFile)
} catch {
ELOG("Unable to delete json at path: \(jsonFile) because: \(error.localizedDescription)")
throw RomDeletionError.fileManagerDeletionError(error)
}
}
}

func deleteRelatedFilesGame(_ game: PVGame) {
Expand All @@ -841,6 +855,48 @@ public extension RomDatabase {
ELOG(error.localizedDescription)
}
}
//attempt to delete files with the same name. There's an issue when importing that the files do NOT get associated, so if we assume the user imported properly, the name should just be the same with different extensions.
let fileManager: FileManager = .default
guard let gameFileUrl = game.file?.url
else {
return
}
let parentDirectory = gameFileUrl.deletingLastPathComponent()
guard fileManager.fileExists(atPath: parentDirectory.pathDecoded)
else {
return
}
let children: [String]
do {
children = try fileManager.subpathsOfDirectory(atPath: parentDirectory.pathDecoded)
} catch {
ELOG("error retrieving files at directory: \(parentDirectory), \(error)")
return
}
guard !children.isEmpty
else {
return
}
DLOG("children: \(children)")
let fileName = gameFileUrl.deletingPathExtension().lastPathComponent
DLOG("fileName without extension: \(fileName)")
children.forEach { child in
let currentChildUrl = parentDirectory.appendingPathComponent(child)
let currentExtension = currentChildUrl.pathExtension
let currentChildFileName = currentChildUrl.deletingPathExtension().lastPathComponent
DLOG("current extension: \(currentExtension), current file name: \(currentChildFileName), current url: \(currentChildUrl)")
if !currentExtension.isEmpty
&& (currentChildFileName == fileName
|| currentChildFileName.starts(with: "\(fileName) (Track ")
|| currentChildFileName.starts(with: "\(fileName) (Disc ")
) {
do {
try fileManager.removeItem(at: currentChildUrl)
} catch {
ELOG("error deleting file: \(currentChildUrl)")
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,27 @@ public final class GameImporter: GameImporting, ObservableObject {

importQueue.remove(atOffsets: offsets)
}

/// Searches for successful imports filtered by files and removes from importQueue and files. This is so that only files imported by iCloud can be removed
/// - Parameter files: set of files to check
public func removeSuccessfulImports(from files: inout Set<URL>) {
guard !files.isEmpty
else {
return
}
importQueueLock.lock()
defer {
importQueueLock.unlock()
}
let offsets = IndexSet(importQueue.enumerated().compactMap { index, item in
if item.status == .success && files.contains(item.url) {
files.remove(item.url)
return index
}
return nil
})
importQueue.remove(atOffsets: offsets)
}

// Public method to manually start processing if needed
public func startProcessing() {
Expand Down Expand Up @@ -658,6 +679,11 @@ public final class GameImporter: GameImporting, ObservableObject {

// Processes each ImportItem in the queue sequentially
private func processQueue() async {
defer {
DispatchQueue.main.async {
NotificationCenter.default.post(name: .RomsFinishedImporting, object: nil)
}
}
// Check for items that are either queued or have a user-chosen system
let itemsToProcess = importQueue.filter {
$0.status == .queued || $0.userChosenSystem != nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class GameImporterDatabaseService : GameImporterDatabaseServicing {
throw GameImporterError.noSystemMatched
}

let file = PVFile(withURL: queueItem.destinationUrl!)
let file = PVFile(withURL: queueItem.destinationUrl!, relativeRoot: .iCloud)
let game = PVGame(withFile: file, system: system)
game.romPath = partialPath
game.title = title
Expand Down Expand Up @@ -205,7 +205,7 @@ class GameImporterDatabaseService : GameImporterDatabaseServicing {
}
if PVMediaCache.fileExists(forKey: url) {
if let localURL = PVMediaCache.filePath(forKey: url) {
let file = PVImageFile(withURL: localURL, relativeRoot: .iCloud)
let file = PVImageFile(withURL: localURL, relativeRoot: .documents)
game.originalArtworkFile = file
return game
}
Expand All @@ -229,15 +229,15 @@ class GameImporterDatabaseService : GameImporterDatabaseServicing {
if let artwork = NSImage(data: data) {
do {
let localURL = try PVMediaCache.writeImage(toDisk: artwork, withKey: url)
let file = PVImageFile(withURL: localURL, relativeRoot: .iCloud)
let file = PVImageFile(withURL: localURL, relativeRoot: .documents)
game.originalArtworkFile = file
} catch { ELOG("\(error.localizedDescription)") }
}
#elseif !os(watchOS)
if let artwork = UIImage(data: data) {
do {
let localURL = try PVMediaCache.writeImage(toDisk: artwork, withKey: url)
let file = PVImageFile(withURL: localURL, relativeRoot: .iCloud)
let file = PVImageFile(withURL: localURL, relativeRoot: .documents)
game.originalArtworkFile = file
} catch { ELOG("\(error.localizedDescription)") }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ class GameImporterSystemsService: GameImporterSystemsServicing {
}

func determineSystems(for item: ImportQueueItem) async throws -> [SystemIdentifier] {
// First try MD5 lookup
// if syncing from icloud, we have the system, so try to get the system this way
if let system = SystemIdentifier(rawValue: item.url.deletingLastPathComponent().lastPathComponent) {
DLOG("found system: \(system)")
return [system]
}
// next try MD5 lookup
if let md5 = item.md5 {
if let systemID = try await lookup.systemIdentifier(forRomMD5: md5, or: item.url.lastPathComponent) {
return [systemID]
Expand Down
Loading
Loading