KMP migration M2: iOS support, device verification round, CMP rebrand - #14
Merged
Merged
Conversation
… to updraft-sdk Without the Compose compiler plugin, updraft-sdk's setContent lambdas compiled as plain Function0 and crashed with NoSuchMethodError when any Updraft dialog opened. The sample also lacked the :updraft-sdk dependency, so no collector was subscribed to Updraft.events on Android and all dialogs were silently dropped.
Charcoal chrome with Updraft logo header, color swatches with selection halo, dashed undo button, draw-hint overlay, white box form fields and yellow action buttons, per legacy layouts from dd72439^. Content now padded by safeDrawing insets. Default stroke black at 4dp like legacy FreeDrawView.
Staging base URL u2.mqd.me is unreachable (connection fails), which made every feedback upload and update check fail. Sample now uses the default production base URL where the configured keys are valid.
…ng URL The server field is device_uudid (as sent by the iOS SDK), not device_uuid, so the UUID never showed up on the dashboard. Navigation stack was never implemented on Android; it now reports the host app's activity stack (Android) or view controller chain (iOS), excluding Updraft's own screens. BASE_URL_STAGING pointed at u2.mqd.me which no longer resolves; baseUrl stays overridable for self-hosted instances.
Navigation stack is captured when feedback is triggered, before the Updraft UI covers the app. Apps using single-activity navigation (Compose Navigation, Navigation Component) can plug their library in via Updraft.navigationStackProvider; the platform default reports the activity stack (Android) or view controller chain (iOS). Also fixes the package filter that swallowed host activities whose package merely shares the com.appswithlove.updraft prefix, like the sample app.
The legacy iOS SDK never used shake detection; its feedback trigger was UIApplicationUserDidTakeScreenshotNotification. The accelerometer-based shake also cannot work on the simulator (no accelerometer), so shake appeared broken there. Both triggers are now active on iOS: screenshot (all environments, legacy parity) and shake (physical devices).
Shake reaches iOS apps as a responder-chain motion event, not as accelerometer data, so the CMMotionManager detector never fired on the simulator and required nothing in the responder chain to consume the event on devices. The SDK now swizzles UIWindow.motionEnded:withEvent: at start, calling through to the original implementation. The IMP is a staticCFunction rather than a Kotlin lambda: block bridging would marshal the NSInteger motion argument as an object and crash.
The repo stays and becomes the single home for Android + iOS: root project renamed to updraft-sdk, POM name/URLs point at the new repo slug, README repositions the SDK as Kotlin/Compose Multiplatform and notes that updraft-sdk-ios is superseded. GitHub-side rename and archiving updraft-sdk-ios remain manual release-time steps.
… filter Superseded runs on the same ref are cancelled, ~/.konan is cached (the Kotlin/Native toolchain was re-provisioned on every macOS run before), gradle/actions/setup-gradle replaces the basic setup-java cache and validates the wrapper jar, markdown/docs pushes no longer trigger builds, timeouts bound hung runs, and the redundant pull_request trigger and chmod steps are removed (exec bit is committed).
…rsions Publishing previously ran no tests: a bad push to production would ship broken artifacts that Maven Central cannot replace. The job now runs the full build plus iOS simulator tests first, fails fast if the version is already tagged, publishes under a 'maven-central' GitHub environment (protection rules can be added in settings), and uses the maintained softprops/action-gh-release instead of the archived actions/create-release. JDK unified to 17 to match CI.
The SDK is built with Kotlin 2.2 / CMP 1.9: Kotlin Android consumers need >= 2.1 (metadata n+1 rule), KMP/CMP consumers >= 2.2, Java-only and XCFramework consumers are unaffected. The README lists the exact compile-time errors older projects will see and the fix.
The legacy SDK fetched strings from Loco into Android res/; Compose Multiplatform resources use the same strings.xml format, so updateLoco now writes into updraft-ui-compose commonMain composeResources and both platforms share the result. The API key moves from the build file (exposed in git history — rotate it) to local.properties.
michelutke
requested review from
vladislavfrolov
and removed request for
yannickpulver
July 23, 2026 06:53
Loco is the source of truth again: asset IDs renamed to underscores (compose-resources rejects dots), the ten strings missing from Loco added with German translations, and the draw-hint copy fixed there. This file state is the updateLoco output: alphabetical order and the removal of two unused legacy plurals (relative-age formatting was never implemented in 2.0).
Restores the legacy 'Released 3 weeks ago. You're currently on version X.' message using kotlin.time (no new dependency). Buckets: just now under an hour, then hours/days/weeks/months/years plurals. The plurals live in plurals.xml so updateLoco, which only rewrites strings.xml, cannot clobber them. Falls back to the previous message when create_at is missing or unparseable.
19 tasks
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
M2 on top of #15: iOS support, first real device-verification round (which found and fixed several release blockers), and the repo rebrand to the multiplatform SDK.
:updraft-core(iosArm64,iosSimulatorArm64,iosX64): screenshot grabber (UIGraphicsImageRenderer), foreground observer, NSUserDefaults store, app info, and shake — see "How" for why shake needed three mechanisms.:updraft-ui-composeon iOS: same CMP feedback UI;UpdraftIos.autoWire()presents dialogs/feedback on the topmost view controller;UpdraftFeedbackViewControllerfor manual hosting.device_uudidandnavigation_stack, withUpdraft.navigationStackProviderfor single-activity apps (Compose Navigation etc.) andUpdraftSettings(sendNavigationStack = false)opt-out. README documents per-library integration.sample/composeApp+sample/iosApp), keys loaded fromlocal.propertiesinstead of hardcoded.create_atrenders as "Released 3 weeks ago. You're currently on version X." (legacy parity,kotlin.time, unit-tested buckets; plurals live inplurals.xmloutside Loco's reach). Strings are synced with Loco again — asset IDs renamed to underscores, missing assets added,updateLocoround-trip verified.updraft-sdk(root project name, POM URLs, README repositioning; supersedesupdraft-sdk-ios). Overview doc:docs/cmp-migration-overview.md.Why
How / notable findings (each cost real debugging)
:updraft-sdkcrashed on any dialog — the module never applied the Compose compiler plugin, sosetContentlambdas compiled as plainFunction0→NoSuchMethodErrorat runtime. No compile error (the diagnostic comes from the plugin itself).device_uudid(double-U, a 2018 typo in the backend/iOS SDK contract) — sending the sanedevice_uuidsilently drops the value.motionEnded:), not accelerometer data. The SDK hooksUIWindow.motionEnded:withEvent:via the ObjC runtime so no host-app integration is needed (same approach as Instabug); the IMP is astaticCFunctionbecause Kotlin block bridging marshals theNSIntegermotion argument as an object and segfaults. CoreMotion (device) and the legacy screenshot-notification trigger are kept as well.BASE_URL_STAGING(u2.mqd.me) is dead — removed from the public API;baseUrlstays overridable.Verified
docs/kmp-migration-m1-status.md.Closes #13 — with iOS targets and the Compose Multiplatform UI shipping here, the SDK is usable from KMP/CMP projects on both platforms.