[UNTIL-19417] Migrate ImageBitmap to Compose Multiplatform & add iOS sample app - #55
Merged
djordjeh merged 19 commits intoMar 26, 2026
Merged
Conversation
Replace custom expect/actual ImageBitmap with androidx.compose.ui.graphics.ImageBitmap from Compose Multiplatform as the unified cross-platform image abstraction. - Use Compose ImageBitmap directly across all modules (no typealias indirection) - Implement iOS encodeToBase64() via Skia PNG encoding - Implement iOS BarcodeEncoder using CoreImage (CIQRCodeGenerator, CICode128BarcodeGenerator) - Convert Android plugin controllers (Star, Epson, Sunmi) to use asAndroidBitmap() at SDK boundary - Android BarcodeEncoder returns Compose ImageBitmap via asImageBitmap() - Add Compose plugins to print-engine, star, and epson modules - Update all test files for new ImageBitmap type conversions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
djordjeh
requested changes
Mar 18, 2026
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
shekar-allam
force-pushed
the
shekar/task/UNTIL-19417/print-engine-kmp-3.0.5
branch
from
March 18, 2026 12:34
7e68853 to
8cebb40
Compare
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SloInfinity
reviewed
Mar 18, 2026
…OS printing
- Remove INFOPLIST_KEY_UIApplicationSceneManifest_Generation from project.pbxproj
to prevent auto-enabling UIApplicationSupportsMultipleScenes=true, which caused
Compose to render into zero-size frames on iPad (Stage Manager / multi-window)
- Add UIApplicationSceneManifest{UIApplicationSupportsMultipleScenes=false} and
NSBluetoothAlwaysUsageDescription to Info.plist; without the Bluetooth key iOS
silently terminates any app linked against CoreBluetooth on physical devices
- Wrap Epos2Discovery.start() in withContext(Dispatchers.Main) — Epson SDK requires
the iOS main thread for discovery start/stop
- Implement EpsonPrinterController, EpsonPrintService, EpsonServiceProvider,
StarServiceProvider, EpsonPrinterErrorState iOS actuals (replace TODO stubs)
- Add nativeInterop cinterop def + README for Epson ePOS2 SDK integration
- Wire up MainViewController to live printer discovery and print job dispatch
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…thread safety
- Fix all ePOS2.h enum constants to match actual SDK header values:
EPOS2_MECHANICAL_ERR 0→1, AUTOCUTTER_ERR 1→2, UNRECOVER_ERR 2→3,
AUTORECOVER_ERR 3→4, CODE_PRINTING 1→13, LOW_VOLTAGE_ERR 0→1
- Add EPOS2_NO_ERR and EPOS2_UNKNOWN checks in evaluateStatusInfo
- Check every Epson SDK return code via checkSdkResult() — iOS SDK
returns int error codes unlike Android which throws Epos2Exception
- Guard disconnect() — only call if connect() succeeded
- Close SkiaBitmap/SkiaImage after use to prevent native memory leaks
- Extract shared ImageBitmap.encodeToPngBytes() utility
- Replace remember{scope.launch} with LaunchedEffect(Unit)
- Use flowOn(IO) + collect on Main to avoid mutating Compose state
from background dispatcher
- Replace leaked module-level CoroutineScope with rememberCoroutineScope()
- Guard startPrintJob behind initialized check
- Fall back to TM-T88 for unknown printer models instead of crashing
- Close SkiaImage in BarcodeEncoderImpl after toComposeImageBitmap()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ocol - Show discovery state (searching/found/error) in the sample UI so connection issues are immediately visible on device - Add UISupportedExternalAccessoryProtocols with com.epson.escpos to Info.plist for MFi Bluetooth/USB printer discovery - Fix initialized flag to use mutableStateOf so it survives recomposition Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Strip all printer discovery code from this branch to keep it focused on core iOS printing infrastructure. Discovery will be added as a separate feature in the UNTIL-19514 branch. Removed: - EpsonPrinterDiscovery.ios.kt implementation (reverted to TODO stub) - Discovery flow collection and discoveryStatus from MainViewController - discoveryStatus parameter from PrinterLayout - Discovery permissions from Info.plist (Bluetooth, LocalNetwork, Bonjour, ExternalAccessory) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement full Epson printer discovery on iOS using the ePOS2 SDK: - EpsonPrinterDiscovery.ios.kt: callbackFlow-based discovery using Epos2Discovery with Epos2FilterOption (all ports, printer type). Dispatches start() to Main thread, references delegate in awaitClose to prevent GC, maps device info to ExternalPrinter model - MainViewController: LaunchedEffect-based discovery flow collection with discoveryStatus state (Idle/Discovering/Error), flowOn(IO) for background work with Main-thread Compose state updates - PrinterLayout: discoveryStatus parameter showing search progress - Info.plist: NSBluetoothAlwaysUsageDescription, NSLocalNetworkUsageDescription, NSBonjourServices, UISupportedExternalAccessoryProtocols for Bluetooth/LAN/USB printer discovery permissions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Gradle task to auto-download Epson ePOS SDK xcframework on first iOS build, eliminating manual setup steps - Consolidate SDK config into EpsonSdk object with centralized version, repo URL, and architecture slice constants - DRY up iOS target configuration with configureEpsonInterop() extension - Move EpsonServiceProviderTest from instrumented to unit test with proper null-guard coverage - Update nativeInterop README with auto-download instructions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ekar/task/UNTIL-19514/print-engine-epson-ios-support
- Add Gradle task to auto-download Epson ePOS SDK xcframework on first iOS build, eliminating manual setup steps - Consolidate SDK config into EpsonSdk object with centralized version, repo URL, and architecture slice constants - DRY up iOS target configuration with configureEpsonInterop() extension - Move EpsonServiceProviderTest from instrumented to unit test with proper null-guard coverage - Update nativeInterop README with auto-download instructions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
shekar-allam
force-pushed
the
shekar/task/UNTIL-19417/print-engine-kmp-3.0.5
branch
from
March 20, 2026 08:41
b99ae89 to
db1b743
Compare
…ekar/task/UNTIL-19514/print-engine-epson-ios-support # Conflicts: # print-plugins/epson/build.gradle.kts # print-plugins/epson/src/androidUnitTest/kotlin/de/tillhub/printengine/epson/EpsonServiceProviderTest.kt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nts directly Enable cinterop commonization so Epson SDK constants (enums, #defines) are available in the shared iosMain source set. Replace ~60 hardcoded constants with direct imports from com.epson.epos2. Add a UIKit shim header that imports only UIImage.h instead of all of UIKit, preventing the commonizer from crashing on platform-specific UIKit types (UIMenuSystemElementGroupPreference) that differ across iOS targets. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ral only Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SloInfinity
approved these changes
Mar 24, 2026
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ine-epson-ios-support [UNTIL-19514] Print engine epson ios support
djordjeh
approved these changes
Mar 26, 2026
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.
Summary
ImageBitmapfrom customexpect/actualclass to Compose Multiplatform'sImageBitmap, enabling cross-platform image handlingBarcodeEncoderusing CoreImageCIFilterfor QR code and Code 128 generationencodeToBase64()using Skia bitmap APIsChanges
expect class ImageBitmapwithandroidx.compose.ui.graphics.ImageBitmap, addapi(compose.ui)dependencyasAndroidBitmap()bridge on AndroidMainViewControllerusingComposeUIViewControllerBitmap.createBitmap().asImageBitmap()with Robolectric where neededPrintCommand.Barcode.toString()returning "PrintCommand.Text" instead of "PrintCommand.Barcode"Test plan
./gradlew spotlessCheckpasses./gradlew testDebugpasses (all unit tests green)Output:
iOS
Android
🤖 Generated with Claude Code