Add App Store automatic update check via iTunes Lookup API - #42
Add App Store automatic update check via iTunes Lookup API#42stanchevskid wants to merge 3 commits into
Conversation
Implement checkForUpdatesFromAppStore extension on PrinceOfVersions that queries the iTunes Lookup API for the latest app version. Supports phased release tracking, notification frequency (once/always), configurable network timeout, and optional bundle ID override.
Extract JSON deserialization and result extraction into private helper methods to reduce the number of throw statements in parse().
There was a problem hiding this comment.
Pull request overview
This pull request adds a new checkForUpdatesFromAppStore extension function to enable zero-config update checks against the Apple App Store via the iTunes Lookup API for iOS. The implementation provides support for phased release tracking, configurable notification frequency (ONCE/ALWAYS), custom network timeouts, and optional bundle ID override.
Changes:
- Adds
checkForUpdatesFromAppStore()extension function with phased release tracking and notification frequency controls - Implements iTunes Lookup API response parsing via
AppStoreResponseParser - Adds phased release window detection via
AppStorePhasedReleaseChecker - Adds NSUserDefaults-backed storage for App Store version tracking via
IosAppStoreStorage
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| IosPrinceOfVersions.kt | Adds main extension function with App Store check logic and notification frequency handling |
| AppStoreResponseParser.kt | Parses iTunes Lookup API JSON responses to extract version and release date |
| AppStorePhasedReleaseChecker.kt | Determines if a version is still within its 7-day phased rollout period |
| IosAppStoreStorage.kt | Implements Storage interface using NSUserDefaults for persisting last notified version |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Cover AppStoreResponseParser (10 tests), AppStorePhasedReleaseChecker (6 tests), and IosAppStoreStorage (3 tests) with scenarios for valid inputs, edge cases, and error conditions.
|
I assume that this functionality is present in the original iOS prince of versions and is missing here? My question is whether adding this is urgent? My worry is that from the perspective of a KMP app, having this functionality only in the iOS platform module diverges the API of the platform modules and makes using the lib more convoluted. Now a KMP user for the iOS module can query the App Store, but for the Android/Jvm module needs to host a config json. If the platform module APIs diverge enough, from the lib users perspective, the benefit of using a single lib which has a similar API on all modules compared to different libs per module with different api's disappears. I synced with @antunflas and we came to the conclusion that we should likely plan adding support for this behaviour in a separate, stand alone module, which covers all iOS/Android stores and perhaps jvm if we find something that makes sense there. The implementation specifics of this are not clear yet and some time would need to be set aside to investigate and plan this. But if adding this behaviour to the iOS module is urgent, we can merge this now and plan the module implementation variant and a major, breaking release later. Additionally, it would be good to document this new behaviour in the readme as well. Also, @KCeh, I suggest adding codeowners and automatic assignment to PR reviews so that changes to the lib get reviewed by all parties. |
| CancellationException::class, | ||
| ) | ||
| public suspend fun PrinceOfVersions.checkForUpdatesFromAppStore( | ||
| trackPhaseRelease: Boolean = false, |
There was a problem hiding this comment.
The default for trackPhaseRelease here is false, but the native lib defaults it to true.
| ) | ||
| public suspend fun PrinceOfVersions.checkForUpdatesFromAppStore( | ||
| trackPhaseRelease: Boolean = false, | ||
| notificationFrequency: NotificationType = NotificationType.ONCE, |
There was a problem hiding this comment.
The default for notificationFrequency is ONCE here vs .always in the native lib.
| ConfigurationException::class, | ||
| CancellationException::class, | ||
| ) | ||
| public suspend fun PrinceOfVersions.checkForUpdatesFromAppStore( |
There was a problem hiding this comment.
Can you check the country: String? parameter that the native lib exposes is missing here.
| val appStoreInfo = AppStoreResponseParser.parse(jsonResponse) | ||
|
|
||
| if (appStoreInfo == null) { | ||
| BaseUpdateResult( |
There was a problem hiding this comment.
The native lib returns AppStoreUpdateResult, which exposes updateVersion, updateState, phaseReleaseInProgress, releaseDate, installedVersion, and lastVersionAvailable. Here we collapse everything down to BaseUpdateResult(version, status). The biggest practical loss is phaseReleaseInProgress, when trackPhaseRelease=true and the version is mid-rollout, the caller currently can't tell "in phased rollout, will be available soon" apart from "truly no update available." Native consumers use that to drive UI ("update coming soon" vs nothing). Suggest introducing a dedicated AppStoreUpdateResult type for the iOS surface that mirrors the native fields.
The intent here is to keep the KMP iOS surface 1:1 with ios-prince-of-versions so that consumers migrating from the native lib find the same API shape. That's why this lives only in iosMain — it mirrors the iOS-only checkForUpdateFromAppStore and isn't meant to be a cross-platform store-check abstraction. Agreed that a unified iOS+Android store module is the right long-term design and worth a separate, major release. This isn't urgent, but I'd rather not block the iOS parity piece on the Android side catching up — can we treat this PR as the iOS parity piece and track the unified module as a follow-up? @stanchevskid will add README docs and a note in the PR body calling out the planned cross-platform variant. |
Implement checkForUpdatesFromAppStore extension on PrinceOfVersions that queries the iTunes Lookup API for the latest app version. Supports phased release tracking, notification frequency (once/always), configurable network timeout, and optional bundle ID override.
Summary
Add a new
checkForUpdatesFromAppStoreextension function onPrinceOfVersionsthat enables zero-config update checks against the Apple App Store via the iTunes Lookup API. This complements the existing URL-based configuration check with a native App Store lookup path for iOS.Related issue: None
Changes
Type
Additional information
Description
Library (
princeofversions/src/iosMain)IosPrinceOfVersions.kt— AddedcheckForUpdatesFromAppStore()extension function with support for:ONCEsuppresses repeat notifications for the same version,ALWAYSalways reports)NSBundle.mainBundle.bundleIdentifier)AppStoreResponseParser.kt— Parses the iTunes Lookup API JSON response, extractingversionandcurrentVersionReleaseDate. ReturnsnullwhenresultCountis 0.AppStorePhasedReleaseChecker.kt— Determines whether a version is still within its 7-day phased rollout window based on the release date.IosAppStoreStorage.kt—Storageimplementation backed byNSUserDefaultsfor persisting the last notified App Store version.Checklist
Additional notes
App Store updates are never mandatory, so the result status will only ever be
UpdateStatus.OPTIONALorUpdateStatus.NO_UPDATE.