Sync local profiles consistently (#1051)

Rather than redoing ProfileManager.observeLocal() altogether:

- Keep the existing profiles subscription (localSubscription)
- Reload ALL local profiles on NE notifications

The reload is "heavy" because each profile save causes a reload of ALL
profiles, but it's the most reliable approach and in the end, it only
takes 1-2msec. It can be improved later.

Partially reverts #1049, because the app did not sync when a VPN
configuration was deleted from the OS settings.
This commit is contained in:
Davide 2025-01-04 23:42:10 +01:00 committed by GitHub
parent 236df80950
commit 2f67bcbbf2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 8 additions and 32 deletions

View File

@ -41,7 +41,7 @@
"kind" : "remoteSourceControl",
"location" : "git@github.com:passepartoutvpn/passepartoutkit-source",
"state" : {
"revision" : "6c98ac490edace667f2587ffaf57a5b6a467aa52"
"revision" : "8ced87ec9ea088603798be820ab8e2f1e71c2196"
}
},
{

View File

@ -62,7 +62,7 @@ let package = Package(
],
dependencies: [
// .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", from: "0.14.0"),
.package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", revision: "6c98ac490edace667f2587ffaf57a5b6a467aa52"),
.package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", revision: "8ced87ec9ea088603798be820ab8e2f1e71c2196"),
// .package(path: "../../passepartoutkit-source"),
// .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source-openvpn-openssl", from: "1.0.0"),
.package(url: "git@github.com:passepartoutvpn/passepartoutkit-source-openvpn-openssl", revision: "12c8b9166ba2bf98b63d3ebc5b561ac2ac5a2f86"),

View File

@ -45,7 +45,6 @@ public final class NEProfileRepository: ProfileRepository {
repository
.managersPublisher
.dropFirst()
.sink { [weak self] in
self?.onUpdatedManagers($0)
}
@ -72,26 +71,14 @@ public final class NEProfileRepository: ProfileRepository {
public func saveProfile(_ profile: Profile) async throws {
try await repository.save(profile, forConnecting: false, options: nil, title: title)
if let index = profilesSubject.value.firstIndex(where: { $0.id == profile.id }) {
profilesSubject.value[index] = profile
} else {
profilesSubject.value.append(profile)
}
}
public func removeProfiles(withIds profileIds: [Profile.ID]) async throws {
guard !profileIds.isEmpty else {
return
}
var removedIds: Set<Profile.ID> = []
defer {
profilesSubject.value.removeAll {
removedIds.contains($0.id)
}
}
for id in profileIds {
try await repository.remove(profileId: id)
removedIds.insert(id)
}
}
@ -102,25 +89,14 @@ public final class NEProfileRepository: ProfileRepository {
private extension NEProfileRepository {
func onUpdatedManagers(_ managers: [Profile.ID: NETunnelProviderManager]) {
let profiles = profilesSubject
.value
.filter {
managers.keys.contains($0.id)
let profiles = managers.values.compactMap {
do {
return try repository.profile(from: $0)
} catch {
pp_log(.App.profiles, .error, "Unable to decode profile from NE manager '\($0.localizedDescription ?? "")': \(error)")
return nil
}
let removedProfilesDescription = profilesSubject
.value
.filter {
!managers.keys.contains($0.id)
}
.map {
"\($0.name)(\($0.id)"
}
if !removedProfilesDescription.isEmpty {
pp_log(.App.profiles, .info, "Sync profiles removed externally: \(removedProfilesDescription)")
}
profilesSubject.send(profiles)
}
}