b48a47ce10
- 1A: Notificación mensual de resumen de portfolio (día 5 de cada mes) - 1B: Badge de racha mensual en Dashboard (streak counter) - 1C: Empty states mejorados en Goals y Journal con CTAs claros - 2A: Quick Update sheet — actualiza todas las fuentes desde una pantalla - 2B: Notificación batch update redirige al Quick Update sheet - 2C: Widget deep link portfoliojournal://quickupdate abre Quick Update - 3A: App Store version check banner en Settings - 3C: What's New sheet en primer launch de versión nueva - Localización completa en 7 idiomas para todas las nuevas strings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
37 lines
1.3 KiB
Swift
37 lines
1.3 KiB
Swift
import Foundation
|
|
import Combine
|
|
|
|
@MainActor
|
|
class AppUpdateService: ObservableObject {
|
|
static let shared = AppUpdateService()
|
|
@Published var updateAvailable = false
|
|
@Published var latestVersion: String?
|
|
|
|
private init() {}
|
|
|
|
func checkForUpdate() {
|
|
guard let bundleId = Bundle.main.bundleIdentifier else { return }
|
|
let urlString = "https://itunes.apple.com/lookup?bundleId=\(bundleId)"
|
|
guard let url = URL(string: urlString) else { return }
|
|
|
|
Task {
|
|
do {
|
|
let (data, _) = try await URLSession.shared.data(from: url)
|
|
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
let results = json["results"] as? [[String: Any]],
|
|
let first = results.first,
|
|
let appStoreVersion = first["version"] as? String,
|
|
let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
|
|
else { return }
|
|
|
|
if appStoreVersion.compare(currentVersion, options: .numeric) == .orderedDescending {
|
|
self.updateAvailable = true
|
|
self.latestVersion = appStoreVersion
|
|
}
|
|
} catch {
|
|
// silently fail
|
|
}
|
|
}
|
|
}
|
|
}
|