From f936298fef65ed19c220e341a58727cd6dbc07fb Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Mon, 6 Apr 2026 12:14:21 +0200 Subject: [PATCH 01/26] Create datastore using create function instead of Kotlin get --- .../io/github/chrisimx/scanbridge/ScanBridgeApplication.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt index 91667bb..0b05a2c 100644 --- a/app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt +++ b/app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt @@ -26,12 +26,14 @@ import org.koin.dsl.bind import org.koin.dsl.module import org.koin.plugin.module.dsl.factory import org.koin.plugin.module.dsl.single +import org.koin.plugin.module.dsl.create import org.koin.plugin.module.dsl.viewModel import timber.log.Timber +fun createAppSettingsDataStore(context: Context) = context.appSettingsStore val appModule = module { single> { - get().appSettingsStore + create(::createAppSettingsDataStore) } single() bind LocaleProvider::class single() bind DebugLogService::class From f7f942a4ba38a1865147e9ad67c38954ee7efb94 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Fri, 3 Apr 2026 20:08:19 +0200 Subject: [PATCH 02/26] Add ScanBridge (android) to a multiplatform skeleton --- README.MD.other | 19 + README.md | 12 +- {app => androidApp}/.gitignore | 0 CHANGELOG.md => androidApp/CHANGELOG.md | 0 CONTRIBUTING.md => androidApp/CONTRIBUTING.md | 0 COPYING => androidApp/COPYING | 0 Gemfile => androidApp/Gemfile | 0 Gemfile.lock => androidApp/Gemfile.lock | 0 adb+.sh => androidApp/adb+.sh | 0 ...ItOnGooglePlay_Badge_Web_color_English.svg | 0 .../assets}/get-it-on-fdroid.svg | 0 {assets => androidApp/assets}/icon.svg | 0 {app => androidApp}/build.gradle.kts | 28 +- {fastlane => androidApp/fastlane}/Appfile | 0 {fastlane => androidApp/fastlane}/Fastfile | 0 {fastlane => androidApp/fastlane}/README.md | 0 .../fastlane}/Screengrabfile | 0 .../android/de-DE/changelogs/1000000.txt | 0 .../android/de-DE/changelogs/1000001.txt | 0 .../android/de-DE/changelogs/1001000.txt | 0 .../android/de-DE/changelogs/1002000.txt | 0 .../android/de-DE/changelogs/1003000.txt | 0 .../android/de-DE/changelogs/1004000.txt | 0 .../android/de-DE/changelogs/1005000.txt | 0 .../android/de-DE/changelogs/1006001.txt | 0 .../android/de-DE/changelogs/1006002.txt | 0 .../android/de-DE/changelogs/2000000.txt | 0 .../android/de-DE/changelogs/2000001.txt | 0 .../android/de-DE/changelogs/2001002.txt | 0 .../android/de-DE/changelogs/2001003.txt | 0 .../android/de-DE/changelogs/2001004.txt | 0 .../android/de-DE/full_description.txt | 0 .../01-scannedPageScreen_1773391883115.png | Bin .../02-scanSettings_1773391879801.png | Bin .../03-discoveryScreen_1773391880499.png | Bin .../04-emptyScanScreen_1773391882198.png | Bin .../05-settingsScreen_1773391884031.png | Bin .../01-scannedPageScreen_1773392085232.png | Bin .../02-scanSettings_1773392081788.png | Bin .../03-discoveryScreen_1773392082774.png | Bin .../04-emptyScanScreen_1773392084316.png | Bin .../05-settingsScreen_1773392086217.png | Bin .../01-scannedPageScreen_1772541896730.png | Bin .../02-scanSettings_1772541894045.png | Bin .../03-discoveryScreen_1772541894498.png | Bin .../04-emptyScanScreen_1772541895682.png | Bin .../05-settingsScreen_1772541897397.png | Bin .../android/de-DE/short_description.txt | 0 .../metadata/android/de-DE/title.txt | 0 .../android/en-US/changelogs/1000000.txt | 0 .../android/en-US/changelogs/1000001.txt | 0 .../android/en-US/changelogs/1001000.txt | 0 .../android/en-US/changelogs/1002000.txt | 0 .../android/en-US/changelogs/1003000.txt | 0 .../android/en-US/changelogs/1004000.txt | 0 .../android/en-US/changelogs/1005000.txt | 0 .../android/en-US/changelogs/1006001.txt | 0 .../android/en-US/changelogs/1006002.txt | 0 .../android/en-US/changelogs/2000000.txt | 0 .../android/en-US/changelogs/2000001.txt | 0 .../android/en-US/changelogs/2001002.txt | 0 .../android/en-US/changelogs/2001003.txt | 0 .../android/en-US/changelogs/2001004.txt | 0 .../android/en-US/full_description.txt | 0 .../metadata/android/en-US/images/icon.png | Bin .../01-scannedPageScreen_1773391873581.png | Bin .../02-scanSettings_1773391870896.png | Bin .../03-discoveryScreen_1773391871298.png | Bin .../04-emptyScanScreen_1773391872597.png | Bin .../05-settingsScreen_1773391874196.png | Bin .../01-scannedPageScreen_1773392074370.png | Bin .../02-scanSettings_1773392071595.png | Bin .../03-discoveryScreen_1773392071982.png | Bin .../04-emptyScanScreen_1773392073386.png | Bin .../05-settingsScreen_1773392074964.png | Bin .../01-scannedPageScreen_1772541886403.png | Bin .../02-scanSettings_1772541881705.png | Bin .../03-discoveryScreen_1772541884121.png | Bin .../04-emptyScanScreen_1772541885597.png | Bin .../05-settingsScreen_1772541889078.png | Bin .../android/en-US/short_description.txt | 0 .../metadata/android/en-US/title.txt | 0 .../android/it-IT/changelogs/1000000.txt | 0 .../android/it-IT/changelogs/1000001.txt | 0 .../android/it-IT/changelogs/1001000.txt | 0 .../android/it-IT/changelogs/1002000.txt | 0 .../android/it-IT/changelogs/1003000.txt | 0 .../android/it-IT/changelogs/1004000.txt | 0 .../android/it-IT/changelogs/1005000.txt | 0 .../android/it-IT/changelogs/1006001.txt | 0 .../android/it-IT/changelogs/1006002.txt | 0 .../android/it-IT/changelogs/2000000.txt | 0 .../android/it-IT/changelogs/2000001.txt | 0 .../android/it-IT/changelogs/2001002.txt | 0 .../android/it-IT/changelogs/2001003.txt | 0 .../android/it-IT/changelogs/2001004.txt | 0 .../android/it-IT/full_description.txt | 0 .../01-scannedPageScreen_1773391892623.png | Bin .../02-scanSettings_1773391889434.png | Bin .../03-discoveryScreen_1773391890147.png | Bin .../04-emptyScanScreen_1773391891679.png | Bin .../05-settingsScreen_1773391893582.png | Bin .../01-scannedPageScreen_1773392097014.png | Bin .../02-scanSettings_1773392093573.png | Bin .../03-discoveryScreen_1773392094636.png | Bin .../04-emptyScanScreen_1773392096232.png | Bin .../05-settingsScreen_1773392098119.png | Bin .../01-scannedPageScreen_1772541911340.png | Bin .../02-scanSettings_1772541904718.png | Bin .../03-discoveryScreen_1772541907169.png | Bin .../04-emptyScanScreen_1772541910309.png | Bin .../05-settingsScreen_1772541914017.png | Bin .../android/it-IT/short_description.txt | 0 .../metadata/android/it-IT/title.txt | 0 .../metadata/android/screenshots.html | 0 .../playMetadata/de-DE/changelogs/1006002.txt | 0 .../playMetadata/de-DE/changelogs/2000000.txt | 0 .../playMetadata/de-DE/changelogs/2000001.txt | 0 .../playMetadata/de-DE/changelogs/2001002.txt | 0 .../playMetadata/de-DE/changelogs/2001003.txt | 0 .../playMetadata/de-DE/changelogs/2001004.txt | 0 .../playMetadata/de-DE/full_description.txt | 0 .../01-scannedPageScreen_1773392137705.png | Bin .../02-scanSettings_1773392134051.png | Bin .../03-discoveryScreen_1773392134837.png | Bin .../04-emptyScanScreen_1773392136515.png | Bin .../05-settingsScreen_1773392138645.png | Bin .../06-supportScreen_1773392131057.png | Bin .../de-DE/images/featureGraphic.png | Bin .../01-scannedPageScreen_1773391854599.png | Bin .../02-scanSettings_1773391851373.png | Bin .../03-discoveryScreen_1773391852033.png | Bin .../04-emptyScanScreen_1773391853682.png | Bin .../05-settingsScreen_1773391855601.png | Bin .../06-supportScreen_1773391848067.png | Bin .../01-scannedPageScreen_1773392051915.png | Bin .../02-scanSettings_1773392048636.png | Bin .../03-discoveryScreen_1773392049419.png | Bin .../04-emptyScanScreen_1773392051098.png | Bin .../05-settingsScreen_1773392052967.png | Bin .../06-supportScreen_1773392044965.png | Bin .../01-scannedPageScreen_1772541856637.png | Bin .../02-scanSettings_1772541853898.png | Bin .../03-discoveryScreen_1772541854300.png | Bin .../04-emptyScanScreen_1772541855615.png | Bin .../05-settingsScreen_1772541857282.png | Bin .../06-supportScreen_1772541851562.png | Bin .../playMetadata/de-DE/short_description.txt | 0 .../fastlane}/playMetadata/de-DE/title.txt | 0 .../fastlane}/playMetadata/de-DE/video.txt | 0 .../playMetadata/en-US/changelogs/1006002.txt | 0 .../playMetadata/en-US/changelogs/2000000.txt | 0 .../playMetadata/en-US/changelogs/2000001.txt | 0 .../playMetadata/en-US/changelogs/2001002.txt | 0 .../playMetadata/en-US/changelogs/2001003.txt | 0 .../playMetadata/en-US/changelogs/2001004.txt | 0 .../playMetadata/en-US/full_description.txt | 0 .../01-scannedPageScreen_1773392127266.png | Bin .../02-scanSettings_1773392124079.png | Bin .../03-discoveryScreen_1773392124691.png | Bin .../04-emptyScanScreen_1773392126076.png | Bin .../05-settingsScreen_1773392128027.png | Bin .../06-supportScreen_1773392121020.png | Bin .../en-US/images/featureGraphic.png | Bin .../playMetadata/en-US/images/icon.png | Bin .../01-scannedPageScreen_1773391844501.png | Bin .../02-scanSettings_1773391841799.png | Bin .../03-discoveryScreen_1773391842230.png | Bin .../04-emptyScanScreen_1773391843467.png | Bin .../05-settingsScreen_1773391845183.png | Bin .../06-supportScreen_1773391839216.png | Bin .../01-scannedPageScreen_1773392041217.png | Bin .../02-scanSettings_1773392038538.png | Bin .../03-discoveryScreen_1773392039016.png | Bin .../04-emptyScanScreen_1773392040264.png | Bin .../05-settingsScreen_1773392041800.png | Bin .../06-supportScreen_1773392036000.png | Bin .../01-scannedPageScreen_1772541846501.png | Bin .../02-scanSettings_1772541839135.png | Bin .../03-discoveryScreen_1772541841584.png | Bin .../04-emptyScanScreen_1772541845528.png | Bin .../05-settingsScreen_1772541849182.png | Bin .../06-supportScreen_1772541835912.png | Bin .../playMetadata/en-US/short_description.txt | 0 .../fastlane}/playMetadata/en-US/title.txt | 0 .../fastlane}/playMetadata/en-US/video.txt | 0 .../playMetadata/it-IT/changelogs/1006002.txt | 0 .../playMetadata/it-IT/changelogs/2000000.txt | 0 .../playMetadata/it-IT/changelogs/2000001.txt | 0 .../playMetadata/it-IT/changelogs/2001002.txt | 0 .../playMetadata/it-IT/changelogs/2001003.txt | 0 .../playMetadata/it-IT/changelogs/2001004.txt | 0 .../playMetadata/it-IT/full_description.txt | 0 .../01-scannedPageScreen_1773392147446.png | Bin .../02-scanSettings_1773392144173.png | Bin .../03-discoveryScreen_1773392144879.png | Bin .../04-emptyScanScreen_1773392146388.png | Bin .../05-settingsScreen_1773392148380.png | Bin .../06-supportScreen_1773392140988.png | Bin .../it-IT/images/featureGraphic.png | Bin .../01-scannedPageScreen_1773391864832.png | Bin .../02-scanSettings_1773391861554.png | Bin .../03-discoveryScreen_1773391862266.png | Bin .../04-emptyScanScreen_1773391863833.png | Bin .../05-settingsScreen_1773391865784.png | Bin .../06-supportScreen_1773391858142.png | Bin .../01-scannedPageScreen_1773392064698.png | Bin .../02-scanSettings_1773392060668.png | Bin .../03-discoveryScreen_1773392062139.png | Bin .../04-emptyScanScreen_1773392063851.png | Bin .../05-settingsScreen_1773392065789.png | Bin .../06-supportScreen_1773392056702.png | Bin .../01-scannedPageScreen_1772541871263.png | Bin .../02-scanSettings_1772541864073.png | Bin .../03-discoveryScreen_1772541866487.png | Bin .../04-emptyScanScreen_1772541870383.png | Bin .../05-settingsScreen_1772541873928.png | Bin .../06-supportScreen_1772541861315.png | Bin .../playMetadata/it-IT/short_description.txt | 0 .../fastlane}/playMetadata/it-IT/title.txt | 0 .../fastlane}/playMetadata/it-IT/video.txt | 0 .../fastlane}/playMetadata/screenshots.html | 0 .../gradle/gradle-daemon-jvm.properties | 13 + androidApp/gradle/libs.versions.toml | 100 +++++ {app => androidApp}/proguard-rules.pro | 0 .../1.json | 0 .../2.json | 0 .../src/androidTest/assets/scan-1.jpg | Bin .../chrisimx/scanbridge/ScanBridgeNavHost.kt | 0 .../chrisimx/scanbridge/ScanBridgeTest.kt | 0 .../screenshot/ScanBridgeScreenshotTest.kt | 0 .../src/debug/AndroidManifest.xml | 0 .../scanbridge/StartupTabDefinitions.kt | 0 .../src/main/AndroidManifest.xml | 0 .../src/main/ic_launcher-playstore.png | Bin .../chrisimx/scanbridge/AppSettingsScreen.kt | 0 .../chrisimx/scanbridge/CrashActivity.kt | 4 +- .../chrisimx/scanbridge/CrashHandler.kt | 0 .../github/chrisimx/scanbridge/CropScreen.kt | 4 +- .../chrisimx/scanbridge/MainActivity.kt | 0 .../chrisimx/scanbridge/ScanBridgeApp.kt | 4 +- .../scanbridge/ScanBridgeApplication.kt | 0 .../chrisimx/scanbridge/ScanBridgeNavHost.kt | 0 .../chrisimx/scanbridge/ScanSettings.kt | 0 .../chrisimx/scanbridge/ScannerBrowser.kt | 0 .../scanbridge/ScannerDiscoveryBackend.kt | 0 .../chrisimx/scanbridge/ScanningScreen.kt | 0 .../chrisimx/scanbridge/StartupScreen.kt | 0 .../ScanJobForegroundService.kt | 0 .../data/model/EditedCustomScanner.kt | 0 .../data/model/LegacyESCLScanSettings.kt | 0 .../scanbridge/data/model/LegacySessionV2.kt | 0 .../scanbridge/data/model/PaperFormat.kt | 0 .../chrisimx/scanbridge/data/model/ScanJob.kt | 0 .../data/ui/CustomScannerViewModel.kt | 0 .../ui/ScanSettingsComposableStateHolder.kt | 0 .../data/ui/ScanSettingsStateData.kt | 0 .../scanbridge/data/ui/ScanningScreenData.kt | 0 .../data/ui/ScanningScreenViewModel.kt | 0 .../scanbridge/datastore/DataStores.kt | 0 .../datastore/LastRouteStoreSerializer.kt | 0 .../datastore/ScanBridgeSettingsSerializer.kt | 0 .../datastore/ScanSettingsDataStoreHelpers.kt | 0 .../datastore/ShownMessagesSerializer.kt | 0 .../chrisimx/scanbridge/db/ScanBridgeDb.kt | 0 .../scanbridge/db/daos/CustomScannerDao.kt | 0 .../scanbridge/db/daos/ScannedPageDao.kt | 0 .../chrisimx/scanbridge/db/daos/SessionDao.kt | 0 .../scanbridge/db/daos/TempFileDao.kt | 0 .../scanbridge/db/entities/CustomScanner.kt | 0 .../scanbridge/db/entities/ScannedPage.kt | 0 .../scanbridge/db/entities/Session.kt | 0 .../scanbridge/db/entities/TempFile.kt | 0 .../ScanSettingsTypeConverter.kt | 0 .../ScanSettingsUiDataTypeConverter.kt | 0 .../db/typeconverters/UrlTypeConverter.kt | 0 .../db/typeconverters/UuidTypeConverter.kt | 0 .../chrisimx/scanbridge/logs/FileLogger.kt | 0 .../services/AndroidLocaleProvider.kt | 0 .../scanbridge/services/DebugLogService.kt | 0 .../services/FileDebugLogService.kt | 0 .../scanbridge/services/LocaleProvider.kt | 0 .../scanbridge/services/ScanJobRepository.kt | 0 .../stores/DefaultScanSettingsStore.kt | 0 .../stores/LegacyCustomScannerStore.kt | 0 .../scanbridge/stores/LegacySessionsStore.kt | 0 .../github/chrisimx/scanbridge/theme/Color.kt | 0 .../github/chrisimx/scanbridge/theme/Font.kt | 0 .../github/chrisimx/scanbridge/theme/Theme.kt | 0 .../chrisimx/scanbridge/theme/Typography.kt | 0 .../uicomponents/CrashFileHandler.kt | 0 .../scanbridge/uicomponents/CroppableImage.kt | 0 .../uicomponents/ExportSettingsPopup.kt | 0 .../uicomponents/FoundScannerItem.kt | 0 .../uicomponents/FullScreenError.kt | 0 .../scanbridge/uicomponents/LoadingScreen.kt | 0 .../uicomponents/SizeBasedConditionalView.kt | 0 .../uicomponents/TemporaryFileHandlePrompt.kt | 0 .../scanbridge/uicomponents/TitledCard.kt | 0 .../uicomponents/ValidatedTextField.kt | 0 .../uicomponents/dialog/ConfirmCloseDialog.kt | 0 .../uicomponents/dialog/CrashFileDialog.kt | 0 .../dialog/CustomScannerDialog.kt | 0 .../uicomponents/dialog/DeleteDialog.kt | 0 .../uicomponents/dialog/ErrorDialog.kt | 0 .../uicomponents/dialog/LoadingDialog.kt | 0 .../uicomponents/dialog/SimpleTextDialog.kt | 0 .../dialog/TemporaryFileHandlingDialog.kt | 0 .../uicomponents/settings/CheckboxSetting.kt | 0 .../settings/MoreInformationButton.kt | 0 .../uicomponents/settings/UIntSetting.kt | 0 .../settings/VersionComposable.kt | 0 .../scanbridge/util/ESCLKtExtensions.kt | 0 .../chrisimx/scanbridge/util/ImageUtil.kt | 0 .../util/NavControllerExtensions.kt | 0 .../chrisimx/scanbridge/util/PdfUtil.kt | 0 .../scanbridge/util/ScanFileNameUtil.kt | 0 .../scanbridge/util/ScanSettingsJson.kt | 0 .../scanbridge/util/StateFlowExtensions.kt | 0 .../chrisimx/scanbridge/util/TempFileUtil.kt | 0 .../scanbridge/util/TrustAllTrustManager.kt | 0 .../chrisimx/scanbridge/util/UIUtils.kt | 0 .../scanbridge/util/ZipArchiveUtil.kt | 0 .../src/main/proto/app_settings.proto | 0 .../src/main/proto/route_store.proto | 0 .../src/main/proto/shown_messages.proto | 0 .../main/res/drawable/baseline_image_24.xml | 0 .../drawable/baseline_picture_as_pdf_24.xml | 0 .../res/drawable/baseline_rotate_right_24.xml | 0 .../src/main/res/drawable/favorite_24px.xml | 0 .../src/main/res/drawable/github_mark.xml | 0 .../main/res/drawable/icon_about_dialog.png | Bin .../src/main/res/drawable/outline_crop_24.xml | 0 .../src/main/res/drawable/outline_edit_24.xml | 0 .../main/res/drawable/outline_error_24.xml | 0 .../res/drawable/outline_file_save_24.xml | 0 .../main/res/drawable/outline_pan_zoom_24.xml | 0 .../src/main/res/drawable/outline_scan_24.xml | 0 .../src/main/res/drawable/round_print_36.xml | 0 .../res/drawable/rounded_adf_scanner_24.xml | 0 .../res/drawable/rounded_content_copy_24.xml | 0 .../drawable/rounded_document_scanner_24.xml | 0 .../main/res/drawable/rounded_scanner_24.xml | 0 .../main/res/drawable/rounded_warning_24.xml | 0 .../res/drawable/twotone_wifi_find_24.xml | 0 .../src/main/res/font/poppins_black.ttf | Bin .../src/main/res/font/poppins_blackitalic.ttf | Bin .../src/main/res/font/poppins_bold.ttf | Bin .../src/main/res/font/poppins_bolditalic.ttf | Bin .../src/main/res/font/poppins_extrabold.ttf | Bin .../main/res/font/poppins_extrabolditalic.ttf | Bin .../src/main/res/font/poppins_extralight.ttf | Bin .../res/font/poppins_extralightitalic.ttf | Bin .../src/main/res/font/poppins_italic.ttf | Bin .../src/main/res/font/poppins_light.ttf | Bin .../src/main/res/font/poppins_lightitalic.ttf | Bin .../src/main/res/font/poppins_medium.ttf | Bin .../main/res/font/poppins_mediumitalic.ttf | Bin .../src/main/res/font/poppins_regular.ttf | Bin .../src/main/res/font/poppins_semibold.ttf | Bin .../main/res/font/poppins_semibolditalic.ttf | Bin .../src/main/res/font/poppins_thin.ttf | Bin .../src/main/res/font/poppins_thinitalic.ttf | Bin .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin .../mipmap-hdpi/ic_launcher_background.webp | Bin .../mipmap-hdpi/ic_launcher_foreground.webp | Bin .../res/mipmap-hdpi/ic_launcher_round.webp | Bin .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin .../mipmap-mdpi/ic_launcher_background.webp | Bin .../mipmap-mdpi/ic_launcher_foreground.webp | Bin .../res/mipmap-mdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin .../mipmap-xhdpi/ic_launcher_background.webp | Bin .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin .../mipmap-xxhdpi/ic_launcher_background.webp | Bin .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin .../ic_launcher_background.webp | Bin .../ic_launcher_foreground.webp | Bin .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin .../main/res/raw/test_scanner_capabilities | 0 .../src/main/res/resources.properties | 0 .../src/main/res/values-de/strings.xml | 0 .../src/main/res/values-it/strings.xml | 0 .../src/main/res/values/colors.xml | 0 .../src/main/res/values/strings.xml | 0 .../src/main/res/values/themes.xml | 0 .../src/main/res/xml/backup_rules.xml | 0 .../main/res/xml/data_extraction_rules.xml | 0 .../main/res/xml/network_security_config.xml | 0 .../src/main/res/xml/provider_paths.xml | 0 .../src/play/AndroidManifest.xml | 0 .../chrisimx/scanbridge/AccountSetupScreen.kt | 0 .../scanbridge/InternetConnectivityFlow.kt | 0 .../scanbridge/LicenseErrorStringMapping.kt | 0 .../scanbridge/OwnershipProofService.kt | 0 .../scanbridge/OwnershipTestScreen.kt | 0 .../scanbridge/PlainTextObfuscator.kt | 0 .../chrisimx/scanbridge/SignupScreen.kt | 0 .../scanbridge/SimpleStrictLicensePolicy.kt | 0 .../chrisimx/scanbridge/SpecialIcons.kt | 0 .../scanbridge/StartupTabDefinitions.kt | 0 .../scanbridge/SuccessSigningUpScreen.kt | 0 .../chrisimx/scanbridge/SupportScreen.kt | 0 .../zammadapi/AccountVerificationClient.kt | 0 .../zammadapi/AccountVerifierApi.kt | 0 .../models/AccountCreationRequest.kt | 0 .../zammadapi/models/GoogleChallenge.kt | 0 .../zammadapi/models/VIPCreationResult.kt | 0 .../src/play/res/drawable/fireamp_icon.xml | 0 .../play/res/drawable/outline_globe_24.xml | 0 .../src/play/res/values-de/strings.xml | 0 .../src/play/res/values-it/strings.xml | 0 .../src/play/res/values/strings.xml | 0 .../chrisimx/scanbridge/PaperFormatTest.kt | 0 .../scanbridge/ScanSettingsStoreTest.kt | 0 build.gradle.kts | 10 +- desktopApp/appIcons/LinuxIcon.png | Bin 0 -> 26701 bytes desktopApp/appIcons/MacosIcon.icns | Bin 0 -> 260854 bytes desktopApp/appIcons/WindowsIcon.ico | Bin 0 -> 31243 bytes desktopApp/build.gradle.kts | 33 ++ desktopApp/src/main/kotlin/main.kt | 18 + gradle.properties | 22 +- gradle/gradle-daemon-jvm.properties | 20 +- gradle/libs.versions.toml | 30 +- iosApp/iosApp.xcodeproj/project.pbxproj | 362 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 17324 bytes .../xcschemes/xcschememanagement.plist | 5 + .../xcschemes/iosApp.xcscheme | 66 ++++ .../xcschemes/xcschememanagement.plist | 14 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/AppIcon-20@2x.png | Bin 0 -> 1494 bytes .../AppIcon.appiconset/AppIcon-20@2x~ipad.png | Bin 0 -> 1494 bytes .../AppIcon.appiconset/AppIcon-20@3x.png | Bin 0 -> 2137 bytes .../AppIcon.appiconset/AppIcon-20~ipad.png | Bin 0 -> 636 bytes .../AppIcon.appiconset/AppIcon-29.png | Bin 0 -> 1272 bytes .../AppIcon.appiconset/AppIcon-29@2x.png | Bin 0 -> 2830 bytes .../AppIcon.appiconset/AppIcon-29@2x~ipad.png | Bin 0 -> 2830 bytes .../AppIcon.appiconset/AppIcon-29@3x.png | Bin 0 -> 3716 bytes .../AppIcon.appiconset/AppIcon-29~ipad.png | Bin 0 -> 1272 bytes .../AppIcon.appiconset/AppIcon-40@2x.png | Bin 0 -> 3170 bytes .../AppIcon.appiconset/AppIcon-40@2x~ipad.png | Bin 0 -> 3170 bytes .../AppIcon.appiconset/AppIcon-40@3x.png | Bin 0 -> 4420 bytes .../AppIcon.appiconset/AppIcon-40~ipad.png | Bin 0 -> 1494 bytes .../AppIcon.appiconset/AppIcon-60@2x~car.png | Bin 0 -> 4420 bytes .../AppIcon.appiconset/AppIcon-60@3x~car.png | Bin 0 -> 8223 bytes .../AppIcon-83.5@2x~ipad.png | Bin 0 -> 7382 bytes .../AppIcon.appiconset/AppIcon@2x.png | Bin 0 -> 4420 bytes .../AppIcon.appiconset/AppIcon@2x~ipad.png | Bin 0 -> 6476 bytes .../AppIcon.appiconset/AppIcon@3x.png | Bin 0 -> 8223 bytes .../AppIcon~ios-marketing.png | Bin 0 -> 67276 bytes .../AppIcon.appiconset/AppIcon~ipad.png | Bin 0 -> 3193 bytes .../AppIcon.appiconset/Contents.json | 130 +++++++ iosApp/iosApp/Assets.xcassets/Contents.json | 6 + iosApp/iosApp/Info.plist | 8 + .../Preview Assets.xcassets/Contents.json | 6 + iosApp/iosApp/iosApp.swift | 21 + .../play-licensing/lvl_library/build.gradle | 7 +- settings.gradle.kts | 7 +- shared/.gitignore | 2 + shared/build.gradle.kts | 69 ++++ .../composeResources/drawable/ic_cyclone.xml | 12 + .../drawable/ic_dark_mode.xml | 9 + .../drawable/ic_light_mode.xml | 9 + .../drawable/ic_rotate_right.xml | 10 + .../font/IndieFlower-Regular.ttf | Bin 0 -> 55416 bytes .../composeResources/values/strings.xml | 7 + .../io/github/chrisimx/scanbridge/App.kt | 104 +++++ .../github/chrisimx/scanbridge/theme/Color.kt | 80 ++++ .../github/chrisimx/scanbridge/theme/Theme.kt | 105 +++++ shared/src/iosMain/kotlin/main.kt | 22 ++ 477 files changed, 1334 insertions(+), 62 deletions(-) create mode 100644 README.MD.other rename {app => androidApp}/.gitignore (100%) rename CHANGELOG.md => androidApp/CHANGELOG.md (100%) rename CONTRIBUTING.md => androidApp/CONTRIBUTING.md (100%) rename COPYING => androidApp/COPYING (100%) rename Gemfile => androidApp/Gemfile (100%) rename Gemfile.lock => androidApp/Gemfile.lock (100%) rename adb+.sh => androidApp/adb+.sh (100%) rename {assets => androidApp/assets}/GetItOnGooglePlay_Badge_Web_color_English.svg (100%) rename {assets => androidApp/assets}/get-it-on-fdroid.svg (100%) rename {assets => androidApp/assets}/icon.svg (100%) rename {app => androidApp}/build.gradle.kts (89%) rename {fastlane => androidApp/fastlane}/Appfile (100%) rename {fastlane => androidApp/fastlane}/Fastfile (100%) rename {fastlane => androidApp/fastlane}/README.md (100%) rename {fastlane => androidApp/fastlane}/Screengrabfile (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1000000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1000001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1001000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1002000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1003000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1004000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1005000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1006001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/1006002.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/2000000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/2000001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/2001002.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/2001003.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/changelogs/2001004.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/full_description.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391883115.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/phoneScreenshots/02-scanSettings_1773391879801.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391880499.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391882198.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/phoneScreenshots/05-settingsScreen_1773391884031.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392085232.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392081788.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392082774.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392084316.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392086217.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541896730.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/tenInchScreenshots/02-scanSettings_1772541894045.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541894498.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541895682.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541897397.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/short_description.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/de-DE/title.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1000000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1000001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1001000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1002000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1003000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1004000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1005000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1006001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/1006002.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/2000000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/2000001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/2001002.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/2001003.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/changelogs/2001004.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/full_description.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/icon.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391873581.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/phoneScreenshots/02-scanSettings_1773391870896.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/phoneScreenshots/03-discoveryScreen_1773391871298.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391872597.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/phoneScreenshots/05-settingsScreen_1773391874196.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392074370.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/sevenInchScreenshots/02-scanSettings_1773392071595.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392071982.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392073386.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392074964.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541886403.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/tenInchScreenshots/02-scanSettings_1772541881705.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541884121.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541885597.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/images/tenInchScreenshots/05-settingsScreen_1772541889078.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/short_description.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/en-US/title.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1000000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1000001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1001000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1002000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1003000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1004000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1005000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1006001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/1006002.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/2000000.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/2000001.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/2001002.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/2001003.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/changelogs/2001004.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/full_description.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391892623.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/phoneScreenshots/02-scanSettings_1773391889434.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391890147.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391891679.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/phoneScreenshots/05-settingsScreen_1773391893582.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392097014.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392093573.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392094636.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392096232.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392098119.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541911340.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/tenInchScreenshots/02-scanSettings_1772541904718.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541907169.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541910309.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541914017.png (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/short_description.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/it-IT/title.txt (100%) rename {fastlane => androidApp/fastlane}/metadata/android/screenshots.html (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/changelogs/1006002.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/changelogs/2000000.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/changelogs/2000001.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/changelogs/2001002.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/changelogs/2001003.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/changelogs/2001004.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/full_description.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/chromeScreenshots/01-scannedPageScreen_1773392137705.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/chromeScreenshots/02-scanSettings_1773392134051.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/chromeScreenshots/03-discoveryScreen_1773392134837.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/chromeScreenshots/04-emptyScanScreen_1773392136515.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/chromeScreenshots/05-settingsScreen_1773392138645.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/chromeScreenshots/06-supportScreen_1773392131057.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/featureGraphic.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391854599.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/phoneScreenshots/02-scanSettings_1773391851373.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391852033.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391853682.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/phoneScreenshots/05-settingsScreen_1773391855601.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/phoneScreenshots/06-supportScreen_1773391848067.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392051915.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392048636.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392049419.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392051098.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392052967.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/sevenInchScreenshots/06-supportScreen_1773392044965.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541856637.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/tenInchScreenshots/02-scanSettings_1772541853898.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541854300.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541855615.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541857282.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/images/tenInchScreenshots/06-supportScreen_1772541851562.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/short_description.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/title.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/de-DE/video.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/changelogs/1006002.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/changelogs/2000000.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/changelogs/2000001.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/changelogs/2001002.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/changelogs/2001003.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/changelogs/2001004.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/full_description.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/chromeScreenshots/01-scannedPageScreen_1773392127266.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/chromeScreenshots/02-scanSettings_1773392124079.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/chromeScreenshots/03-discoveryScreen_1773392124691.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/chromeScreenshots/04-emptyScanScreen_1773392126076.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/chromeScreenshots/05-settingsScreen_1773392128027.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/chromeScreenshots/06-supportScreen_1773392121020.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/featureGraphic.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/icon.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391844501.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/phoneScreenshots/02-scanSettings_1773391841799.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/phoneScreenshots/03-discoveryScreen_1773391842230.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391843467.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/phoneScreenshots/05-settingsScreen_1773391845183.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/phoneScreenshots/06-supportScreen_1773391839216.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392041217.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/sevenInchScreenshots/02-scanSettings_1773392038538.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392039016.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392040264.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392041800.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/sevenInchScreenshots/06-supportScreen_1773392036000.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541846501.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/tenInchScreenshots/02-scanSettings_1772541839135.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541841584.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541845528.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/tenInchScreenshots/05-settingsScreen_1772541849182.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/images/tenInchScreenshots/06-supportScreen_1772541835912.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/short_description.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/title.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/en-US/video.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/changelogs/1006002.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/changelogs/2000000.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/changelogs/2000001.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/changelogs/2001002.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/changelogs/2001003.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/changelogs/2001004.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/full_description.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/chromeScreenshots/01-scannedPageScreen_1773392147446.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/chromeScreenshots/02-scanSettings_1773392144173.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/chromeScreenshots/03-discoveryScreen_1773392144879.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/chromeScreenshots/04-emptyScanScreen_1773392146388.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/chromeScreenshots/05-settingsScreen_1773392148380.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/chromeScreenshots/06-supportScreen_1773392140988.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/featureGraphic.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391864832.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/phoneScreenshots/02-scanSettings_1773391861554.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391862266.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391863833.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/phoneScreenshots/05-settingsScreen_1773391865784.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/phoneScreenshots/06-supportScreen_1773391858142.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392064698.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392060668.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392062139.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392063851.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392065789.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/sevenInchScreenshots/06-supportScreen_1773392056702.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541871263.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/tenInchScreenshots/02-scanSettings_1772541864073.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541866487.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541870383.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541873928.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/images/tenInchScreenshots/06-supportScreen_1772541861315.png (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/short_description.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/title.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/it-IT/video.txt (100%) rename {fastlane => androidApp/fastlane}/playMetadata/screenshots.html (100%) create mode 100644 androidApp/gradle/gradle-daemon-jvm.properties create mode 100644 androidApp/gradle/libs.versions.toml rename {app => androidApp}/proguard-rules.pro (100%) rename {app => androidApp}/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json (100%) rename {app => androidApp}/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json (100%) rename {app => androidApp}/src/androidTest/assets/scan-1.jpg (100%) rename {app => androidApp}/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt (100%) rename {app => androidApp}/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeTest.kt (100%) rename {app => androidApp}/src/androidTest/java/io/github/chrisimx/scanbridge/screenshot/ScanBridgeScreenshotTest.kt (100%) rename {app => androidApp}/src/debug/AndroidManifest.xml (100%) rename {app => androidApp}/src/fdroid/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt (100%) rename {app => androidApp}/src/main/AndroidManifest.xml (100%) rename {app => androidApp}/src/main/ic_launcher-playstore.png (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/AppSettingsScreen.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt (96%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt (97%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt (97%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/model/EditedCustomScanner.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacyESCLScanSettings.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/model/PaperFormat.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/model/ScanJob.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/ui/CustomScannerViewModel.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/datastore/DataStores.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/datastore/LastRouteStoreSerializer.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanBridgeSettingsSerializer.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanSettingsDataStoreHelpers.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/datastore/ShownMessagesSerializer.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/entities/Session.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/entities/TempFile.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/logs/FileLogger.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/services/DebugLogService.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/stores/LegacyCustomScannerStore.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/theme/Color.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/theme/Theme.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CrashFileHandler.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CroppableImage.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ExportSettingsPopup.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FoundScannerItem.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FullScreenError.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/SizeBasedConditionalView.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TemporaryFileHandlePrompt.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ConfirmCloseDialog.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CrashFileDialog.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CustomScannerDialog.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/DeleteDialog.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ErrorDialog.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/LoadingDialog.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/SimpleTextDialog.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/TemporaryFileHandlingDialog.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/CheckboxSetting.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/MoreInformationButton.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/UIntSetting.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/ESCLKtExtensions.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/ImageUtil.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/NavControllerExtensions.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/PdfUtil.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/ScanFileNameUtil.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/ScanSettingsJson.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/StateFlowExtensions.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/TempFileUtil.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/TrustAllTrustManager.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/UIUtils.kt (100%) rename {app => androidApp}/src/main/java/io/github/chrisimx/scanbridge/util/ZipArchiveUtil.kt (100%) rename {app => androidApp}/src/main/proto/app_settings.proto (100%) rename {app => androidApp}/src/main/proto/route_store.proto (100%) rename {app => androidApp}/src/main/proto/shown_messages.proto (100%) rename {app => androidApp}/src/main/res/drawable/baseline_image_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/baseline_picture_as_pdf_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/baseline_rotate_right_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/favorite_24px.xml (100%) rename {app => androidApp}/src/main/res/drawable/github_mark.xml (100%) rename {app => androidApp}/src/main/res/drawable/icon_about_dialog.png (100%) rename {app => androidApp}/src/main/res/drawable/outline_crop_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/outline_edit_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/outline_error_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/outline_file_save_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/outline_pan_zoom_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/outline_scan_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/round_print_36.xml (100%) rename {app => androidApp}/src/main/res/drawable/rounded_adf_scanner_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/rounded_content_copy_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/rounded_document_scanner_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/rounded_scanner_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/rounded_warning_24.xml (100%) rename {app => androidApp}/src/main/res/drawable/twotone_wifi_find_24.xml (100%) rename {app => androidApp}/src/main/res/font/poppins_black.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_blackitalic.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_bold.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_bolditalic.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_extrabold.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_extrabolditalic.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_extralight.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_extralightitalic.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_italic.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_light.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_lightitalic.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_medium.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_mediumitalic.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_regular.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_semibold.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_semibolditalic.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_thin.ttf (100%) rename {app => androidApp}/src/main/res/font/poppins_thinitalic.ttf (100%) rename {app => androidApp}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename {app => androidApp}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename {app => androidApp}/src/main/res/mipmap-hdpi/ic_launcher.webp (100%) rename {app => androidApp}/src/main/res/mipmap-hdpi/ic_launcher_background.webp (100%) rename {app => androidApp}/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp (100%) rename {app => androidApp}/src/main/res/mipmap-hdpi/ic_launcher_round.webp (100%) rename {app => androidApp}/src/main/res/mipmap-mdpi/ic_launcher.webp (100%) rename {app => androidApp}/src/main/res/mipmap-mdpi/ic_launcher_background.webp (100%) rename {app => androidApp}/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp (100%) rename {app => androidApp}/src/main/res/mipmap-mdpi/ic_launcher_round.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xhdpi/ic_launcher.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xhdpi/ic_launcher_background.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xhdpi/ic_launcher_round.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xxhdpi/ic_launcher.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xxxhdpi/ic_launcher.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp (100%) rename {app => androidApp}/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp (100%) rename {app => androidApp}/src/main/res/raw/test_scanner_capabilities (100%) rename {app => androidApp}/src/main/res/resources.properties (100%) rename {app => androidApp}/src/main/res/values-de/strings.xml (100%) rename {app => androidApp}/src/main/res/values-it/strings.xml (100%) rename {app => androidApp}/src/main/res/values/colors.xml (100%) rename {app => androidApp}/src/main/res/values/strings.xml (100%) rename {app => androidApp}/src/main/res/values/themes.xml (100%) rename {app => androidApp}/src/main/res/xml/backup_rules.xml (100%) rename {app => androidApp}/src/main/res/xml/data_extraction_rules.xml (100%) rename {app => androidApp}/src/main/res/xml/network_security_config.xml (100%) rename {app => androidApp}/src/main/res/xml/provider_paths.xml (100%) rename {app => androidApp}/src/play/AndroidManifest.xml (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/AccountSetupScreen.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/InternetConnectivityFlow.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/LicenseErrorStringMapping.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/OwnershipProofService.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/OwnershipTestScreen.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/PlainTextObfuscator.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/SignupScreen.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/SimpleStrictLicensePolicy.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/SpecialIcons.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/SuccessSigningUpScreen.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/SupportScreen.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerificationClient.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerifierApi.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/AccountCreationRequest.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/GoogleChallenge.kt (100%) rename {app => androidApp}/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/VIPCreationResult.kt (100%) rename {app => androidApp}/src/play/res/drawable/fireamp_icon.xml (100%) rename {app => androidApp}/src/play/res/drawable/outline_globe_24.xml (100%) rename {app => androidApp}/src/play/res/values-de/strings.xml (100%) rename {app => androidApp}/src/play/res/values-it/strings.xml (100%) rename {app => androidApp}/src/play/res/values/strings.xml (100%) rename {app => androidApp}/src/test/java/org/github/chrisimx/scanbridge/PaperFormatTest.kt (100%) rename {app => androidApp}/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt (100%) create mode 100644 desktopApp/appIcons/LinuxIcon.png create mode 100644 desktopApp/appIcons/MacosIcon.icns create mode 100644 desktopApp/appIcons/WindowsIcon.ico create mode 100644 desktopApp/build.gradle.kts create mode 100644 desktopApp/src/main/kotlin/main.kt create mode 100644 iosApp/iosApp.xcodeproj/project.pbxproj create mode 100644 iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/iosApp.xcscheme create mode 100644 iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png create mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 iosApp/iosApp/Assets.xcassets/Contents.json create mode 100644 iosApp/iosApp/Info.plist create mode 100644 iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 iosApp/iosApp/iosApp.swift create mode 100644 shared/.gitignore create mode 100644 shared/build.gradle.kts create mode 100644 shared/src/commonMain/composeResources/drawable/ic_cyclone.xml create mode 100644 shared/src/commonMain/composeResources/drawable/ic_dark_mode.xml create mode 100644 shared/src/commonMain/composeResources/drawable/ic_light_mode.xml create mode 100644 shared/src/commonMain/composeResources/drawable/ic_rotate_right.xml create mode 100644 shared/src/commonMain/composeResources/font/IndieFlower-Regular.ttf create mode 100644 shared/src/commonMain/composeResources/values/strings.xml create mode 100644 shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/App.kt create mode 100644 shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt create mode 100644 shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt create mode 100644 shared/src/iosMain/kotlin/main.kt diff --git a/README.MD.other b/README.MD.other new file mode 100644 index 0000000..afde789 --- /dev/null +++ b/README.MD.other @@ -0,0 +1,19 @@ +# ScanBridge + +### Android +To run the application on android device/emulator: + - open project in Android Studio and run imported android run configuration + +To build the application bundle: + - run `./gradlew :androidApp:assembleDebug` + - find `.apk` file in `androidApp/build/outputs/apk/debug/androidApp-debug.apk` + +### Desktop +Run the desktop application: `./gradlew :desktopApp:run` +Run the desktop **hot reload** application: `./gradlew :desktopApp:hotRun --auto` + +### iOS +To run the application on iPhone device/simulator: + - Open `iosApp/iosApp.xcproject` in Xcode and run standard configuration + - Or use [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) for Android Studio + diff --git a/README.md b/README.md index a01bd62..679da54 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

- Get it on F-Droid - Get it on Google Play - Discover scanners in your network - Scan multiple pages - Use your scanner to the maximum of its abilities + Discover scanners in your network + Scan multiple pages + Use your scanner to the maximum of its abilities ## Features @@ -104,7 +104,7 @@ If you want to chat with me or other users, you can join the Matrix room ## Contributions Contributions are welcome, and it would be amazing if you want to help. Refer to -the [Contribution Guidelines](CONTRIBUTING.md) for more information. +the [Contribution Guidelines](androidApp/CONTRIBUTING.md) for more information. ## License diff --git a/app/.gitignore b/androidApp/.gitignore similarity index 100% rename from app/.gitignore rename to androidApp/.gitignore diff --git a/CHANGELOG.md b/androidApp/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to androidApp/CHANGELOG.md diff --git a/CONTRIBUTING.md b/androidApp/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to androidApp/CONTRIBUTING.md diff --git a/COPYING b/androidApp/COPYING similarity index 100% rename from COPYING rename to androidApp/COPYING diff --git a/Gemfile b/androidApp/Gemfile similarity index 100% rename from Gemfile rename to androidApp/Gemfile diff --git a/Gemfile.lock b/androidApp/Gemfile.lock similarity index 100% rename from Gemfile.lock rename to androidApp/Gemfile.lock diff --git a/adb+.sh b/androidApp/adb+.sh similarity index 100% rename from adb+.sh rename to androidApp/adb+.sh diff --git a/assets/GetItOnGooglePlay_Badge_Web_color_English.svg b/androidApp/assets/GetItOnGooglePlay_Badge_Web_color_English.svg similarity index 100% rename from assets/GetItOnGooglePlay_Badge_Web_color_English.svg rename to androidApp/assets/GetItOnGooglePlay_Badge_Web_color_English.svg diff --git a/assets/get-it-on-fdroid.svg b/androidApp/assets/get-it-on-fdroid.svg similarity index 100% rename from assets/get-it-on-fdroid.svg rename to androidApp/assets/get-it-on-fdroid.svg diff --git a/assets/icon.svg b/androidApp/assets/icon.svg similarity index 100% rename from assets/icon.svg rename to androidApp/assets/icon.svg diff --git a/app/build.gradle.kts b/androidApp/build.gradle.kts similarity index 89% rename from app/build.gradle.kts rename to androidApp/build.gradle.kts index 01f50bc..32ce3b8 100644 --- a/app/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -18,26 +18,10 @@ plugins { id("app.cash.paraphrase") version "0.4.1" } -fun getGitCommitHash(): String { - return try { - val command = "git rev-parse --short HEAD" - val process = ProcessBuilder() - .command(command.split(" ")) - .directory(rootProject.projectDir) - .redirectError(ProcessBuilder.Redirect.INHERIT) - .start() - val wait = process.waitFor(60, TimeUnit.SECONDS) - if (!wait) { - return "unknown" - } - - val result = process.inputStream.bufferedReader().readText() - - result.trim() - } catch (_: Exception) { - "unknown" // Fallback - } -} +val gitHashProvider = providers.exec { + commandLine("git", "rev-parse", "--short", "HEAD") + isIgnoreExitValue = true +}.standardOutput.asText.map { it.trim() } tasks.withType().all { compilerOptions { @@ -76,10 +60,10 @@ android { getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) - buildConfigField("String", "GIT_COMMIT_HASH", "\"${getGitCommitHash()}\"") + buildConfigField("String", "GIT_COMMIT_HASH", "\"${gitHashProvider.get()}\"") } debug { - buildConfigField("String", "GIT_COMMIT_HASH", "\"${getGitCommitHash()}\"") + buildConfigField("String", "GIT_COMMIT_HASH", "\"${gitHashProvider.get()}\"") } } flavorDimensions += "edition" diff --git a/fastlane/Appfile b/androidApp/fastlane/Appfile similarity index 100% rename from fastlane/Appfile rename to androidApp/fastlane/Appfile diff --git a/fastlane/Fastfile b/androidApp/fastlane/Fastfile similarity index 100% rename from fastlane/Fastfile rename to androidApp/fastlane/Fastfile diff --git a/fastlane/README.md b/androidApp/fastlane/README.md similarity index 100% rename from fastlane/README.md rename to androidApp/fastlane/README.md diff --git a/fastlane/Screengrabfile b/androidApp/fastlane/Screengrabfile similarity index 100% rename from fastlane/Screengrabfile rename to androidApp/fastlane/Screengrabfile diff --git a/fastlane/metadata/android/de-DE/changelogs/1000000.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1000000.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1000000.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1000000.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/1000001.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1000001.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1000001.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1000001.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/1001000.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1001000.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1001000.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1001000.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/1002000.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1002000.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1002000.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1002000.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/1003000.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1003000.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1003000.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1003000.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/1004000.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1004000.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1004000.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1004000.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/1005000.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1005000.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1005000.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1005000.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/1006001.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1006001.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1006001.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1006001.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/1006002.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/1006002.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/1006002.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/1006002.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/2000000.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/2000000.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/2000000.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/2000000.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/2000001.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/2000001.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/2000001.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/2000001.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/2001002.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/2001002.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/2001002.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/2001002.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/2001003.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/2001003.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/2001003.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/2001003.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/2001004.txt b/androidApp/fastlane/metadata/android/de-DE/changelogs/2001004.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/2001004.txt rename to androidApp/fastlane/metadata/android/de-DE/changelogs/2001004.txt diff --git a/fastlane/metadata/android/de-DE/full_description.txt b/androidApp/fastlane/metadata/android/de-DE/full_description.txt similarity index 100% rename from fastlane/metadata/android/de-DE/full_description.txt rename to androidApp/fastlane/metadata/android/de-DE/full_description.txt diff --git a/fastlane/metadata/android/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391883115.png b/androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391883115.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391883115.png rename to androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391883115.png diff --git a/fastlane/metadata/android/de-DE/images/phoneScreenshots/02-scanSettings_1773391879801.png b/androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/02-scanSettings_1773391879801.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/phoneScreenshots/02-scanSettings_1773391879801.png rename to androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/02-scanSettings_1773391879801.png diff --git a/fastlane/metadata/android/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391880499.png b/androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391880499.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391880499.png rename to androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391880499.png diff --git a/fastlane/metadata/android/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391882198.png b/androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391882198.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391882198.png rename to androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391882198.png diff --git a/fastlane/metadata/android/de-DE/images/phoneScreenshots/05-settingsScreen_1773391884031.png b/androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/05-settingsScreen_1773391884031.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/phoneScreenshots/05-settingsScreen_1773391884031.png rename to androidApp/fastlane/metadata/android/de-DE/images/phoneScreenshots/05-settingsScreen_1773391884031.png diff --git a/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392085232.png b/androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392085232.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392085232.png rename to androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392085232.png diff --git a/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392081788.png b/androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392081788.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392081788.png rename to androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392081788.png diff --git a/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392082774.png b/androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392082774.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392082774.png rename to androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392082774.png diff --git a/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392084316.png b/androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392084316.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392084316.png rename to androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392084316.png diff --git a/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392086217.png b/androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392086217.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392086217.png rename to androidApp/fastlane/metadata/android/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392086217.png diff --git a/fastlane/metadata/android/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541896730.png b/androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541896730.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541896730.png rename to androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541896730.png diff --git a/fastlane/metadata/android/de-DE/images/tenInchScreenshots/02-scanSettings_1772541894045.png b/androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/02-scanSettings_1772541894045.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/tenInchScreenshots/02-scanSettings_1772541894045.png rename to androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/02-scanSettings_1772541894045.png diff --git a/fastlane/metadata/android/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541894498.png b/androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541894498.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541894498.png rename to androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541894498.png diff --git a/fastlane/metadata/android/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541895682.png b/androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541895682.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541895682.png rename to androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541895682.png diff --git a/fastlane/metadata/android/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541897397.png b/androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541897397.png similarity index 100% rename from fastlane/metadata/android/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541897397.png rename to androidApp/fastlane/metadata/android/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541897397.png diff --git a/fastlane/metadata/android/de-DE/short_description.txt b/androidApp/fastlane/metadata/android/de-DE/short_description.txt similarity index 100% rename from fastlane/metadata/android/de-DE/short_description.txt rename to androidApp/fastlane/metadata/android/de-DE/short_description.txt diff --git a/fastlane/metadata/android/de-DE/title.txt b/androidApp/fastlane/metadata/android/de-DE/title.txt similarity index 100% rename from fastlane/metadata/android/de-DE/title.txt rename to androidApp/fastlane/metadata/android/de-DE/title.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1000000.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1000000.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1000000.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1000000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1000001.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1000001.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1000001.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1000001.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1001000.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1001000.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1001000.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1001000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1002000.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1002000.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1002000.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1002000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1003000.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1003000.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1003000.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1003000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1004000.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1004000.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1004000.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1004000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1005000.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1005000.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1005000.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1005000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1006001.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1006001.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1006001.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1006001.txt diff --git a/fastlane/metadata/android/en-US/changelogs/1006002.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/1006002.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/1006002.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/1006002.txt diff --git a/fastlane/metadata/android/en-US/changelogs/2000000.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/2000000.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/2000000.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/2000000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/2000001.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/2000001.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/2000001.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/2000001.txt diff --git a/fastlane/metadata/android/en-US/changelogs/2001002.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/2001002.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/2001002.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/2001002.txt diff --git a/fastlane/metadata/android/en-US/changelogs/2001003.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/2001003.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/2001003.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/2001003.txt diff --git a/fastlane/metadata/android/en-US/changelogs/2001004.txt b/androidApp/fastlane/metadata/android/en-US/changelogs/2001004.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/2001004.txt rename to androidApp/fastlane/metadata/android/en-US/changelogs/2001004.txt diff --git a/fastlane/metadata/android/en-US/full_description.txt b/androidApp/fastlane/metadata/android/en-US/full_description.txt similarity index 100% rename from fastlane/metadata/android/en-US/full_description.txt rename to androidApp/fastlane/metadata/android/en-US/full_description.txt diff --git a/fastlane/metadata/android/en-US/images/icon.png b/androidApp/fastlane/metadata/android/en-US/images/icon.png similarity index 100% rename from fastlane/metadata/android/en-US/images/icon.png rename to androidApp/fastlane/metadata/android/en-US/images/icon.png diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391873581.png b/androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391873581.png similarity index 100% rename from fastlane/metadata/android/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391873581.png rename to androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391873581.png diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/02-scanSettings_1773391870896.png b/androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/02-scanSettings_1773391870896.png similarity index 100% rename from fastlane/metadata/android/en-US/images/phoneScreenshots/02-scanSettings_1773391870896.png rename to androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/02-scanSettings_1773391870896.png diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/03-discoveryScreen_1773391871298.png b/androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/03-discoveryScreen_1773391871298.png similarity index 100% rename from fastlane/metadata/android/en-US/images/phoneScreenshots/03-discoveryScreen_1773391871298.png rename to androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/03-discoveryScreen_1773391871298.png diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391872597.png b/androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391872597.png similarity index 100% rename from fastlane/metadata/android/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391872597.png rename to androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391872597.png diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/05-settingsScreen_1773391874196.png b/androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/05-settingsScreen_1773391874196.png similarity index 100% rename from fastlane/metadata/android/en-US/images/phoneScreenshots/05-settingsScreen_1773391874196.png rename to androidApp/fastlane/metadata/android/en-US/images/phoneScreenshots/05-settingsScreen_1773391874196.png diff --git a/fastlane/metadata/android/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392074370.png b/androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392074370.png similarity index 100% rename from fastlane/metadata/android/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392074370.png rename to androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392074370.png diff --git a/fastlane/metadata/android/en-US/images/sevenInchScreenshots/02-scanSettings_1773392071595.png b/androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/02-scanSettings_1773392071595.png similarity index 100% rename from fastlane/metadata/android/en-US/images/sevenInchScreenshots/02-scanSettings_1773392071595.png rename to androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/02-scanSettings_1773392071595.png diff --git a/fastlane/metadata/android/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392071982.png b/androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392071982.png similarity index 100% rename from fastlane/metadata/android/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392071982.png rename to androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392071982.png diff --git a/fastlane/metadata/android/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392073386.png b/androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392073386.png similarity index 100% rename from fastlane/metadata/android/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392073386.png rename to androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392073386.png diff --git a/fastlane/metadata/android/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392074964.png b/androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392074964.png similarity index 100% rename from fastlane/metadata/android/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392074964.png rename to androidApp/fastlane/metadata/android/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392074964.png diff --git a/fastlane/metadata/android/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541886403.png b/androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541886403.png similarity index 100% rename from fastlane/metadata/android/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541886403.png rename to androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541886403.png diff --git a/fastlane/metadata/android/en-US/images/tenInchScreenshots/02-scanSettings_1772541881705.png b/androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/02-scanSettings_1772541881705.png similarity index 100% rename from fastlane/metadata/android/en-US/images/tenInchScreenshots/02-scanSettings_1772541881705.png rename to androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/02-scanSettings_1772541881705.png diff --git a/fastlane/metadata/android/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541884121.png b/androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541884121.png similarity index 100% rename from fastlane/metadata/android/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541884121.png rename to androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541884121.png diff --git a/fastlane/metadata/android/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541885597.png b/androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541885597.png similarity index 100% rename from fastlane/metadata/android/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541885597.png rename to androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541885597.png diff --git a/fastlane/metadata/android/en-US/images/tenInchScreenshots/05-settingsScreen_1772541889078.png b/androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/05-settingsScreen_1772541889078.png similarity index 100% rename from fastlane/metadata/android/en-US/images/tenInchScreenshots/05-settingsScreen_1772541889078.png rename to androidApp/fastlane/metadata/android/en-US/images/tenInchScreenshots/05-settingsScreen_1772541889078.png diff --git a/fastlane/metadata/android/en-US/short_description.txt b/androidApp/fastlane/metadata/android/en-US/short_description.txt similarity index 100% rename from fastlane/metadata/android/en-US/short_description.txt rename to androidApp/fastlane/metadata/android/en-US/short_description.txt diff --git a/fastlane/metadata/android/en-US/title.txt b/androidApp/fastlane/metadata/android/en-US/title.txt similarity index 100% rename from fastlane/metadata/android/en-US/title.txt rename to androidApp/fastlane/metadata/android/en-US/title.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1000000.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1000000.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1000000.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1000000.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1000001.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1000001.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1000001.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1000001.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1001000.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1001000.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1001000.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1001000.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1002000.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1002000.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1002000.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1002000.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1003000.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1003000.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1003000.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1003000.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1004000.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1004000.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1004000.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1004000.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1005000.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1005000.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1005000.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1005000.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1006001.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1006001.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1006001.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1006001.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/1006002.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/1006002.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/1006002.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/1006002.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/2000000.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/2000000.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/2000000.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/2000000.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/2000001.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/2000001.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/2000001.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/2000001.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/2001002.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/2001002.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/2001002.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/2001002.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/2001003.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/2001003.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/2001003.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/2001003.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/2001004.txt b/androidApp/fastlane/metadata/android/it-IT/changelogs/2001004.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/2001004.txt rename to androidApp/fastlane/metadata/android/it-IT/changelogs/2001004.txt diff --git a/fastlane/metadata/android/it-IT/full_description.txt b/androidApp/fastlane/metadata/android/it-IT/full_description.txt similarity index 100% rename from fastlane/metadata/android/it-IT/full_description.txt rename to androidApp/fastlane/metadata/android/it-IT/full_description.txt diff --git a/fastlane/metadata/android/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391892623.png b/androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391892623.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391892623.png rename to androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391892623.png diff --git a/fastlane/metadata/android/it-IT/images/phoneScreenshots/02-scanSettings_1773391889434.png b/androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/02-scanSettings_1773391889434.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/phoneScreenshots/02-scanSettings_1773391889434.png rename to androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/02-scanSettings_1773391889434.png diff --git a/fastlane/metadata/android/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391890147.png b/androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391890147.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391890147.png rename to androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391890147.png diff --git a/fastlane/metadata/android/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391891679.png b/androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391891679.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391891679.png rename to androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391891679.png diff --git a/fastlane/metadata/android/it-IT/images/phoneScreenshots/05-settingsScreen_1773391893582.png b/androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/05-settingsScreen_1773391893582.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/phoneScreenshots/05-settingsScreen_1773391893582.png rename to androidApp/fastlane/metadata/android/it-IT/images/phoneScreenshots/05-settingsScreen_1773391893582.png diff --git a/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392097014.png b/androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392097014.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392097014.png rename to androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392097014.png diff --git a/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392093573.png b/androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392093573.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392093573.png rename to androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392093573.png diff --git a/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392094636.png b/androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392094636.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392094636.png rename to androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392094636.png diff --git a/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392096232.png b/androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392096232.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392096232.png rename to androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392096232.png diff --git a/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392098119.png b/androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392098119.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392098119.png rename to androidApp/fastlane/metadata/android/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392098119.png diff --git a/fastlane/metadata/android/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541911340.png b/androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541911340.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541911340.png rename to androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541911340.png diff --git a/fastlane/metadata/android/it-IT/images/tenInchScreenshots/02-scanSettings_1772541904718.png b/androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/02-scanSettings_1772541904718.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/tenInchScreenshots/02-scanSettings_1772541904718.png rename to androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/02-scanSettings_1772541904718.png diff --git a/fastlane/metadata/android/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541907169.png b/androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541907169.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541907169.png rename to androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541907169.png diff --git a/fastlane/metadata/android/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541910309.png b/androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541910309.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541910309.png rename to androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541910309.png diff --git a/fastlane/metadata/android/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541914017.png b/androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541914017.png similarity index 100% rename from fastlane/metadata/android/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541914017.png rename to androidApp/fastlane/metadata/android/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541914017.png diff --git a/fastlane/metadata/android/it-IT/short_description.txt b/androidApp/fastlane/metadata/android/it-IT/short_description.txt similarity index 100% rename from fastlane/metadata/android/it-IT/short_description.txt rename to androidApp/fastlane/metadata/android/it-IT/short_description.txt diff --git a/fastlane/metadata/android/it-IT/title.txt b/androidApp/fastlane/metadata/android/it-IT/title.txt similarity index 100% rename from fastlane/metadata/android/it-IT/title.txt rename to androidApp/fastlane/metadata/android/it-IT/title.txt diff --git a/fastlane/metadata/android/screenshots.html b/androidApp/fastlane/metadata/android/screenshots.html similarity index 100% rename from fastlane/metadata/android/screenshots.html rename to androidApp/fastlane/metadata/android/screenshots.html diff --git a/fastlane/playMetadata/de-DE/changelogs/1006002.txt b/androidApp/fastlane/playMetadata/de-DE/changelogs/1006002.txt similarity index 100% rename from fastlane/playMetadata/de-DE/changelogs/1006002.txt rename to androidApp/fastlane/playMetadata/de-DE/changelogs/1006002.txt diff --git a/fastlane/playMetadata/de-DE/changelogs/2000000.txt b/androidApp/fastlane/playMetadata/de-DE/changelogs/2000000.txt similarity index 100% rename from fastlane/playMetadata/de-DE/changelogs/2000000.txt rename to androidApp/fastlane/playMetadata/de-DE/changelogs/2000000.txt diff --git a/fastlane/playMetadata/de-DE/changelogs/2000001.txt b/androidApp/fastlane/playMetadata/de-DE/changelogs/2000001.txt similarity index 100% rename from fastlane/playMetadata/de-DE/changelogs/2000001.txt rename to androidApp/fastlane/playMetadata/de-DE/changelogs/2000001.txt diff --git a/fastlane/playMetadata/de-DE/changelogs/2001002.txt b/androidApp/fastlane/playMetadata/de-DE/changelogs/2001002.txt similarity index 100% rename from fastlane/playMetadata/de-DE/changelogs/2001002.txt rename to androidApp/fastlane/playMetadata/de-DE/changelogs/2001002.txt diff --git a/fastlane/playMetadata/de-DE/changelogs/2001003.txt b/androidApp/fastlane/playMetadata/de-DE/changelogs/2001003.txt similarity index 100% rename from fastlane/playMetadata/de-DE/changelogs/2001003.txt rename to androidApp/fastlane/playMetadata/de-DE/changelogs/2001003.txt diff --git a/fastlane/playMetadata/de-DE/changelogs/2001004.txt b/androidApp/fastlane/playMetadata/de-DE/changelogs/2001004.txt similarity index 100% rename from fastlane/playMetadata/de-DE/changelogs/2001004.txt rename to androidApp/fastlane/playMetadata/de-DE/changelogs/2001004.txt diff --git a/fastlane/playMetadata/de-DE/full_description.txt b/androidApp/fastlane/playMetadata/de-DE/full_description.txt similarity index 100% rename from fastlane/playMetadata/de-DE/full_description.txt rename to androidApp/fastlane/playMetadata/de-DE/full_description.txt diff --git a/fastlane/playMetadata/de-DE/images/chromeScreenshots/01-scannedPageScreen_1773392137705.png b/androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/01-scannedPageScreen_1773392137705.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/chromeScreenshots/01-scannedPageScreen_1773392137705.png rename to androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/01-scannedPageScreen_1773392137705.png diff --git a/fastlane/playMetadata/de-DE/images/chromeScreenshots/02-scanSettings_1773392134051.png b/androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/02-scanSettings_1773392134051.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/chromeScreenshots/02-scanSettings_1773392134051.png rename to androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/02-scanSettings_1773392134051.png diff --git a/fastlane/playMetadata/de-DE/images/chromeScreenshots/03-discoveryScreen_1773392134837.png b/androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/03-discoveryScreen_1773392134837.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/chromeScreenshots/03-discoveryScreen_1773392134837.png rename to androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/03-discoveryScreen_1773392134837.png diff --git a/fastlane/playMetadata/de-DE/images/chromeScreenshots/04-emptyScanScreen_1773392136515.png b/androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/04-emptyScanScreen_1773392136515.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/chromeScreenshots/04-emptyScanScreen_1773392136515.png rename to androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/04-emptyScanScreen_1773392136515.png diff --git a/fastlane/playMetadata/de-DE/images/chromeScreenshots/05-settingsScreen_1773392138645.png b/androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/05-settingsScreen_1773392138645.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/chromeScreenshots/05-settingsScreen_1773392138645.png rename to androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/05-settingsScreen_1773392138645.png diff --git a/fastlane/playMetadata/de-DE/images/chromeScreenshots/06-supportScreen_1773392131057.png b/androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/06-supportScreen_1773392131057.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/chromeScreenshots/06-supportScreen_1773392131057.png rename to androidApp/fastlane/playMetadata/de-DE/images/chromeScreenshots/06-supportScreen_1773392131057.png diff --git a/fastlane/playMetadata/de-DE/images/featureGraphic.png b/androidApp/fastlane/playMetadata/de-DE/images/featureGraphic.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/featureGraphic.png rename to androidApp/fastlane/playMetadata/de-DE/images/featureGraphic.png diff --git a/fastlane/playMetadata/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391854599.png b/androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391854599.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391854599.png rename to androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/01-scannedPageScreen_1773391854599.png diff --git a/fastlane/playMetadata/de-DE/images/phoneScreenshots/02-scanSettings_1773391851373.png b/androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/02-scanSettings_1773391851373.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/phoneScreenshots/02-scanSettings_1773391851373.png rename to androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/02-scanSettings_1773391851373.png diff --git a/fastlane/playMetadata/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391852033.png b/androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391852033.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391852033.png rename to androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/03-discoveryScreen_1773391852033.png diff --git a/fastlane/playMetadata/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391853682.png b/androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391853682.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391853682.png rename to androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/04-emptyScanScreen_1773391853682.png diff --git a/fastlane/playMetadata/de-DE/images/phoneScreenshots/05-settingsScreen_1773391855601.png b/androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/05-settingsScreen_1773391855601.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/phoneScreenshots/05-settingsScreen_1773391855601.png rename to androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/05-settingsScreen_1773391855601.png diff --git a/fastlane/playMetadata/de-DE/images/phoneScreenshots/06-supportScreen_1773391848067.png b/androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/06-supportScreen_1773391848067.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/phoneScreenshots/06-supportScreen_1773391848067.png rename to androidApp/fastlane/playMetadata/de-DE/images/phoneScreenshots/06-supportScreen_1773391848067.png diff --git a/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392051915.png b/androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392051915.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392051915.png rename to androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/01-scannedPageScreen_1773392051915.png diff --git a/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392048636.png b/androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392048636.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392048636.png rename to androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/02-scanSettings_1773392048636.png diff --git a/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392049419.png b/androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392049419.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392049419.png rename to androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/03-discoveryScreen_1773392049419.png diff --git a/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392051098.png b/androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392051098.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392051098.png rename to androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/04-emptyScanScreen_1773392051098.png diff --git a/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392052967.png b/androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392052967.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392052967.png rename to androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/05-settingsScreen_1773392052967.png diff --git a/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/06-supportScreen_1773392044965.png b/androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/06-supportScreen_1773392044965.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/sevenInchScreenshots/06-supportScreen_1773392044965.png rename to androidApp/fastlane/playMetadata/de-DE/images/sevenInchScreenshots/06-supportScreen_1773392044965.png diff --git a/fastlane/playMetadata/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541856637.png b/androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541856637.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541856637.png rename to androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/01-scannedPageScreen_1772541856637.png diff --git a/fastlane/playMetadata/de-DE/images/tenInchScreenshots/02-scanSettings_1772541853898.png b/androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/02-scanSettings_1772541853898.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/tenInchScreenshots/02-scanSettings_1772541853898.png rename to androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/02-scanSettings_1772541853898.png diff --git a/fastlane/playMetadata/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541854300.png b/androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541854300.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541854300.png rename to androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/03-discoveryScreen_1772541854300.png diff --git a/fastlane/playMetadata/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541855615.png b/androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541855615.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541855615.png rename to androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/04-emptyScanScreen_1772541855615.png diff --git a/fastlane/playMetadata/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541857282.png b/androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541857282.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541857282.png rename to androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/05-settingsScreen_1772541857282.png diff --git a/fastlane/playMetadata/de-DE/images/tenInchScreenshots/06-supportScreen_1772541851562.png b/androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/06-supportScreen_1772541851562.png similarity index 100% rename from fastlane/playMetadata/de-DE/images/tenInchScreenshots/06-supportScreen_1772541851562.png rename to androidApp/fastlane/playMetadata/de-DE/images/tenInchScreenshots/06-supportScreen_1772541851562.png diff --git a/fastlane/playMetadata/de-DE/short_description.txt b/androidApp/fastlane/playMetadata/de-DE/short_description.txt similarity index 100% rename from fastlane/playMetadata/de-DE/short_description.txt rename to androidApp/fastlane/playMetadata/de-DE/short_description.txt diff --git a/fastlane/playMetadata/de-DE/title.txt b/androidApp/fastlane/playMetadata/de-DE/title.txt similarity index 100% rename from fastlane/playMetadata/de-DE/title.txt rename to androidApp/fastlane/playMetadata/de-DE/title.txt diff --git a/fastlane/playMetadata/de-DE/video.txt b/androidApp/fastlane/playMetadata/de-DE/video.txt similarity index 100% rename from fastlane/playMetadata/de-DE/video.txt rename to androidApp/fastlane/playMetadata/de-DE/video.txt diff --git a/fastlane/playMetadata/en-US/changelogs/1006002.txt b/androidApp/fastlane/playMetadata/en-US/changelogs/1006002.txt similarity index 100% rename from fastlane/playMetadata/en-US/changelogs/1006002.txt rename to androidApp/fastlane/playMetadata/en-US/changelogs/1006002.txt diff --git a/fastlane/playMetadata/en-US/changelogs/2000000.txt b/androidApp/fastlane/playMetadata/en-US/changelogs/2000000.txt similarity index 100% rename from fastlane/playMetadata/en-US/changelogs/2000000.txt rename to androidApp/fastlane/playMetadata/en-US/changelogs/2000000.txt diff --git a/fastlane/playMetadata/en-US/changelogs/2000001.txt b/androidApp/fastlane/playMetadata/en-US/changelogs/2000001.txt similarity index 100% rename from fastlane/playMetadata/en-US/changelogs/2000001.txt rename to androidApp/fastlane/playMetadata/en-US/changelogs/2000001.txt diff --git a/fastlane/playMetadata/en-US/changelogs/2001002.txt b/androidApp/fastlane/playMetadata/en-US/changelogs/2001002.txt similarity index 100% rename from fastlane/playMetadata/en-US/changelogs/2001002.txt rename to androidApp/fastlane/playMetadata/en-US/changelogs/2001002.txt diff --git a/fastlane/playMetadata/en-US/changelogs/2001003.txt b/androidApp/fastlane/playMetadata/en-US/changelogs/2001003.txt similarity index 100% rename from fastlane/playMetadata/en-US/changelogs/2001003.txt rename to androidApp/fastlane/playMetadata/en-US/changelogs/2001003.txt diff --git a/fastlane/playMetadata/en-US/changelogs/2001004.txt b/androidApp/fastlane/playMetadata/en-US/changelogs/2001004.txt similarity index 100% rename from fastlane/playMetadata/en-US/changelogs/2001004.txt rename to androidApp/fastlane/playMetadata/en-US/changelogs/2001004.txt diff --git a/fastlane/playMetadata/en-US/full_description.txt b/androidApp/fastlane/playMetadata/en-US/full_description.txt similarity index 100% rename from fastlane/playMetadata/en-US/full_description.txt rename to androidApp/fastlane/playMetadata/en-US/full_description.txt diff --git a/fastlane/playMetadata/en-US/images/chromeScreenshots/01-scannedPageScreen_1773392127266.png b/androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/01-scannedPageScreen_1773392127266.png similarity index 100% rename from fastlane/playMetadata/en-US/images/chromeScreenshots/01-scannedPageScreen_1773392127266.png rename to androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/01-scannedPageScreen_1773392127266.png diff --git a/fastlane/playMetadata/en-US/images/chromeScreenshots/02-scanSettings_1773392124079.png b/androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/02-scanSettings_1773392124079.png similarity index 100% rename from fastlane/playMetadata/en-US/images/chromeScreenshots/02-scanSettings_1773392124079.png rename to androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/02-scanSettings_1773392124079.png diff --git a/fastlane/playMetadata/en-US/images/chromeScreenshots/03-discoveryScreen_1773392124691.png b/androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/03-discoveryScreen_1773392124691.png similarity index 100% rename from fastlane/playMetadata/en-US/images/chromeScreenshots/03-discoveryScreen_1773392124691.png rename to androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/03-discoveryScreen_1773392124691.png diff --git a/fastlane/playMetadata/en-US/images/chromeScreenshots/04-emptyScanScreen_1773392126076.png b/androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/04-emptyScanScreen_1773392126076.png similarity index 100% rename from fastlane/playMetadata/en-US/images/chromeScreenshots/04-emptyScanScreen_1773392126076.png rename to androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/04-emptyScanScreen_1773392126076.png diff --git a/fastlane/playMetadata/en-US/images/chromeScreenshots/05-settingsScreen_1773392128027.png b/androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/05-settingsScreen_1773392128027.png similarity index 100% rename from fastlane/playMetadata/en-US/images/chromeScreenshots/05-settingsScreen_1773392128027.png rename to androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/05-settingsScreen_1773392128027.png diff --git a/fastlane/playMetadata/en-US/images/chromeScreenshots/06-supportScreen_1773392121020.png b/androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/06-supportScreen_1773392121020.png similarity index 100% rename from fastlane/playMetadata/en-US/images/chromeScreenshots/06-supportScreen_1773392121020.png rename to androidApp/fastlane/playMetadata/en-US/images/chromeScreenshots/06-supportScreen_1773392121020.png diff --git a/fastlane/playMetadata/en-US/images/featureGraphic.png b/androidApp/fastlane/playMetadata/en-US/images/featureGraphic.png similarity index 100% rename from fastlane/playMetadata/en-US/images/featureGraphic.png rename to androidApp/fastlane/playMetadata/en-US/images/featureGraphic.png diff --git a/fastlane/playMetadata/en-US/images/icon.png b/androidApp/fastlane/playMetadata/en-US/images/icon.png similarity index 100% rename from fastlane/playMetadata/en-US/images/icon.png rename to androidApp/fastlane/playMetadata/en-US/images/icon.png diff --git a/fastlane/playMetadata/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391844501.png b/androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391844501.png similarity index 100% rename from fastlane/playMetadata/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391844501.png rename to androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/01-scannedPageScreen_1773391844501.png diff --git a/fastlane/playMetadata/en-US/images/phoneScreenshots/02-scanSettings_1773391841799.png b/androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/02-scanSettings_1773391841799.png similarity index 100% rename from fastlane/playMetadata/en-US/images/phoneScreenshots/02-scanSettings_1773391841799.png rename to androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/02-scanSettings_1773391841799.png diff --git a/fastlane/playMetadata/en-US/images/phoneScreenshots/03-discoveryScreen_1773391842230.png b/androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/03-discoveryScreen_1773391842230.png similarity index 100% rename from fastlane/playMetadata/en-US/images/phoneScreenshots/03-discoveryScreen_1773391842230.png rename to androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/03-discoveryScreen_1773391842230.png diff --git a/fastlane/playMetadata/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391843467.png b/androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391843467.png similarity index 100% rename from fastlane/playMetadata/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391843467.png rename to androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/04-emptyScanScreen_1773391843467.png diff --git a/fastlane/playMetadata/en-US/images/phoneScreenshots/05-settingsScreen_1773391845183.png b/androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/05-settingsScreen_1773391845183.png similarity index 100% rename from fastlane/playMetadata/en-US/images/phoneScreenshots/05-settingsScreen_1773391845183.png rename to androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/05-settingsScreen_1773391845183.png diff --git a/fastlane/playMetadata/en-US/images/phoneScreenshots/06-supportScreen_1773391839216.png b/androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/06-supportScreen_1773391839216.png similarity index 100% rename from fastlane/playMetadata/en-US/images/phoneScreenshots/06-supportScreen_1773391839216.png rename to androidApp/fastlane/playMetadata/en-US/images/phoneScreenshots/06-supportScreen_1773391839216.png diff --git a/fastlane/playMetadata/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392041217.png b/androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392041217.png similarity index 100% rename from fastlane/playMetadata/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392041217.png rename to androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/01-scannedPageScreen_1773392041217.png diff --git a/fastlane/playMetadata/en-US/images/sevenInchScreenshots/02-scanSettings_1773392038538.png b/androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/02-scanSettings_1773392038538.png similarity index 100% rename from fastlane/playMetadata/en-US/images/sevenInchScreenshots/02-scanSettings_1773392038538.png rename to androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/02-scanSettings_1773392038538.png diff --git a/fastlane/playMetadata/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392039016.png b/androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392039016.png similarity index 100% rename from fastlane/playMetadata/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392039016.png rename to androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/03-discoveryScreen_1773392039016.png diff --git a/fastlane/playMetadata/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392040264.png b/androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392040264.png similarity index 100% rename from fastlane/playMetadata/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392040264.png rename to androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/04-emptyScanScreen_1773392040264.png diff --git a/fastlane/playMetadata/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392041800.png b/androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392041800.png similarity index 100% rename from fastlane/playMetadata/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392041800.png rename to androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/05-settingsScreen_1773392041800.png diff --git a/fastlane/playMetadata/en-US/images/sevenInchScreenshots/06-supportScreen_1773392036000.png b/androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/06-supportScreen_1773392036000.png similarity index 100% rename from fastlane/playMetadata/en-US/images/sevenInchScreenshots/06-supportScreen_1773392036000.png rename to androidApp/fastlane/playMetadata/en-US/images/sevenInchScreenshots/06-supportScreen_1773392036000.png diff --git a/fastlane/playMetadata/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541846501.png b/androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541846501.png similarity index 100% rename from fastlane/playMetadata/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541846501.png rename to androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/01-scannedPageScreen_1772541846501.png diff --git a/fastlane/playMetadata/en-US/images/tenInchScreenshots/02-scanSettings_1772541839135.png b/androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/02-scanSettings_1772541839135.png similarity index 100% rename from fastlane/playMetadata/en-US/images/tenInchScreenshots/02-scanSettings_1772541839135.png rename to androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/02-scanSettings_1772541839135.png diff --git a/fastlane/playMetadata/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541841584.png b/androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541841584.png similarity index 100% rename from fastlane/playMetadata/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541841584.png rename to androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/03-discoveryScreen_1772541841584.png diff --git a/fastlane/playMetadata/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541845528.png b/androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541845528.png similarity index 100% rename from fastlane/playMetadata/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541845528.png rename to androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/04-emptyScanScreen_1772541845528.png diff --git a/fastlane/playMetadata/en-US/images/tenInchScreenshots/05-settingsScreen_1772541849182.png b/androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/05-settingsScreen_1772541849182.png similarity index 100% rename from fastlane/playMetadata/en-US/images/tenInchScreenshots/05-settingsScreen_1772541849182.png rename to androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/05-settingsScreen_1772541849182.png diff --git a/fastlane/playMetadata/en-US/images/tenInchScreenshots/06-supportScreen_1772541835912.png b/androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/06-supportScreen_1772541835912.png similarity index 100% rename from fastlane/playMetadata/en-US/images/tenInchScreenshots/06-supportScreen_1772541835912.png rename to androidApp/fastlane/playMetadata/en-US/images/tenInchScreenshots/06-supportScreen_1772541835912.png diff --git a/fastlane/playMetadata/en-US/short_description.txt b/androidApp/fastlane/playMetadata/en-US/short_description.txt similarity index 100% rename from fastlane/playMetadata/en-US/short_description.txt rename to androidApp/fastlane/playMetadata/en-US/short_description.txt diff --git a/fastlane/playMetadata/en-US/title.txt b/androidApp/fastlane/playMetadata/en-US/title.txt similarity index 100% rename from fastlane/playMetadata/en-US/title.txt rename to androidApp/fastlane/playMetadata/en-US/title.txt diff --git a/fastlane/playMetadata/en-US/video.txt b/androidApp/fastlane/playMetadata/en-US/video.txt similarity index 100% rename from fastlane/playMetadata/en-US/video.txt rename to androidApp/fastlane/playMetadata/en-US/video.txt diff --git a/fastlane/playMetadata/it-IT/changelogs/1006002.txt b/androidApp/fastlane/playMetadata/it-IT/changelogs/1006002.txt similarity index 100% rename from fastlane/playMetadata/it-IT/changelogs/1006002.txt rename to androidApp/fastlane/playMetadata/it-IT/changelogs/1006002.txt diff --git a/fastlane/playMetadata/it-IT/changelogs/2000000.txt b/androidApp/fastlane/playMetadata/it-IT/changelogs/2000000.txt similarity index 100% rename from fastlane/playMetadata/it-IT/changelogs/2000000.txt rename to androidApp/fastlane/playMetadata/it-IT/changelogs/2000000.txt diff --git a/fastlane/playMetadata/it-IT/changelogs/2000001.txt b/androidApp/fastlane/playMetadata/it-IT/changelogs/2000001.txt similarity index 100% rename from fastlane/playMetadata/it-IT/changelogs/2000001.txt rename to androidApp/fastlane/playMetadata/it-IT/changelogs/2000001.txt diff --git a/fastlane/playMetadata/it-IT/changelogs/2001002.txt b/androidApp/fastlane/playMetadata/it-IT/changelogs/2001002.txt similarity index 100% rename from fastlane/playMetadata/it-IT/changelogs/2001002.txt rename to androidApp/fastlane/playMetadata/it-IT/changelogs/2001002.txt diff --git a/fastlane/playMetadata/it-IT/changelogs/2001003.txt b/androidApp/fastlane/playMetadata/it-IT/changelogs/2001003.txt similarity index 100% rename from fastlane/playMetadata/it-IT/changelogs/2001003.txt rename to androidApp/fastlane/playMetadata/it-IT/changelogs/2001003.txt diff --git a/fastlane/playMetadata/it-IT/changelogs/2001004.txt b/androidApp/fastlane/playMetadata/it-IT/changelogs/2001004.txt similarity index 100% rename from fastlane/playMetadata/it-IT/changelogs/2001004.txt rename to androidApp/fastlane/playMetadata/it-IT/changelogs/2001004.txt diff --git a/fastlane/playMetadata/it-IT/full_description.txt b/androidApp/fastlane/playMetadata/it-IT/full_description.txt similarity index 100% rename from fastlane/playMetadata/it-IT/full_description.txt rename to androidApp/fastlane/playMetadata/it-IT/full_description.txt diff --git a/fastlane/playMetadata/it-IT/images/chromeScreenshots/01-scannedPageScreen_1773392147446.png b/androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/01-scannedPageScreen_1773392147446.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/chromeScreenshots/01-scannedPageScreen_1773392147446.png rename to androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/01-scannedPageScreen_1773392147446.png diff --git a/fastlane/playMetadata/it-IT/images/chromeScreenshots/02-scanSettings_1773392144173.png b/androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/02-scanSettings_1773392144173.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/chromeScreenshots/02-scanSettings_1773392144173.png rename to androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/02-scanSettings_1773392144173.png diff --git a/fastlane/playMetadata/it-IT/images/chromeScreenshots/03-discoveryScreen_1773392144879.png b/androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/03-discoveryScreen_1773392144879.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/chromeScreenshots/03-discoveryScreen_1773392144879.png rename to androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/03-discoveryScreen_1773392144879.png diff --git a/fastlane/playMetadata/it-IT/images/chromeScreenshots/04-emptyScanScreen_1773392146388.png b/androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/04-emptyScanScreen_1773392146388.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/chromeScreenshots/04-emptyScanScreen_1773392146388.png rename to androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/04-emptyScanScreen_1773392146388.png diff --git a/fastlane/playMetadata/it-IT/images/chromeScreenshots/05-settingsScreen_1773392148380.png b/androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/05-settingsScreen_1773392148380.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/chromeScreenshots/05-settingsScreen_1773392148380.png rename to androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/05-settingsScreen_1773392148380.png diff --git a/fastlane/playMetadata/it-IT/images/chromeScreenshots/06-supportScreen_1773392140988.png b/androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/06-supportScreen_1773392140988.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/chromeScreenshots/06-supportScreen_1773392140988.png rename to androidApp/fastlane/playMetadata/it-IT/images/chromeScreenshots/06-supportScreen_1773392140988.png diff --git a/fastlane/playMetadata/it-IT/images/featureGraphic.png b/androidApp/fastlane/playMetadata/it-IT/images/featureGraphic.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/featureGraphic.png rename to androidApp/fastlane/playMetadata/it-IT/images/featureGraphic.png diff --git a/fastlane/playMetadata/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391864832.png b/androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391864832.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391864832.png rename to androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/01-scannedPageScreen_1773391864832.png diff --git a/fastlane/playMetadata/it-IT/images/phoneScreenshots/02-scanSettings_1773391861554.png b/androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/02-scanSettings_1773391861554.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/phoneScreenshots/02-scanSettings_1773391861554.png rename to androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/02-scanSettings_1773391861554.png diff --git a/fastlane/playMetadata/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391862266.png b/androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391862266.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391862266.png rename to androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/03-discoveryScreen_1773391862266.png diff --git a/fastlane/playMetadata/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391863833.png b/androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391863833.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391863833.png rename to androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/04-emptyScanScreen_1773391863833.png diff --git a/fastlane/playMetadata/it-IT/images/phoneScreenshots/05-settingsScreen_1773391865784.png b/androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/05-settingsScreen_1773391865784.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/phoneScreenshots/05-settingsScreen_1773391865784.png rename to androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/05-settingsScreen_1773391865784.png diff --git a/fastlane/playMetadata/it-IT/images/phoneScreenshots/06-supportScreen_1773391858142.png b/androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/06-supportScreen_1773391858142.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/phoneScreenshots/06-supportScreen_1773391858142.png rename to androidApp/fastlane/playMetadata/it-IT/images/phoneScreenshots/06-supportScreen_1773391858142.png diff --git a/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392064698.png b/androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392064698.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392064698.png rename to androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/01-scannedPageScreen_1773392064698.png diff --git a/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392060668.png b/androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392060668.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392060668.png rename to androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/02-scanSettings_1773392060668.png diff --git a/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392062139.png b/androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392062139.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392062139.png rename to androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/03-discoveryScreen_1773392062139.png diff --git a/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392063851.png b/androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392063851.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392063851.png rename to androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/04-emptyScanScreen_1773392063851.png diff --git a/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392065789.png b/androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392065789.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392065789.png rename to androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/05-settingsScreen_1773392065789.png diff --git a/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/06-supportScreen_1773392056702.png b/androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/06-supportScreen_1773392056702.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/sevenInchScreenshots/06-supportScreen_1773392056702.png rename to androidApp/fastlane/playMetadata/it-IT/images/sevenInchScreenshots/06-supportScreen_1773392056702.png diff --git a/fastlane/playMetadata/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541871263.png b/androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541871263.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541871263.png rename to androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/01-scannedPageScreen_1772541871263.png diff --git a/fastlane/playMetadata/it-IT/images/tenInchScreenshots/02-scanSettings_1772541864073.png b/androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/02-scanSettings_1772541864073.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/tenInchScreenshots/02-scanSettings_1772541864073.png rename to androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/02-scanSettings_1772541864073.png diff --git a/fastlane/playMetadata/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541866487.png b/androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541866487.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541866487.png rename to androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/03-discoveryScreen_1772541866487.png diff --git a/fastlane/playMetadata/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541870383.png b/androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541870383.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541870383.png rename to androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/04-emptyScanScreen_1772541870383.png diff --git a/fastlane/playMetadata/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541873928.png b/androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541873928.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541873928.png rename to androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/05-settingsScreen_1772541873928.png diff --git a/fastlane/playMetadata/it-IT/images/tenInchScreenshots/06-supportScreen_1772541861315.png b/androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/06-supportScreen_1772541861315.png similarity index 100% rename from fastlane/playMetadata/it-IT/images/tenInchScreenshots/06-supportScreen_1772541861315.png rename to androidApp/fastlane/playMetadata/it-IT/images/tenInchScreenshots/06-supportScreen_1772541861315.png diff --git a/fastlane/playMetadata/it-IT/short_description.txt b/androidApp/fastlane/playMetadata/it-IT/short_description.txt similarity index 100% rename from fastlane/playMetadata/it-IT/short_description.txt rename to androidApp/fastlane/playMetadata/it-IT/short_description.txt diff --git a/fastlane/playMetadata/it-IT/title.txt b/androidApp/fastlane/playMetadata/it-IT/title.txt similarity index 100% rename from fastlane/playMetadata/it-IT/title.txt rename to androidApp/fastlane/playMetadata/it-IT/title.txt diff --git a/fastlane/playMetadata/it-IT/video.txt b/androidApp/fastlane/playMetadata/it-IT/video.txt similarity index 100% rename from fastlane/playMetadata/it-IT/video.txt rename to androidApp/fastlane/playMetadata/it-IT/video.txt diff --git a/fastlane/playMetadata/screenshots.html b/androidApp/fastlane/playMetadata/screenshots.html similarity index 100% rename from fastlane/playMetadata/screenshots.html rename to androidApp/fastlane/playMetadata/screenshots.html diff --git a/androidApp/gradle/gradle-daemon-jvm.properties b/androidApp/gradle/gradle-daemon-jvm.properties new file mode 100644 index 0000000..c4e7acb --- /dev/null +++ b/androidApp/gradle/gradle-daemon-jvm.properties @@ -0,0 +1,13 @@ +#This file is generated by updateDaemonJvm +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/67a0fee3c4236b6397dcbe8575ca2011/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/536afcd1dff540251f85e5d2c80458cf/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/67a0fee3c4236b6397dcbe8575ca2011/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/0b98aec810298c2c1d7fdac5dac37910/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/658299a896470fbb3103ba3a430ee227/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/67a0fee3c4236b6397dcbe8575ca2011/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/248ffb1098f61659502d0c09aa348294/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/ac151d55def6b6a9a159dc4cb4642851/redirect +toolchainVendor=JETBRAINS +toolchainVersion=21 diff --git a/androidApp/gradle/libs.versions.toml b/androidApp/gradle/libs.versions.toml new file mode 100644 index 0000000..e546184 --- /dev/null +++ b/androidApp/gradle/libs.versions.toml @@ -0,0 +1,100 @@ +[versions] +agp = "9.1.0" +coilCompose = "3.3.0" +constraintlayoutCompose = "1.1.1" +datastore = "1.2.0" +esclkt = "2.0.6" +escl-mock-server = "1.0.1" +itextCore = "9.3.0" +kotlin = "2.3.20-Beta1" +coreKtx = "1.17.0" +junit = "4.13.2" +junitVersion = "1.3.0" +espressoCore = "3.7.0" +kotlinReflect = "2.1.20" +kotlinxSerializationJson = "1.9.0" +lifecycleRuntimeKtx = "2.9.4" +activityCompose = "1.11.0" +composeBom = "2025.10.00" +room = "2.8.4" +timber = "5.0.1" +zoomable = "0.18.0" +material3 = "1.5.0-alpha06" +materialIcons = "1.7.8" +navigationCompose = "2.9.5" +versionsPlugin = "0.53.0" +screengrab = "2.1.1" +ktor = "3.4.0" +koin = "4.2.0-RC1" +koin-plugin = "0.3.0" +protobuf-plugin = "0.9.6" +protobuf-kotlin-lite = "4.33.5" +rules = "1.7.0" + +[libraries] + +androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" } + +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } + +koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" } +koin-annotations = { module = "io.insert-koin:koin-annotations", version.ref = "koin" } +koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin" } +koin-test-junit4 = { module = "io.insert-koin:koin-test-junit4", version.ref = "koin" } + +# Android +koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" } +koin-android-test = { module = "io.insert-koin:koin-android-test", version.ref = "koin" } + +koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin"} + +koin-androix-navigation = { module = "io.insert-koin:koin-androidx-compose-navigation", version.ref = "koin"} + +# Compose +koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", version.ref = "koin" } +koin-compose-viewmodel-navigation = { module = "io.insert-koin:koin-compose-viewmodel-navigation", version.ref = "koin" } +koin-androidx-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koin" } + +ktor-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor"} +ktor-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor"} +androidx-constraintlayout-compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "constraintlayoutCompose" } +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" } +androidx-material-icons-core = { module = "androidx.compose.material:material-icons-core" , version.ref = "materialIcons"} +androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } +coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coilCompose" } +esclkt = { module = "io.github.chrisimx:esclkt", version.ref = "esclkt" } +itext7-core = { module = "com.itextpdf:itext-core", version.ref = "itextCore" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +androidx-ui = { group = "androidx.compose.ui", name = "ui" } +androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } +androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } +androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } +androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } +kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlinReflect" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +screengrab = { module = "tools.fastlane:screengrab", version.ref = "screengrab" } +timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } +zoomable = { module = "me.saket.telephoto:zoomable", version.ref = "zoomable" } +protobuf-kotlin-lite = { module = "com.google.protobuf:protobuf-kotlin-lite", version.ref = "protobuf-kotlin-lite"} +androidx-rules = { group = "androidx.test", name = "rules", version.ref = "rules" } + +escl-mock-server = { module = "io.github.chrisimx:escl-mock-server", version.ref = "escl-mock-server"} + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +versions = { id = "com.github.ben-manes.versions", version.ref = "versionsPlugin" } +koin = { id = "io.insert-koin.compiler.plugin", version.ref = "koin-plugin" } +protobuf = { id = "com.google.protobuf", version.ref = "protobuf-plugin" } +room = { id = "androidx.room", version.ref = "room"} \ No newline at end of file diff --git a/app/proguard-rules.pro b/androidApp/proguard-rules.pro similarity index 100% rename from app/proguard-rules.pro rename to androidApp/proguard-rules.pro diff --git a/app/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json b/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json similarity index 100% rename from app/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json rename to androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json diff --git a/app/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json b/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json similarity index 100% rename from app/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json rename to androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json diff --git a/app/src/androidTest/assets/scan-1.jpg b/androidApp/src/androidTest/assets/scan-1.jpg similarity index 100% rename from app/src/androidTest/assets/scan-1.jpg rename to androidApp/src/androidTest/assets/scan-1.jpg diff --git a/app/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt b/androidApp/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt similarity index 100% rename from app/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt rename to androidApp/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt diff --git a/app/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeTest.kt b/androidApp/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeTest.kt similarity index 100% rename from app/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeTest.kt rename to androidApp/src/androidTest/java/io/github/chrisimx/scanbridge/ScanBridgeTest.kt diff --git a/app/src/androidTest/java/io/github/chrisimx/scanbridge/screenshot/ScanBridgeScreenshotTest.kt b/androidApp/src/androidTest/java/io/github/chrisimx/scanbridge/screenshot/ScanBridgeScreenshotTest.kt similarity index 100% rename from app/src/androidTest/java/io/github/chrisimx/scanbridge/screenshot/ScanBridgeScreenshotTest.kt rename to androidApp/src/androidTest/java/io/github/chrisimx/scanbridge/screenshot/ScanBridgeScreenshotTest.kt diff --git a/app/src/debug/AndroidManifest.xml b/androidApp/src/debug/AndroidManifest.xml similarity index 100% rename from app/src/debug/AndroidManifest.xml rename to androidApp/src/debug/AndroidManifest.xml diff --git a/app/src/fdroid/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt b/androidApp/src/fdroid/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt similarity index 100% rename from app/src/fdroid/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt rename to androidApp/src/fdroid/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt diff --git a/app/src/main/AndroidManifest.xml b/androidApp/src/main/AndroidManifest.xml similarity index 100% rename from app/src/main/AndroidManifest.xml rename to androidApp/src/main/AndroidManifest.xml diff --git a/app/src/main/ic_launcher-playstore.png b/androidApp/src/main/ic_launcher-playstore.png similarity index 100% rename from app/src/main/ic_launcher-playstore.png rename to androidApp/src/main/ic_launcher-playstore.png diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/AppSettingsScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/AppSettingsScreen.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/AppSettingsScreen.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/AppSettingsScreen.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt similarity index 96% rename from app/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt index 981beed..5d196fb 100644 --- a/app/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt @@ -13,7 +13,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +// TODO: import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -28,7 +28,7 @@ import io.github.chrisimx.scanbridge.theme.ScanBridgeTheme import timber.log.Timber class CrashActivity : ComponentActivity() { - @OptIn(ExperimentalMaterial3ExpressiveApi::class) + // TODO: @OptIn(ExperimentalMaterial3ExpressiveApi::class) override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt similarity index 97% rename from app/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt index 36597ab..fbdd7f1 100644 --- a/app/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt @@ -6,7 +6,7 @@ import androidx.compose.animation.core.snap import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +// TODO: import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExtendedFloatingActionButton import androidx.compose.material3.FabPosition import androidx.compose.material3.Icon @@ -69,7 +69,7 @@ suspend fun finishCrop(cropRect: Rect, file: String): File? = withContext(Dispat return@withContext croppedFile } -@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalTelephotoApi::class) +// TODO: @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalTelephotoApi::class) @Composable fun CropScreen(scanId: Uuid, returnRoute: BaseRoute, navController: NavController) { val context = LocalContext.current diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt similarity index 97% rename from app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt index 5057871..5d39c22 100644 --- a/app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt @@ -24,7 +24,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Favorite import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +// TODO: import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -59,7 +59,7 @@ import kotlinx.coroutines.withContext import kotlinx.serialization.json.Json import timber.log.Timber -@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) +// TODO: @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun ScanBridgeApp() { ScanBridgeTheme { diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeNavHost.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/model/EditedCustomScanner.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/EditedCustomScanner.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/model/EditedCustomScanner.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/EditedCustomScanner.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacyESCLScanSettings.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacyESCLScanSettings.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacyESCLScanSettings.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacyESCLScanSettings.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/model/PaperFormat.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/PaperFormat.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/model/PaperFormat.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/PaperFormat.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/model/ScanJob.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/ScanJob.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/model/ScanJob.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/ScanJob.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/ui/CustomScannerViewModel.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/CustomScannerViewModel.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/ui/CustomScannerViewModel.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/CustomScannerViewModel.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/datastore/DataStores.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/DataStores.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/datastore/DataStores.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/DataStores.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/datastore/LastRouteStoreSerializer.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/LastRouteStoreSerializer.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/datastore/LastRouteStoreSerializer.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/LastRouteStoreSerializer.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanBridgeSettingsSerializer.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanBridgeSettingsSerializer.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanBridgeSettingsSerializer.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanBridgeSettingsSerializer.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanSettingsDataStoreHelpers.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanSettingsDataStoreHelpers.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanSettingsDataStoreHelpers.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/ScanSettingsDataStoreHelpers.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/datastore/ShownMessagesSerializer.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/ShownMessagesSerializer.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/datastore/ShownMessagesSerializer.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/datastore/ShownMessagesSerializer.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/entities/Session.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/Session.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/entities/Session.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/Session.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/entities/TempFile.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/TempFile.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/entities/TempFile.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/TempFile.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/logs/FileLogger.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/logs/FileLogger.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/logs/FileLogger.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/logs/FileLogger.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/services/DebugLogService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/DebugLogService.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/services/DebugLogService.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/services/DebugLogService.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/stores/LegacyCustomScannerStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacyCustomScannerStore.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/stores/LegacyCustomScannerStore.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacyCustomScannerStore.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/theme/Color.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Color.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/theme/Color.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Color.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/theme/Theme.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Theme.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/theme/Theme.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Theme.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CrashFileHandler.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CrashFileHandler.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CrashFileHandler.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CrashFileHandler.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CroppableImage.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CroppableImage.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CroppableImage.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/CroppableImage.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ExportSettingsPopup.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ExportSettingsPopup.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ExportSettingsPopup.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ExportSettingsPopup.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FoundScannerItem.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FoundScannerItem.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FoundScannerItem.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FoundScannerItem.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FullScreenError.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FullScreenError.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FullScreenError.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/FullScreenError.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/SizeBasedConditionalView.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/SizeBasedConditionalView.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/SizeBasedConditionalView.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/SizeBasedConditionalView.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TemporaryFileHandlePrompt.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TemporaryFileHandlePrompt.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TemporaryFileHandlePrompt.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TemporaryFileHandlePrompt.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ConfirmCloseDialog.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ConfirmCloseDialog.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ConfirmCloseDialog.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ConfirmCloseDialog.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CrashFileDialog.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CrashFileDialog.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CrashFileDialog.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CrashFileDialog.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CustomScannerDialog.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CustomScannerDialog.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CustomScannerDialog.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/CustomScannerDialog.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/DeleteDialog.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/DeleteDialog.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/DeleteDialog.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/DeleteDialog.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ErrorDialog.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ErrorDialog.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ErrorDialog.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/ErrorDialog.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/LoadingDialog.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/LoadingDialog.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/LoadingDialog.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/LoadingDialog.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/SimpleTextDialog.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/SimpleTextDialog.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/SimpleTextDialog.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/SimpleTextDialog.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/TemporaryFileHandlingDialog.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/TemporaryFileHandlingDialog.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/TemporaryFileHandlingDialog.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/dialog/TemporaryFileHandlingDialog.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/CheckboxSetting.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/CheckboxSetting.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/CheckboxSetting.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/CheckboxSetting.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/MoreInformationButton.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/MoreInformationButton.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/MoreInformationButton.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/MoreInformationButton.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/UIntSetting.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/UIntSetting.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/UIntSetting.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/UIntSetting.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/ESCLKtExtensions.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ESCLKtExtensions.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/ESCLKtExtensions.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ESCLKtExtensions.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/ImageUtil.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ImageUtil.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/ImageUtil.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ImageUtil.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/NavControllerExtensions.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/NavControllerExtensions.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/NavControllerExtensions.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/NavControllerExtensions.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/PdfUtil.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/PdfUtil.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/PdfUtil.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/PdfUtil.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/ScanFileNameUtil.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ScanFileNameUtil.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/ScanFileNameUtil.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ScanFileNameUtil.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/ScanSettingsJson.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ScanSettingsJson.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/ScanSettingsJson.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ScanSettingsJson.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/StateFlowExtensions.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/StateFlowExtensions.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/StateFlowExtensions.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/StateFlowExtensions.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/TempFileUtil.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/TempFileUtil.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/TempFileUtil.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/TempFileUtil.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/TrustAllTrustManager.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/TrustAllTrustManager.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/TrustAllTrustManager.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/TrustAllTrustManager.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/UIUtils.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/UIUtils.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/UIUtils.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/UIUtils.kt diff --git a/app/src/main/java/io/github/chrisimx/scanbridge/util/ZipArchiveUtil.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ZipArchiveUtil.kt similarity index 100% rename from app/src/main/java/io/github/chrisimx/scanbridge/util/ZipArchiveUtil.kt rename to androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ZipArchiveUtil.kt diff --git a/app/src/main/proto/app_settings.proto b/androidApp/src/main/proto/app_settings.proto similarity index 100% rename from app/src/main/proto/app_settings.proto rename to androidApp/src/main/proto/app_settings.proto diff --git a/app/src/main/proto/route_store.proto b/androidApp/src/main/proto/route_store.proto similarity index 100% rename from app/src/main/proto/route_store.proto rename to androidApp/src/main/proto/route_store.proto diff --git a/app/src/main/proto/shown_messages.proto b/androidApp/src/main/proto/shown_messages.proto similarity index 100% rename from app/src/main/proto/shown_messages.proto rename to androidApp/src/main/proto/shown_messages.proto diff --git a/app/src/main/res/drawable/baseline_image_24.xml b/androidApp/src/main/res/drawable/baseline_image_24.xml similarity index 100% rename from app/src/main/res/drawable/baseline_image_24.xml rename to androidApp/src/main/res/drawable/baseline_image_24.xml diff --git a/app/src/main/res/drawable/baseline_picture_as_pdf_24.xml b/androidApp/src/main/res/drawable/baseline_picture_as_pdf_24.xml similarity index 100% rename from app/src/main/res/drawable/baseline_picture_as_pdf_24.xml rename to androidApp/src/main/res/drawable/baseline_picture_as_pdf_24.xml diff --git a/app/src/main/res/drawable/baseline_rotate_right_24.xml b/androidApp/src/main/res/drawable/baseline_rotate_right_24.xml similarity index 100% rename from app/src/main/res/drawable/baseline_rotate_right_24.xml rename to androidApp/src/main/res/drawable/baseline_rotate_right_24.xml diff --git a/app/src/main/res/drawable/favorite_24px.xml b/androidApp/src/main/res/drawable/favorite_24px.xml similarity index 100% rename from app/src/main/res/drawable/favorite_24px.xml rename to androidApp/src/main/res/drawable/favorite_24px.xml diff --git a/app/src/main/res/drawable/github_mark.xml b/androidApp/src/main/res/drawable/github_mark.xml similarity index 100% rename from app/src/main/res/drawable/github_mark.xml rename to androidApp/src/main/res/drawable/github_mark.xml diff --git a/app/src/main/res/drawable/icon_about_dialog.png b/androidApp/src/main/res/drawable/icon_about_dialog.png similarity index 100% rename from app/src/main/res/drawable/icon_about_dialog.png rename to androidApp/src/main/res/drawable/icon_about_dialog.png diff --git a/app/src/main/res/drawable/outline_crop_24.xml b/androidApp/src/main/res/drawable/outline_crop_24.xml similarity index 100% rename from app/src/main/res/drawable/outline_crop_24.xml rename to androidApp/src/main/res/drawable/outline_crop_24.xml diff --git a/app/src/main/res/drawable/outline_edit_24.xml b/androidApp/src/main/res/drawable/outline_edit_24.xml similarity index 100% rename from app/src/main/res/drawable/outline_edit_24.xml rename to androidApp/src/main/res/drawable/outline_edit_24.xml diff --git a/app/src/main/res/drawable/outline_error_24.xml b/androidApp/src/main/res/drawable/outline_error_24.xml similarity index 100% rename from app/src/main/res/drawable/outline_error_24.xml rename to androidApp/src/main/res/drawable/outline_error_24.xml diff --git a/app/src/main/res/drawable/outline_file_save_24.xml b/androidApp/src/main/res/drawable/outline_file_save_24.xml similarity index 100% rename from app/src/main/res/drawable/outline_file_save_24.xml rename to androidApp/src/main/res/drawable/outline_file_save_24.xml diff --git a/app/src/main/res/drawable/outline_pan_zoom_24.xml b/androidApp/src/main/res/drawable/outline_pan_zoom_24.xml similarity index 100% rename from app/src/main/res/drawable/outline_pan_zoom_24.xml rename to androidApp/src/main/res/drawable/outline_pan_zoom_24.xml diff --git a/app/src/main/res/drawable/outline_scan_24.xml b/androidApp/src/main/res/drawable/outline_scan_24.xml similarity index 100% rename from app/src/main/res/drawable/outline_scan_24.xml rename to androidApp/src/main/res/drawable/outline_scan_24.xml diff --git a/app/src/main/res/drawable/round_print_36.xml b/androidApp/src/main/res/drawable/round_print_36.xml similarity index 100% rename from app/src/main/res/drawable/round_print_36.xml rename to androidApp/src/main/res/drawable/round_print_36.xml diff --git a/app/src/main/res/drawable/rounded_adf_scanner_24.xml b/androidApp/src/main/res/drawable/rounded_adf_scanner_24.xml similarity index 100% rename from app/src/main/res/drawable/rounded_adf_scanner_24.xml rename to androidApp/src/main/res/drawable/rounded_adf_scanner_24.xml diff --git a/app/src/main/res/drawable/rounded_content_copy_24.xml b/androidApp/src/main/res/drawable/rounded_content_copy_24.xml similarity index 100% rename from app/src/main/res/drawable/rounded_content_copy_24.xml rename to androidApp/src/main/res/drawable/rounded_content_copy_24.xml diff --git a/app/src/main/res/drawable/rounded_document_scanner_24.xml b/androidApp/src/main/res/drawable/rounded_document_scanner_24.xml similarity index 100% rename from app/src/main/res/drawable/rounded_document_scanner_24.xml rename to androidApp/src/main/res/drawable/rounded_document_scanner_24.xml diff --git a/app/src/main/res/drawable/rounded_scanner_24.xml b/androidApp/src/main/res/drawable/rounded_scanner_24.xml similarity index 100% rename from app/src/main/res/drawable/rounded_scanner_24.xml rename to androidApp/src/main/res/drawable/rounded_scanner_24.xml diff --git a/app/src/main/res/drawable/rounded_warning_24.xml b/androidApp/src/main/res/drawable/rounded_warning_24.xml similarity index 100% rename from app/src/main/res/drawable/rounded_warning_24.xml rename to androidApp/src/main/res/drawable/rounded_warning_24.xml diff --git a/app/src/main/res/drawable/twotone_wifi_find_24.xml b/androidApp/src/main/res/drawable/twotone_wifi_find_24.xml similarity index 100% rename from app/src/main/res/drawable/twotone_wifi_find_24.xml rename to androidApp/src/main/res/drawable/twotone_wifi_find_24.xml diff --git a/app/src/main/res/font/poppins_black.ttf b/androidApp/src/main/res/font/poppins_black.ttf similarity index 100% rename from app/src/main/res/font/poppins_black.ttf rename to androidApp/src/main/res/font/poppins_black.ttf diff --git a/app/src/main/res/font/poppins_blackitalic.ttf b/androidApp/src/main/res/font/poppins_blackitalic.ttf similarity index 100% rename from app/src/main/res/font/poppins_blackitalic.ttf rename to androidApp/src/main/res/font/poppins_blackitalic.ttf diff --git a/app/src/main/res/font/poppins_bold.ttf b/androidApp/src/main/res/font/poppins_bold.ttf similarity index 100% rename from app/src/main/res/font/poppins_bold.ttf rename to androidApp/src/main/res/font/poppins_bold.ttf diff --git a/app/src/main/res/font/poppins_bolditalic.ttf b/androidApp/src/main/res/font/poppins_bolditalic.ttf similarity index 100% rename from app/src/main/res/font/poppins_bolditalic.ttf rename to androidApp/src/main/res/font/poppins_bolditalic.ttf diff --git a/app/src/main/res/font/poppins_extrabold.ttf b/androidApp/src/main/res/font/poppins_extrabold.ttf similarity index 100% rename from app/src/main/res/font/poppins_extrabold.ttf rename to androidApp/src/main/res/font/poppins_extrabold.ttf diff --git a/app/src/main/res/font/poppins_extrabolditalic.ttf b/androidApp/src/main/res/font/poppins_extrabolditalic.ttf similarity index 100% rename from app/src/main/res/font/poppins_extrabolditalic.ttf rename to androidApp/src/main/res/font/poppins_extrabolditalic.ttf diff --git a/app/src/main/res/font/poppins_extralight.ttf b/androidApp/src/main/res/font/poppins_extralight.ttf similarity index 100% rename from app/src/main/res/font/poppins_extralight.ttf rename to androidApp/src/main/res/font/poppins_extralight.ttf diff --git a/app/src/main/res/font/poppins_extralightitalic.ttf b/androidApp/src/main/res/font/poppins_extralightitalic.ttf similarity index 100% rename from app/src/main/res/font/poppins_extralightitalic.ttf rename to androidApp/src/main/res/font/poppins_extralightitalic.ttf diff --git a/app/src/main/res/font/poppins_italic.ttf b/androidApp/src/main/res/font/poppins_italic.ttf similarity index 100% rename from app/src/main/res/font/poppins_italic.ttf rename to androidApp/src/main/res/font/poppins_italic.ttf diff --git a/app/src/main/res/font/poppins_light.ttf b/androidApp/src/main/res/font/poppins_light.ttf similarity index 100% rename from app/src/main/res/font/poppins_light.ttf rename to androidApp/src/main/res/font/poppins_light.ttf diff --git a/app/src/main/res/font/poppins_lightitalic.ttf b/androidApp/src/main/res/font/poppins_lightitalic.ttf similarity index 100% rename from app/src/main/res/font/poppins_lightitalic.ttf rename to androidApp/src/main/res/font/poppins_lightitalic.ttf diff --git a/app/src/main/res/font/poppins_medium.ttf b/androidApp/src/main/res/font/poppins_medium.ttf similarity index 100% rename from app/src/main/res/font/poppins_medium.ttf rename to androidApp/src/main/res/font/poppins_medium.ttf diff --git a/app/src/main/res/font/poppins_mediumitalic.ttf b/androidApp/src/main/res/font/poppins_mediumitalic.ttf similarity index 100% rename from app/src/main/res/font/poppins_mediumitalic.ttf rename to androidApp/src/main/res/font/poppins_mediumitalic.ttf diff --git a/app/src/main/res/font/poppins_regular.ttf b/androidApp/src/main/res/font/poppins_regular.ttf similarity index 100% rename from app/src/main/res/font/poppins_regular.ttf rename to androidApp/src/main/res/font/poppins_regular.ttf diff --git a/app/src/main/res/font/poppins_semibold.ttf b/androidApp/src/main/res/font/poppins_semibold.ttf similarity index 100% rename from app/src/main/res/font/poppins_semibold.ttf rename to androidApp/src/main/res/font/poppins_semibold.ttf diff --git a/app/src/main/res/font/poppins_semibolditalic.ttf b/androidApp/src/main/res/font/poppins_semibolditalic.ttf similarity index 100% rename from app/src/main/res/font/poppins_semibolditalic.ttf rename to androidApp/src/main/res/font/poppins_semibolditalic.ttf diff --git a/app/src/main/res/font/poppins_thin.ttf b/androidApp/src/main/res/font/poppins_thin.ttf similarity index 100% rename from app/src/main/res/font/poppins_thin.ttf rename to androidApp/src/main/res/font/poppins_thin.ttf diff --git a/app/src/main/res/font/poppins_thinitalic.ttf b/androidApp/src/main/res/font/poppins_thinitalic.ttf similarity index 100% rename from app/src/main/res/font/poppins_thinitalic.ttf rename to androidApp/src/main/res/font/poppins_thinitalic.ttf diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-hdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher.webp rename to androidApp/src/main/res/mipmap-hdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_background.webp b/androidApp/src/main/res/mipmap-hdpi/ic_launcher_background.webp similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher_background.webp rename to androidApp/src/main/res/mipmap-hdpi/ic_launcher_background.webp diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/androidApp/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp rename to androidApp/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher_round.webp rename to androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-mdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher.webp rename to androidApp/src/main/res/mipmap-mdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_background.webp b/androidApp/src/main/res/mipmap-mdpi/ic_launcher_background.webp similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher_background.webp rename to androidApp/src/main/res/mipmap-mdpi/ic_launcher_background.webp diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/androidApp/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp rename to androidApp/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher_round.webp rename to androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-xhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher.webp rename to androidApp/src/main/res/mipmap-xhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_background.webp b/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_background.webp similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher_background.webp rename to androidApp/src/main/res/mipmap-xhdpi/ic_launcher_background.webp diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp rename to androidApp/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp rename to androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher.webp rename to androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp b/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp rename to androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp rename to androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp rename to androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp rename to androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp b/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp rename to androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp rename to androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp rename to androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/raw/test_scanner_capabilities b/androidApp/src/main/res/raw/test_scanner_capabilities similarity index 100% rename from app/src/main/res/raw/test_scanner_capabilities rename to androidApp/src/main/res/raw/test_scanner_capabilities diff --git a/app/src/main/res/resources.properties b/androidApp/src/main/res/resources.properties similarity index 100% rename from app/src/main/res/resources.properties rename to androidApp/src/main/res/resources.properties diff --git a/app/src/main/res/values-de/strings.xml b/androidApp/src/main/res/values-de/strings.xml similarity index 100% rename from app/src/main/res/values-de/strings.xml rename to androidApp/src/main/res/values-de/strings.xml diff --git a/app/src/main/res/values-it/strings.xml b/androidApp/src/main/res/values-it/strings.xml similarity index 100% rename from app/src/main/res/values-it/strings.xml rename to androidApp/src/main/res/values-it/strings.xml diff --git a/app/src/main/res/values/colors.xml b/androidApp/src/main/res/values/colors.xml similarity index 100% rename from app/src/main/res/values/colors.xml rename to androidApp/src/main/res/values/colors.xml diff --git a/app/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml similarity index 100% rename from app/src/main/res/values/strings.xml rename to androidApp/src/main/res/values/strings.xml diff --git a/app/src/main/res/values/themes.xml b/androidApp/src/main/res/values/themes.xml similarity index 100% rename from app/src/main/res/values/themes.xml rename to androidApp/src/main/res/values/themes.xml diff --git a/app/src/main/res/xml/backup_rules.xml b/androidApp/src/main/res/xml/backup_rules.xml similarity index 100% rename from app/src/main/res/xml/backup_rules.xml rename to androidApp/src/main/res/xml/backup_rules.xml diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/androidApp/src/main/res/xml/data_extraction_rules.xml similarity index 100% rename from app/src/main/res/xml/data_extraction_rules.xml rename to androidApp/src/main/res/xml/data_extraction_rules.xml diff --git a/app/src/main/res/xml/network_security_config.xml b/androidApp/src/main/res/xml/network_security_config.xml similarity index 100% rename from app/src/main/res/xml/network_security_config.xml rename to androidApp/src/main/res/xml/network_security_config.xml diff --git a/app/src/main/res/xml/provider_paths.xml b/androidApp/src/main/res/xml/provider_paths.xml similarity index 100% rename from app/src/main/res/xml/provider_paths.xml rename to androidApp/src/main/res/xml/provider_paths.xml diff --git a/app/src/play/AndroidManifest.xml b/androidApp/src/play/AndroidManifest.xml similarity index 100% rename from app/src/play/AndroidManifest.xml rename to androidApp/src/play/AndroidManifest.xml diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/AccountSetupScreen.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/AccountSetupScreen.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/AccountSetupScreen.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/AccountSetupScreen.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/InternetConnectivityFlow.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/InternetConnectivityFlow.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/InternetConnectivityFlow.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/InternetConnectivityFlow.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/LicenseErrorStringMapping.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/LicenseErrorStringMapping.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/LicenseErrorStringMapping.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/LicenseErrorStringMapping.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/OwnershipProofService.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/OwnershipProofService.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/OwnershipProofService.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/OwnershipProofService.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/OwnershipTestScreen.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/OwnershipTestScreen.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/OwnershipTestScreen.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/OwnershipTestScreen.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/PlainTextObfuscator.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/PlainTextObfuscator.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/PlainTextObfuscator.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/PlainTextObfuscator.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/SignupScreen.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/SignupScreen.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/SignupScreen.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/SignupScreen.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/SimpleStrictLicensePolicy.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/SimpleStrictLicensePolicy.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/SimpleStrictLicensePolicy.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/SimpleStrictLicensePolicy.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/SpecialIcons.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/SpecialIcons.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/SpecialIcons.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/SpecialIcons.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/StartupTabDefinitions.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/SuccessSigningUpScreen.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/SuccessSigningUpScreen.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/SuccessSigningUpScreen.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/SuccessSigningUpScreen.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/SupportScreen.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/SupportScreen.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/SupportScreen.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/SupportScreen.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerificationClient.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerificationClient.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerificationClient.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerificationClient.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerifierApi.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerifierApi.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerifierApi.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/AccountVerifierApi.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/AccountCreationRequest.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/AccountCreationRequest.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/AccountCreationRequest.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/AccountCreationRequest.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/GoogleChallenge.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/GoogleChallenge.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/GoogleChallenge.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/GoogleChallenge.kt diff --git a/app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/VIPCreationResult.kt b/androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/VIPCreationResult.kt similarity index 100% rename from app/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/VIPCreationResult.kt rename to androidApp/src/play/java/io/github/chrisimx/scanbridge/zammadapi/models/VIPCreationResult.kt diff --git a/app/src/play/res/drawable/fireamp_icon.xml b/androidApp/src/play/res/drawable/fireamp_icon.xml similarity index 100% rename from app/src/play/res/drawable/fireamp_icon.xml rename to androidApp/src/play/res/drawable/fireamp_icon.xml diff --git a/app/src/play/res/drawable/outline_globe_24.xml b/androidApp/src/play/res/drawable/outline_globe_24.xml similarity index 100% rename from app/src/play/res/drawable/outline_globe_24.xml rename to androidApp/src/play/res/drawable/outline_globe_24.xml diff --git a/app/src/play/res/values-de/strings.xml b/androidApp/src/play/res/values-de/strings.xml similarity index 100% rename from app/src/play/res/values-de/strings.xml rename to androidApp/src/play/res/values-de/strings.xml diff --git a/app/src/play/res/values-it/strings.xml b/androidApp/src/play/res/values-it/strings.xml similarity index 100% rename from app/src/play/res/values-it/strings.xml rename to androidApp/src/play/res/values-it/strings.xml diff --git a/app/src/play/res/values/strings.xml b/androidApp/src/play/res/values/strings.xml similarity index 100% rename from app/src/play/res/values/strings.xml rename to androidApp/src/play/res/values/strings.xml diff --git a/app/src/test/java/org/github/chrisimx/scanbridge/PaperFormatTest.kt b/androidApp/src/test/java/org/github/chrisimx/scanbridge/PaperFormatTest.kt similarity index 100% rename from app/src/test/java/org/github/chrisimx/scanbridge/PaperFormatTest.kt rename to androidApp/src/test/java/org/github/chrisimx/scanbridge/PaperFormatTest.kt diff --git a/app/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt b/androidApp/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt similarity index 100% rename from app/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt rename to androidApp/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index d497f64..c70a45c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,13 @@ import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask -// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - alias(libs.plugins.android.application) apply false - alias(libs.plugins.kotlin.compose) apply false + alias(libs.plugins.kotlin.multiplatform).apply(false) + alias(libs.plugins.compose.compiler).apply(false) + alias(libs.plugins.compose.multiplatform).apply(false) + alias(libs.plugins.kotlin.android).apply(false) + alias(libs.plugins.android.application).apply(false) + alias(libs.plugins.android.kmp.library).apply(false) + alias(libs.plugins.kotlin.jvm).apply(false) alias(libs.plugins.versions) } diff --git a/desktopApp/appIcons/LinuxIcon.png b/desktopApp/appIcons/LinuxIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..a2a45177828cfad12314c1ad8bf355810a6650ea GIT binary patch literal 26701 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 DB{tZG literal 0 HcmV?d00001 diff --git a/desktopApp/appIcons/MacosIcon.icns b/desktopApp/appIcons/MacosIcon.icns new file mode 100644 index 0000000000000000000000000000000000000000..083def599c89cf7e55dd2c27c8e2d16a6743d94d GIT binary patch literal 260854 zcmeFZRZtyo@HRLH4({%*!3l)m9Nb-kLvRT0&cWRsfUrLNpBZaYdlvxq;l|q3ksAPDA|h3kq|uOxkpTcela-NB zdplzO&xQ#9wx_sy{rsjREh{0a!K)mbY#@`YN;vqszvf!ReE~~_OpO%W&m+#DXvJu4 zfIE#G+^vdR;s>RzraYiV%+YI&poUus9blAW3K2v6C-#-1O_SK{Bi*$*+(f3S&;H}h zSDd)4WcST(zSn)euKhn>`??2X(@d;3^EE#xR!?b>bCy*RsGYzNvng_{x~GV#J`Rce z5kbHir{b9Fb*yZoFvhnZmysW2s>bKq3f0i@16v`nN(TH~iF%owb?hRS$2$*()i@ou zl2Xo_7Uud6?1OZaiWXJz9b{#Stk-JkW9L!0C1ec0O(8 zB#G>&asocVG)aFR8V~R63sr8OEjw(BhvN%N4CXQO_#p|bM3cKJD$*lpqaa^6F8Cj; z7~Hw(Ivkhtwx#lP?K`wzeO z_>>N6T{h$BvHp&WrJ)H|1mE)D*LpyLX?~81FI!6G0?ELC=tr3-{*+lVs~UysGL0C- zje%?XD|6ef%y-+s8N(Tx=l)9qQvaNGA~-f%l$D$JXsWe@`KmB?o$0L(V!2XXRC);t z%tmL@u2X5&{QZgRT^1gcb7pY(3`L_Ht@H%83q<8SYrlof%KDaBfUKmF#CI{{ptn5y z003~`|2KI^`KCtszw*$<+xz-W$?kvhP+Pj`6N-w4Iqr*ldTA6%R@NnE9#z>r1a`Z; zf0U4WTuNSgjGOyvI)lGs%yxMUOhrYn(xAaTE`c`gn_n1_RUV9l7m|dCc!}-y*+XD| z1OM|%s(}R`m&ab$ZSJ7QL_p`&2D7NV?8{Gv{J2ml9NGBrS@VS>zefl1ghM~3Dxj^0LU}lgsY}i|y!u{_IBGxoe$<6l zMy57YQ=IDluPM<6z0bRlv1x;#;z<)=oIZJ+rMzsq9}|#-zmIvp^O24N)gIls->3~b zMxsxP5)JP|1QBi{t2$dQZ-9-m>=!FnD_BUA`2B&2mDIp>QxjfAULL{k%q2`PxF)za zQO_{S^48YwpLfD4R-m8$^g;pieL{X~Cp?40nuNbwsu$%4MpGcx%)G>5csK8u6J`T% z=kqVsLiWf22g@qrKjD1tzYb@xtM~(m2VdUt;K{JU8n3*{O7)vbw4wEf z@0=$`TXIagfO#ImkvkA7=$~|42+YyYxb>jq?l~L@6($ZP>mLPaVbyF+I~fVf1Eebq(FN?;)oS% zYO~ERozuSB2?j!E61}aTX@tF-JeUSLH(^~7k@d$x=iJlpM-de(cm$E_-LT_UN*~g9zP_ zer_Z|hNW%;Ixzi_%9Xz88hsKV!i^@BGMExfo75g4MBj z3uQp9}hg zX+{ZM@ZF2EIiJ+Y@~SYfI=njlb!&!eFstp<*bcU>+8zD(yVSxHmWH)(9K}9kN$xf0 zXC_aJC;t{~@w)%qzYtW#9aQv*s zgV5*Xgime=;vP0WGRoX`_8^klzEp6KCG2R&FR8CJjFL_U)x3`ShuSx%a|rr)_~@ON z`e{}Zzw;6Giz5%rJ*g{*02f({T48UDL4n%=CU%iK;a#(H-j`IE3s8z^a{Qyo_#*IA zU>PCY0iWurn@yam-&$MR;YS7xr1a0yU)c~W@dpn-F+rw^>K=C21ILD@lwh21lrwI? z`l!&mZ{I-WCcx9bO&fGT-PO+gz32d2Bdd5B2n98Obyq&2YN*f~E@S&QDcSca_%2M& zH1V5K60Y%`$;*LjQ9R2ym(fET6E_ihII=o4JAhR}odM%7$D{LKMwz)mE4mha_xOJr zNO(bYj&Ocy$F!=PF+&-$ElOml+wjkrAu|C~ukqaRE_P$T|E=X~bjnsDxw?&=-NR-} zu;{2&%U>GJ7*p)htqw-~->Wqz=YQ4uziRzowf?VK|5vU5zhA8#c>nJ}yeKn+x#g&TFQA#|Ekap13 zs~^TBJSTd6i8j3ONLIp)Tcwvhk_na~`*c(SZ+vr?HRhT@RR7a*Wb}x(mhN|nsOiLz z5g{mpXj2OP2j)x9KOs#+tz$MiYoXz@c1GXNU`h^Sv~2(VTmAcmqr zv*&?A{&ouwY6fZ3+NmQ~R{>!q*Q~MK^r384<0l1lKch%F=c6lOjcN#0UoFk8z4~)k zTBK5P+Y^5lfU@`te@aav>1nB6JtdxkPv#e;n$H?G|I6n0A@0n{QKCW#7y6K-IHqWs zE4Nf)?rMLoz66BHJk^2$F3E46dY%|{a0;yhGmcG`B7f}{QnT<`KNC7$zt~l@ypVAP z$gryt0?_>t^R5SpPd=#mYF?K_VNaghn9r^=?!=%Mbh=U1wO)G-dIx`|os?u}^Won2 zGPvn?NvA^5rOe7Eh{oT$+#{*Cb0Z>B)YcJ!g#IEj35$p;vWZ^H52)pBHyHdxZj-ji zcM+)!N56k&w6Dn@WVlRLlW^0V&_4SGkNU=O97=eApi?J^0T_#*k<+shp3JX% zikvvu%J;YQtmTm_(&b6d=N)=G4VKIX7RNFOQP}YLyV50AdL*X9nD^Xiax6JTN#muy z=31SpOmZ2>7{4#fK*ds6iY)Iki|1yb&jMDTJ*{+2&t(XqTe%;sZ92Zeiz-R4l^%T| zAbByGe^NhEZ7$Rlef7FdpwAJK%BJ}~RTM(tE!^_8tqjc}6-&_L-j_{l(7x3_liyal zl6ss`iV*s)N)ViCy^$kxx!kJudPbqRqEZttgiE)_{5@pHjM&QzgSGt{L&z)BSp7jz zr$N={_C4<60ZwXOB0_bmZ>~4kPKg<85(?7ZoQrx$t1-be*4z1D)3K|3G#&*DsO!3X z`1*tnKmELaAtol^Qvc7TI*hx&C~K*;0KsFr%B3`Puc4Qe9kn~j!mj*Nn_Sp^b8R}g zzvoATgZT~H$#~>->EsF0KZ4A=J9<6Idv#oz&EGe1j;f60N?9bxr&B{f8Iu#$MsP)N zCqM8+mC)mU=gV-;Ef)pfs&{7^M_;z?PsleR;};aRIUnP-kMecPDiu|Gc|)NQg~g_~ zXDY#Hqitq|@VU%ogB$L0r?DAG zl+ckjMy2juUrD@vzJLYqrhpUhJ)7ty2stT1JM)Gf4P}LvEEg+(3Zko;+6*Dh2^!Ujf1R!k9ig~8S(A(I>pSV0qmJhQ&L^h* zx|)CFkM70m+J+L3$(w( zIWyaUyqsuxzN12Cjvefu`I>fVrDeOm@{1);l9%#MAazH#ZE6Q-rYvrXc;4cFFp(}T zPGIvZkCF%VeFADPk3wCA_dZ8)$Y24VT8UYz%iwoYpLOc$1~G`ifh`C%Gh2cCUHU>< z_`Hs;eY`zlg>>P9=Nh_A&|V5@l0DL29f<1rT1IUU0}s0qUf`zXOeuCXDw{Q8vFdu$ zKrX#>F0b*^#jXKItcjgj@S@?O#rsTpA@T`0#g(iOP z@9w4z9~4r#s!3}18zysXxj28UKFj-cLFjqKcqKA1o&P+>t5nBYfdG3UJcp5Qh|uk} z%c+04u;V6P6C0)2moS+sT;0XyVu}fV>t@*)`_z^xyO(?8*BwdcZYHon)r7+qSHhYB- zGV=u?3Bxn^-435jDbzD}UAWMpI;8Q6D0qS(L8MIMk@UslR4+l?tO;bD3XBBy{P~3Y z9$1w=+XUmIIi!GpbWyZw%)#v0yxzY0Pq z49W=eA$agkm!5O|T2O2+An|MQnL?ym6sTJ)Erm-l#D>7RXfv)u!+C4?*EtTXF~7Sp zhnM9`#`?U~fccF(TTAM7>juZjs1U4r?^kV-t0A7Ixu}5YhRu z`Luiymvo~0proIp8u_WL%b6g$tH!k-X)3wVZx%y^(^Huf!WzR%o~1C~w0&hMg?37r zaj>aKzcJGEW~WH^rj#+dVZ9XkhGl8yj(By7xI=&C2s0Im1ixFvn$NHRaHNh8xV zn(V?9Gdf+d-#Z|7x!f_T#F}H)|6PTJj3X5cn^|1GWco#+VqcO*DAt@8KSo)h_^WR- zN1(v#E494b!9?#9nOp$-_;XN+3v8R z;^ngoktd>?G37Q>wHR%TB&q(}QjMcR5iVZd2vos`PPqLom5Vu-@Vm8_cVk{j$`g&< zY_cv9cFxzMot?;DINS)hQlxm4O{WKph2-s+eJMOoQT=>eYna3vrG-!KDZb2?I#kZ{ zn1;KABD;HOo z<2QDk4lq2O@&NoWF_abYZ@a7S&)zM*M*t3(mOI~niT_>0(9;v)Y&0THb)FmoMvnA{ zI3|g%DhvcNB0fXuzp|i}X{TZ+M`NE-Xk#Nj2U^%ZIJ-hDk;#}cUp$T&pSy)5LEcC} zk{49Uc#1>^!RIOZ41=2?L{={(jt%N$Cak9n_>e26>2RUhA{B$? zmLB4(u<6e=Q5G1M8ELPv5nw7!Min)RBDf#4i_5_nJ9W~ae#Y#ke8v1(S}Z~oM7D>C zH%9L78Z3~;G&uO@Ls`LaTTk|{qJ{7Yj+>^E_18iD_u(#wEI8h1ORWo(G8iD>^f!qB zW)RonXq?JY=}!dBecvsbQ-)Ul-6@JP=#)5QFCuv_8RHad;&npkecD{w{DD!TattvE zhP(LU-JA1d0w541Th9g3~p&o7Jc@3&ZB zEU|-d!6=JE_)|)b#^36TXkzUf6da+U_i4oTl}Izxos2{rnP*7xxTG27C(*pHCq=vr z3QnK2rHdTZ8%aLVGQZcP=^4N>ap5Osw-(wZr@?0VJR_^PJ34c=h^PEnlNC)SznIj^ zh|buB9_$ol{_`P|{;KP5vP{6`BaDF|=zOL1NAVn~*NUW)-hB$Yg7IEARMXdb`Jv5Y z`FrkCL-l4loi_y06z%e80EzqeDwp05SHoB0{du=BqpaQvE{0Uva5Mb}zm0Vw-`H~3 zWY@@l)*FhtFD81?fC-FZcr-Y~cijZuH=n*U$B=$!BWL;C+A z{r`~ue@Op7r2ik%{}1W^hxGqL`u`#Q|B(Lw|Byb%$2VHc)BmQY4}F^uK>t@yzfbt{ z=$jJofA;kM8X$P$N|NM`8k{;GA{B(J>p_h{q6vkJGI%VEOn1zTj7*9UY{bB+l5$FX zTuhQOZPh5`2x>(!F$f}3K`6G&S$g|pmq$nJsQJg1>=U@8)j=2KUULt3i%ySD;RfQp zLK`92EE^&3h0RP9V2%{b2DAby!7Q(s=rs&_+8Y*mt7}=2i0Q=ubf<2?;j?5$E9~^KK8bySwKpiOz+5E@34;6 zRx^6WS=ahZV%=J_*@?L4U4Hz05)z5YY0UW!QsJxNz zw{9x;#~&wn_D-BlsmMh&F?ew~mO`2}H3^lszqoR1f1=szI z`Lk<~y4lz(ic10kW1@{ml01i)ozETWW5YF|e6g^OxV7H-@NMeD`kVFW2m3VolVUF z-nB6SMuwPsnnYO#gY?A3@t<_XBHS(r!g(bw9amL;=C?2bR`)+fH4(1DBPbVvRYCGM zBjuU(>i_27)u7y)#(K!po!|+?iIzdWQ+uK8uk!NQ7_I3r#DABM3vfIEg7NrY(&)c_ z$c8~lZQcy=Dw|L|8V1=GyLI7;xI61*h5H7IGJerbsf}-WLNoZLe3G@u;VB&z>MAl& zW#D>c0Wqyhkj^)aRmwSYGQQUfFK76v$H8F?T<``yCwz zCKA$-?}AJ({mji9#O9jSp(;r-pv?f4f#mucM>xj?c|Z7;D59N{2lkb#z1`X;5^*iI z2kz;$Wp<43d2#^9k*lq5yMVS?=_wt5>~f&nYkz$vg1;qED2Ka&h9GP|tTGIQE7@HB zBxE74WerEaOQN)9Z@0eu z(ckn~ncRgp|Hu<`0)^KaFAuqxJ^gmEzx*4@;s8McC_$)WD=U=~+dAnry5q!5YwC8L z;$ME71fcswd8uX0=9+vjt=(GbGJh>L`t;XJvz+Q<5=_q+>+QDuEb$6JsX&y@uhB-@ z?>6-s#-l7WcWIOE9$q8rk$bOtB7Le!_i?t%+-Eid|fA6RtllBup|+~ z%LTI@j)%mat47}_A`qy-y~gp7cRKxLp(qaXH2(CSZJyY0Cal}o*dF_ z2S0r>uV4h7Rv4r|e>kz8p3YHFHvikDJ*p6LS&z+Rf9&Pcuq?%nZ+vdtsbK(H1MB9I zPi-TRj;yuyxj3oai|=DN-M)p(#wTPkLnzpJ7Uh!^sZOg&B^nShB|r+r1`a^bmBL=b zh}$c}gz>qTk&cdQ>yQ^Cxd)>dVP2<{*rk6BCc>U=?F}nIHVxmKj_VS-DYYg?v*Elv z-;0=ZetaGe2B6-4=)jJ}9u81n7RK3;4>cH_G$(MW*Ri!he!RMrRC?G^tL|f!kATCh z%r=q@csVPR%r4KXHxO+j-7y7n3skXca&K-kQi}?a?}{fWc?#jEGwBZ7HvCN}USON( zQ?THFsyl^V@iY*lR zusL7F1Hq1qvTdV52vEz%P^_)Ub#k2FNx-_srSHojfg~El6A-3gVb>(+gP!QLfb^zH z7>*%z;OgGg?%f>?cx(e=#l>#FCg{D{ux+*$g z9|04_5)-3vIp0-`59H_FCV~#cA+-!(sMtr)6dh8I4Gw1iuP|3L+UX`Ss~v zSdH7x524u#q2PT=^N))yuwi+V6J~=$70P2{#_2NYeY>!*fu^2dM~q;h4s9Hxfcalt z@RetOX`=J29(k7-M@`Y4k(deN@sxM~ZpF!591>v+$-??8kh3Nf6F@-(isoRt<^S53 zVmdm&8`vwWzdXgV3VG+>ec^cBz455EHaqC~;UTePR`=?CLAv6+ha27IpK35VYMS{C zCe8GHY6LT3qwbz$STO}$5e%ACJ%dfXXl!=FJ<7%m1VZ zH+JZY(NZ`7a9r=#EPb@x=Cin^$-$7FPD2%W*E`alkv#D2wJF<9=}x*yhTOr0<#aik zSv!z6iQ0^%^zX_*r!v2R6D33u@XIpaVT(eG*4@?s8VwYr@=Leinl!o#**X>_X7+ux zwRr2E{TKV2b42<$pT|%A7XAK_$SV0V!P)uqr^}3O46vD5@+B>rKM2_1@421!gmGK< z3=sDtGEK<7(ykDv?4RB#2N|K(ST|}O2I_#!*Kj_c8hl{A7_9Q%0 zM|7^kd$@>y|Ch$5aO?pFZU(GQd^|>FlT_qmJsGj)Wt2wJQm+$^IT%NpHAwa>UW^ zb=jepGHUO=F;MzuYuqe89gDcfRlQtyE^wB1EfbftKkYZlfVv)`9*F>Pe~D^6OjJ!p z2DUs_$1P@Pqlf|@YiJvkn#vYsX@8;wJIo&9*skXOMMsg`das1qk&O0bIVzd9_H?bu zzF6($!`@g58uv7k{W<=O)vkXw?&NxeaCb?lJdFf<;sEK~j~uJl>A_5dn_4)qTB({W zKuLmVa8S#p;zSCuLpn#k{}(-s4z<@5tGzjU@uq2UEC8O3wV;LX>du>w7*oA@AQ}~NT zY_jstiv`!snNu8Y*%$z|7yhvA_1#7q{cqvP%4W5Z?8AcTJHvDMCEU2)X6<3Pe(i+7 z7%}Nzm~y?n@5WG^*rXC*y3qZ_Tuo7O-Jqz;)5XmR32HfSk#SsD=8+E)C+N|K8y1m? zF`J-Aey7!bb z^x64>C0oJ=HLf%=J)Vk`GzCZ%Ogq{_9AM7!dp!(%TEE0R$V66 zxH7v!V+jOBrHJ8?4r%RX9Kq}@t7iavy%0X&!s7fzqV^Qn#g%%#r1`X?LtK#K;d5h- z@xl5X6A~uLfs7iYicBUx_7-g?N~0f9YUh=aKSIt_v%DVGm{IX&;W>=|Ycf0Id9Z<) z2{j=SF>c!LbB;7Cgn_R^%re!!k0iSH2=zwrB1$DYbkSnQD1ukVT5Ky;%82i&94>5+ z(Ua7yp3Ve*volqn08n&cX?KXVwbmG;t4I)+2~yq??n$N?or%dWibC&NvXm)(IdvL2 zYh_2FPii9H)Cvc4H=V`cBv+RdFI9ny5D|YTLUWCoPwfzu-6&Y&e2yO`;Ua@}n~bsD zzWpx)Pp|Rbx0WWS$)2ztNGr@EZ=~BC~ zN+uX4NIA=`ncue5%LAycXoqVA%kC_0W7-2{IJnV6qM_YME$pWu7#n*H7}{!DVJG+f zp=DSKyS7h|*`Xn-Jx%HCR_0%mKDe}Ecq{L7k58$Y> zmcOAR!&J=@i6ibY*Pvm95joplxIK^fL19F1;|6jsukt2FF@U}Vok4X6eSvL@6AsjjI0M7+B@%`!5 z+CGagjpF=Qo}vzrz%ZKa$)8W#-mQU%hyL`1ePnHcy}!uUn?wC_Jms_kNDVdc0H~-t zYQ=zXR{&x#1)CINK4n4>G)ic$K<%Of7ZK*_1gQ`|?GdHDg)_uOo(4dqCT&k0IKhIR z-Hac%#unb}Fk;gF^q0N%SN$|Y)iA(T#sqZlu(wt+kcfw+5K`sFDdcO@qK%2Up)gv+t8a*G)p?OlgZqLCT&ErR)n0;_uQ^-Ai}=X(9oHWHCMQ-WbLO*Xp+B zg~VkW@!7PMUlOpsN>Ykd8+wTXdwpklE(glU8&PN1fe69sN>~wUV&eV}QOmzLUw4Zu z-~k238x$EkB3SiWO8`M83ag(J0u_SeWtTa*R^?MiuZ!RJv>l+*-u?DJ_K3dc!SOML$sKavJT7i$cV=&CnRUm=`ZlQeo`w^iC~`=^l$4V- zA;#yT8(ky><8vT6$-l;)FWl#q{kS(tAAw?1H>(s4_?2f$7<5NSv;ih+-{fa0z zN~C+;${Xi|aQxMW0;Nc7+F4x_4qyts6?tmhNpmC};Yb(jqfl{{oZ#~>Ba&!RD%Eux z+Q-;L|JFNSd)@2n9;SpIC>oa2;fO~zaQOM8$2@2DkUWesh43>wNUr&b;-1jl6)J?{9_Wewg1<3Dk)o&Q8;){4{A={c7=oCM_Bi%~Yh9WQ`uqL=6vBquX z6|hi|LO4sL6fGY3TTJQ3kmS!zsY)oS-fRiDG%98@c^X(encMejK7fSstAk33*Tr;T9NR9PRn?gzlD7TqY72|@~zCD zvuL1*!y&Cm<AK!Lg3KW-iVcSW#*GuhLar zj#LYzBE5e}8WHd-qKcV9QgTDs_&#xmMe);(E!v+}Elh$588%pe^JHkN0J_bQk^>P= zC9Er$jL$)zcSED4cWYSYK78R z*a23#xm+UjzU%KTWq_|GLC-6>e~YNU(ch7L+uL5mXUH2fAjavb!er`(TnypRR_vC6 zrSnxTJ$9~~fZsOGy8ujiAH|J`V3ON6Q~Umd=5dO07YnE&9Jk_V7Kwn1upxQ*4`fDo zNO)PTZ0U1{#i}h}ECzyMkHWt}wC^UeL2OIgowB5h8Dx^Sqe30C+sDy?*L){SlzDDA zlb21IHUCS95m9wlGUIK^p*$JKODv308Y+MVxLC$0Bc5maHE2SGW-;@L6!C-@51r?y zFO2a=W;Tk+dYzSCY~<)Hkd!+qqu77r&+FVaW1q+xp#Yn)ROLjo@lq^L-EBa|hv)l{ zEdMJP4Sq(o9HP4#JX#;A={9lkciO=z9O(X12U>?K;I_~Rs;s(2BCXgb5a3iaTQn( zjMuw%l;TV9ep!MQ_I-Q>CK`+b+819oFNv|FmgXf5s7+0bC`I%J@%(Ai#ckdf?X#;f zIWV9}uk)FPSIm7Ofk9%D5Yo@#`OKvA&Q>R$4!F~)s_MB22^?J4L8fBArZ z-I)Gz3D%6!mUH@eCcBkH>4L1kd^72{R6VEY}HOcek8F>CMhT0TI&G=SJ@Oile~V! z2$Th`OYeYlW2qwL&E9jDausJbAmS3UG{yd>113R9Bf}yd?+&&agmoqXq*pYQgp9bsI+0-jHB!+uBFa2R-dU6&dlO#m zR3wcyEL#Opy!zkr90|{QVia?RwxYn4I%>YZ{rW=W?0zRL0IjHr-v>ee2zKa7gpLcJ z{o&&=+J}J(`C}SE%C-I2FM`?s%&4^rMcUw1cE^91QN4|=v6RY*&=2u|7lX+s$7GMy z(1bbfp{$v&i8&4^uEEhX?fPUQ7+>BE<-nFS$JC-P6m6yMfG)jot65?IaEJOi#A^ z*Kfb}A~0)$ey(+|z?>rr{##$~?3^{a=N_M(njTw$Wpm5_+EcOy+Dl$vz`la5ze2ZU zGyLcJndf#w(D3@|K47WRs2q#&gj~OOyA^SH$HYz4*%GSmgZ8Tzw|a@d@yhG-%SMs9RZjf1W%vtgOvh1vcE;a8{^!>V&k|t zmJwL3w4(RMz@B<70`rE*$5+SoALD#+-On1{W@87QC3DUYu8OYBF9~4k}81M@@wl*luw&@! zZgOUWB0=8WTq>)`HeIlBbHYXKjaQD*+gcqR=x!Ps`jd9^FAQPC6GFFRjexUfO)r1b zk6kbC#!;7rP;Ey72O7kH3ec!tHJag16#pZZsww05Iq&y&DQ1n7?uESi2)fi;ddz&g zeYX%|*c*Bnc*u5}Kqo6ZqQ)5Dxch4m#~sGL+`}3if+z%@A(f_T6S0%Y#dlnW{Fga!Kp*@^4oJH6;{}`}}B01iOO47s&`f*LG;7VOZ-iQG;|HB0UQ1@YFp3a^&PC%64Z(I;vRcNhcTEe{;<~cSL0rV2TaesFI zMf1!}*@WH+@0bDd% zflV05hrB==Vc&GHBPc&>67qqfQyxac1$d&cPg5|Vq-9xr3;qA{uMiI2x3l;EPwoTg zO$!A4FYbfBbD72ejr-uMK6l$?JwtDh@?KXiv)(+4k#b0b2a%~S^4y~!s4zdj7eiDM zGqr?rdmTpt1R8)F!899QFA8m*Qaez}dc7CEJfitF^(gf)vs!dtT;j0mu`aaXbDD`y zFXIStq_pBQMp|Ydz+mI0HO_C;)IGfDwW+U}1ouyWMDM zf;SoE9&{6e=>h>Dm|eaX2SIPLHxp7s6LdrXaXX!z+`th6Kr>*2U`5A3AVBo#a-az1 zP4;HuNEyLL2~b8Db$Yt?yvg27(7|sW0Pw{qLHt_~0Avi*6ZqxfjVRrkHjxW%GTYpG>Wy)!F{Pe@}FLQup)0vEdfk7wI@= zXI)089)cUY->rGb%gB{=@_vr&CkNcTz+bVf8Rp`Wkl>N*$2n@CBf0dqRaMomV5<$2 zVXGzTu;8uXYefpj1@Qev|BU~|mdbQ@4Ijl%JLIT^QfX%oIxt?(YVRS1Xi7BpSFZGv zOpO@5ypl}8BezStvK}(ZtQgBF_m@t(CdxD4C;?`Mf3CWFDCa& zXkb%*swCjcM_*4*lfn6FWSU;RAL3Q422@mTGDA2h;;VCC?LWHU&4hPv=x7gpJr&z4 zEQg+nJ$!sZ+i=a0xW-}b=ezD1>zllLTgoA=RS}5BMDaV&((;`}c$Jk=G71?RBM$1) z%NWNN8{{|?;0B8r-I48MMUXcASd*Ra?d?c=>K#A*x;k!z*6xr4LwGL64u|?nq^ie* zkr~LxeJIRx@ZP--sXhAeqpfSaMz@bjbXGj?+V3$b_df8+tquH zAcR=N2=knp>Q?5Zt6>Xn|bz&XCJ z{A3~xP2q|WS8KO@JL}*$za;^`PTK6Sv+NYro!52X6anO1cDrtw`I7_E<*xZU*OqVf z@g=9p_-*_Yfk%2F5`cSN_)6#^*zE{nWV1rT#)KRk!gADxYe#oeCIM7QFXLOz0R&0e zSHqt?Rv(*S5Phu?N=8xfJTNrg{68hIO^V=rDiAFyZLmx8nZWx&{T>B*k^;RL~A|4#Oq@85YY1Gr@|7PAP}6uVS!&Tn- z_kU4Ze`Lew&It&`FJy;@_z(LfgUC}Aw5QugQf6DE8y;~EBp$O=G>)z!lbRcJv0dJsX zxX)!)8s$vL0V6wYZ!BJJbky7u<&v&v@MZn?S9H0=ci9-RvPc4fIksRw^23OyG|Q8T%LUMb^~9jI z)>BDr20Im_X)v1QojsdP`}w4?4F3axzxj|hz(84^RPM#SmGabb<|^*j%6o&PN}XM_ zr9{a`=@xQTZWTY~1=&L~$^e+~@n0rL!1muQ7UBNp;kNyQ?o=FlV|mJfNUvs?Z|Z8} z@WA@xb3&)Xn0>Y$-(Gg{(-ZPLuO*gb4gaMf0@nsb!CGrR026v#OX`KPO@>t!HSRy+ z{=Vq-QniRDn+QAx1}?Q}#VJl$JJ!9P_pVe`&vHg4k>sgTUj>o67LT*F;Dh{)Ga3uP zFsfh}r(z@xB$pitON;fFwGNu}**tw=)R2-1t_A?Ac1PFLHTj4_K8A>qlPM8|VM+nx zP5BfAMi?6dEvWQ$ev#uat7RtXYLjWD~(JxLGD~+ z?y#n4WE?3~c%iL0_1kLQZ_mQ(xrI zueBPNXZxNpeu0nM1cz3@H+0{8YI9LyqmH@ylCH_JQA=NtE9iwOlD6vPyIK%e#r z4FNSmj&yPV*7W<66vOZw0!5d~Bdpg^bloUvw>xDNgpx`yh)%bc$391}`pa^zkk|FC zng>=IKEN34Th))K*Al<+@D$QstE^_MsTz!A8L3izw@n@Bv4Av~B2rxDK2q zXNBCLr^vlPtYM%UQ*e3qD0{2f#MXI=kN$E8fq4{eUSK5j6f*Q7HZd@YX6awZ*x?my z0PzR!cR~fT@;K+m;_2|fP-PeGQ}tk6g}wE(>*z($Y6Q33iKu=TrhnH2$canD3BaMi z3QiR#s|s7o&3gEg$9nVgYJvz3@y-C{{3D>>cou%Nao^XHM&?4`+TAI#l03d&dP`+b z!@KE$E+Zu>M_nN|9TaJQGkjD)bNV)`Z-()|MSWXR7^>*1KK}a2K|VHC+w*G(g^pkE z!T#+%qrEmVDFjB<%NDMel;uW3w){7emL-=)+NJd^vd=pLN=VcP_u$-UUF2{#t(FC^oWH zsLAz-!`+e2Dfn$@c8i2fipYa*%&d}VgF27ekTZM2cHTdP;yv3M$0A54T&HH@W2`3#(9a+#2#HX>yAxwk@$c=Wz=2BOU>otf75O1F* zN&yMVtgUY;0v13xF+(X+Sb-iXHQ!A>N~8S)09()q$7k`y9Si^p4{Wu}ovjJ1bJp&k zn!?=|WKu5;CJ->O5qpwC>Qzv^z!gg;ZI=6;E(3{*+3!0Vfj+?B)uR+Wa4D{e0Rvmp}<0H-cN}FI6`7FD{cT+@)-nt_xh81 zKlpdPN97eoB9ua$KDpJ(*cr%)VqQ6^(p7rtMJviBl~)FtQoco*@_CJ7f&zffiQocL zwp(MYgD3`bliuDphcDdQK|!#f5s)qHh@QBPo5xTbD~8~_DhP1ahf=KoG@$&Ue+XMO zLbXO>+P5U`d5*jC^8wUr)4!U}95l7HtI`9(x`4Ey*YsVt?e1@O{}RzfYF?Cr%Y{sz#s9GF{e zj;1pR0R7P7e+srj)hHxJ^e#-R*=}z37T6E<@vUTlokRd4{T3{$9`p(gC^p~hxVhSP z92-w9Bt@0VGI0f#ZVV?1R1crBL4x0Yd0iB&Qy>0F4OafM^&n6V4QJn;4K&oIugV)^ zB~MYw|7oXR7sM`BtD?d4Z!KMrh^*5}mx4IpS2tyYDDNddC6LuZ-iZoatDIAchPC|; zn0Z0r)7}mo)H5v*yKJr8Omi!goV=%YjslX}=qReTX^o*rzp}E>JikCpfuA zPxnLiMW;A+bbIt88hJ=Ih-uNk*=fWQh`oH`yLDB;JeW6?RWkvNa5aI(l{r>U{>@Yp zT0V`9qzky&nXJz|3{NnRsK%}U94MU2(AR8Sz5SO9S30k-fx#h(kRYV9UnlV*3F&tn zM^8Q9L~bD^&QYYLB0DU`9t_J*+F6=Uxumz%8GPkTLp22CfiGmRAKK%6DlI~b_{hpb z@lfu*BgQkrfX*g&&Gp=olw5z*eW02Va^++qg8)$lpl1b?M=s6gb=c~tz^M`i2ufQ_ zHqY-a7)Tu(TA!(GhJD{0@Zf>YzKVqQqHrBTwDTPm?Zt9s&DmivMuP_cNhL3|MvW2& zI+yO73XYV^)J~=}xPfnrNbc$fo;Hp#X-!KMOM`1tUURe^6(8Q|hArd3J6X|)08DTK zVA&VucbI48@zVle)EPi704ctcrJM!!M}H`LveEP3rt&u27{Y4impf(n+rI4`NIdwt z?8#hqM0KPs^>keruNim1H5v6(1AoT>712tw;dA?K?KvD&QkV_OxUGQ<(D|0S6Ax$= z*=*X_KE~a#ODQsi=bn>GJ;oRk>xX~o3LX1yrt)xuaktiKSAN#p6@a)z22q33qoYMD zyy3Ci3nE;;oB$NDfu+}-7+gSwh&T`Pgs(nw6L11H&+i?ybUprsqC?aMQ0Td_gfHHW zIE9b_@GDqPkO~P=x0Fpx)Ool5B*EwmfVrh|vNtqt8?^BOMqEHNL(O~7v>d=I^DR!S zoz%>eWZ)kEhs?#PuI6A6s}t_%L@Jwc=x2%0j|9&0MJc?%Y_3|MrBnS5N0?M zCmxVT1aB!xMl)_boW7QsG6cYC9R^mMm-lDCFZ!8bl(&3TH_I(bo2l9oc<6G;_>Dqa zm?tkyXRSD&+RRl|s;9wQLW0}JqW)#~)K&PR6x)dzV*KXak^cX~=B7j`%slrJDxk#8Mif2O-N#C+%crGPjtO3+COtXK-V-Chmxk4$YT zVgkm!;!=lZQ6E^H+ID#G&v|Sv)ao~meap|z1$Bz)q+aKuS_$e#FC>q$Xqg`rYnaaT z(^s-GrxSBw0SN3t{09KI@r^(por2vjQDO@nR|(Jv!+L?`zvAGQCs9HGM@oOZc<#n% z-~B#Sl>)1?(wNG&X1!xw8yVDv0a!G*{a)B9QJIw_`Ch;d)8&IjBwo1fX2f9z6T5F; z-#C{(ti{a6IWw*QqwGe1&%+X8s9G-4!Y}4u7hWOng0V)AvqCERJ!WOX;>O_77- zb#~I?zflrWe7cq&yAuHdP4kd!a?83Y8DkWP<7Qb#X~9Rp{um zqkY57^leogk1j*Y2)ttVaSjHF zhW5h8MF4R_z+bH-hSJ3T;P0?6oHvOO#`(;J0swJxXs;cPW_fmt?9NMCkvQpSp+|4~ z;k{}=Fhe>VVqS&>U;|bF)vK?ezJi{y7Y4WVW6Xr)7!sj;Pvy5!`FI-+M@WeD7MT`D z>We`tmj@q(2Q4k9ZB0J4Vh{szh_g*@8;zt06u>Yeope&>b?@p&bOe4@0JHQ@>}b;? zGJ(pp3x#JCH$eGh$~VURb|7a7kcy!A}|(AC|r3I$0!UI0W_?p zOVu`{q}(!jPY71#N-9j(%dL9IHU4~=eA=wVTFC}S3}nt^lkVxBp-1#JBoj+fVq+%` zNIr}e$W$4rv0SL{`J&whu)uS*z7d88?;kIPX4(*L!%yHuvrD?qY?j|oOrWA}kL6~5 zbK`5gqPgM%tGMByt3~?jq1E_^nCts7`_^#b@c)P^7ROGtX$4DPG$+FpCsKj8?Mswykbo8yBq>^PFQvY)w`jCjU=V-5&kS~Ld4$&~0 zEOF7r^g<7_OQtTz^tD^#Zim#iiuyl_)0f7U^KSg#59Gy1UyKWg5IA&noxV^1&7K|~ z5&Kd#*oJzLr%)*qd6QMnw7(wd0xyzZ zc^WHLhAmokFZP?JN&%S8Z7>*+8l)PK!l?|&0~!2ELdtF~(h}vb(iEPK<;L=W{K#9E z5avb|y2Z0m7Nz&O%n+sZ_t%PFf4MuL5sMd%!wORRK@CFWMWICv)_iPm#JYPN^nIs* z#&Amr%%1pQi_iT<1O|~h8L1*+)yPyJ$Xe9*VqN>ghb!h`MBZFvfKsFxxG2!^qLBRQ z)$*3I>Wt324_C{#_gJO0>eAKy5(Le+b}X*aILi12B##X!R@8 z@n~-oG0lJp_tA0mQn!Z?K)b*p`fbQVt0^fJxr3}yYZ?}nIYz3hR z&+7zZ#=`wDs_xgbBF%G2OIdrB6zK|D@#;pB_(r^Yi7?!rMWGan!BQ%g4C z9H-|6q`n31@(FCZts?@>IKVkKJ3!UuYIjFU?~)uU_G9X5DKq76A0ZN!ljMWqyhU)` zEI!>vCST|u@id$qWi$61@rP!3_C?nFuEu2B*$cEOdQyLimzXZdo*Z}bglWiQ!mp!D zN63K5?Zq;NJ?C{J^EyyxWiS&Yabk^Hx-uI#%#GAx7Jp?cRIfCN>Rz^JVq6==O`U&{ zp+k#&g8Nc_;~mjbA#qEAg!&?8CR0;%C#xuCnqJ1}wllm`oE}A6M970kLfO>x-6Y;>NexU7?~XRQpekM_xV07wacIYHL3yXi@Se|3YX=@5hUwmihK&&EG_k zfgWQ0>6)!aJ^j)}`q*pr1)V1(K!6yOsYU`q{ERVv7P7nlBO`5;1a*>MEN;|lSu|YjB%(uT`roJHugSd?o%{$|d*jqyo?acc=6nbr#)Q7`0vgM! z*(sm+JY64--gdD7v2Q+;ds|ms=ax>_cFfd_T^+ITRGs|(h_NlJ*9ndYh8V}`1&rq+ zuMhHx%P*V7<;jmFzDQrG&!cp=v{Ao(6=&|m4PEg7vAkcbRoiHDJK~0C;sBfplKvii z0Di;QMw2M`Bt`t4QOV`Le?L2~*+uq;U$f$VaR%Q0KTeI5iOd?d6({Q5_g*tqV6_|T z^E&n%nITgpjiCSzvHYonHd|LQ?l~r%h>#{Bm*IhE;;OOIIha)gP>sBjbM5)@Vzlj1 zCL~Fjy{qgBoKHZ@SI_oxxV+8NkZ}5I4%!qR3vQq`<>5oYPY}I3o-!8!nw|Ah7p}@A znmYhwO{L5FLl~4$WbzGdK*pFG)Oi)r1yrv-Uiru$^g58&1tmS5)RhGOXtJyzabdbH zCN24;3wt|c1pa{a*;qi3yvryF+0_ydh&kr_XibZK;pNj zr8F}LKzo^kKBgYVb&Dw3CniB0+`=?<6O+K0_k&VqgXo^pL+MBTVc|DF#+n+PEqifx zNBR11ZW<(8sK7Dp3~u$E5D2o>OJd;G7eTJ%`y|F!rL@jSgl%Da_eF{EOGieML+oN0 zo(0iN(j*anxKP;dE%rCaUs@*F5>GK*3o_$qaKx88?yBcvMA9KvTr5;Ej9BQay{$pB z0Ffd}#eMRXhB~E@766ErkeM$dWFbG1;x`S$pxu%J z6caMJ!LDSwIQa-#oOcKHy!BB14@Mc@_QN_lj+^dqf5fE_@u#%#=KFP=rSF|yNp zi~>W=f)U7p%BsXWgs&7paeQU#yPZxeZKtJoD665K53_$WXJ=5Zjx!!J*H!zrt*T8G zZU4m86*!pl!FqX6=Lln%23_!TD+Z>KQomNB6e^{63s$~5elhaT<24UCE6^EZkGOlH z|J_s0szw|&;WPEziwvp~aV<@DFzf9i7KysJe+jSb+(|Uzo&DSkryzr`dhsqGy#%J{ z4;nQknoVj|n#6CrBq*UpC)E%H;QpGRDxiI_DJ4(L8f}?vf9d+A;y~h9|r@re3Ro}LKY%_v2wG9%1>*0`H9x`()xD4E<`?~-)F4154Jpf~Z zG$J4}5O#WD7&8j2IMy_SxO8LN+$ibGj!A~y8A%MZj}5I2i=e?MAw2G{&;M?niGA@F z3BvAvn)v6U(XB8qMz-4h#dD!_Hx-(LW!6h@xKR9#RCNSJbnGRN#VDZQz?aViqH{LS?l`r!*FdcPv^^Hp9=ka{!gu7 zhqrObvY%LCRbXy3;P`BwRH<7$98WX$mo>ggKz#v80H;n7ed#@C@>FgRiJy(O`v6*3 z&-?p%sXKQSb|H#4#C!Hl`cr4wTAe=d0CNIW@-7Gi2=MjwaucxZexH5)8NZq{z?e!( zSzKPf$nc?RYk)}DN$WNDn#XGwrO8V_n^6_;XGV>Zwf`Q$ggF%`{vgO_hcE;f|A5f{ zSB`U-QYa(vT7nkU1u<0ph7(*?IAj`H_hiQM8eQe>r=uH=0ZI`{8&FI_n!0Ud5BVew zd5A7wm&CEMaoPnTD2`yPcQfP9UY`5%i2`5%gkcNj_Hyq!#q4(~BN(vRguT2_}ou(z&r z9IPV&*Ed)i*$#744|Y6xW`s0T4A8^dbn-Nfq-x3J)s)5Cz1^*pyAuhhs_ndq6b5Hn zv5%W$1^SS*+rzo2zRw!!)x5Oe*&u_q0+#-irHE`{^oP4X%6H`P2ytL|*=1c14X&Nv z7hFIJ+=_|ko+~qyvn;2;F`m|wrcda0^$`jVHS%goUap$c*gL1R%@*``O0MeSkdjFf z@*$~8E(6lctfn8-87^4)`>uwksl_nH$n}TUK02e@POUZx8h(=)kYQK&tRhU!-CD=Y zzAU#bzT#>eH}_HQNPY_5kNO`6;n=<;Pw26gH}dvXj&)q}@%#OuRo@`J){D>RBQ##p zubZgbNNoXd95vB9-5@0v4Re*+#*mAweg-QoVR2*4}2#T zs6qh#D1{3Gtd<)4oqrg3wI#~sGD-mE>K7}F%yt055q#`#RH(| z_L!p*s&ld`-4ys`Wzgn`l*(IL1yv;nyda;4qL0<0_x;c}vQb;0^|z&<;e2tGr098i zx?&QH@<7kWv%-HMj;=lbX)7yX7TP&wfuh z-EBdFnMvi6pT0j!2aTf(!FOyozZtE=+wZfo-fR;}9g?=dkL;2Tiw*|zbx$&B^Y(X9 z`X~vmKNwDNH6vpwfs~I_aq!dasgEkL$^Jrb0UE~`(@l*1*c>2CwHf|zrn;cQPT}GX zs+_$MG)37R(;jR!^|*G3Y)Yl!WRu_?%#|?VViJ^Iy%Q5Jj!7PV*DB}og2H-Qe(DlY z1ctSek(r`aCPg=egp39->c^X^npvujfiU9|M8Fc#O=t6d2Hl1ba9JO8pDy_&=H`iQL3uarOzGORn0toG zktq_eJ^CB(J+|mRbVD7xJ0kGm$zpOfG!*CZOXWwp$739k7oy3&T{te5bX`o1As;S0 z3=^zXC{hpt-Sxj`tNlS(Ln$UHp|+$1OcJ><@ZndAygmAqPt4*)Y%$U2BkF?qJ8K-> zEDtP4x!Y6~62QKM`y=s^bcy(aoeZ80{fHO#n)39`mLf?@CPEI>>}zNzcCTe2)}Ije ze;5cRwJ&>w(ZKLRBkVtoWSOW*r)x>7p|g#Dy%q_I5UfbJi)rv7&=TxjB2{hIf8%R| z*k5Nu>w)Bs+CQY47s0W5K4K){hy&lq#|yr5d}&}3@#7cW3hGyBTe@`=tN?@+g)cn@ zy^d4p6Fu*}<-?x-ad3%|Z>iR4*6 z{e5yR>TS{!l3fCbOjS$iaJa!pK%vhcq4d!4KlUz_h*|uGH5^N;^ktjvpgoOeG(&O0dws!&!rgdAR{#$IQT%;rjoTt15Hu- zu}evja!IR;E;3NKZjHRqwfPMZ5NUf92+4>L3Cf`&wIhbVh-4*c=lEa%(@vr$0e}_56P22B+qCx*KnUy3KYX#Y^ zqoIRAAQBd)sw0!^K@ouKfNA#jG+BD4MrUNN_5nscQ3zqC@HN=g0Rf(lYMU-A$kGYu z?~PhdT?@nh?98h)j=)Uz{MkC;W5Ncxp%@Ok%YMbhLcPwkdH=*bG_9GXVnZjjFhlOJ z^SeD3bK3jsqb8qRHB#p+wVAPvyy5+#|E`k^?3q6!w!$^piSZ?_q%as+(B|oF21p1M zED2y@XW#xBWhEe{*bk^*$B|pI8x9L~kENmIQl^mnfN#TX#e(Ruj6y$7;?oS(bR@{& zvKEEU2xz^q5}}lQlKWFKw_#nrRsEUO{!8`b)nm0mg#Q+`Mz;hLr+veRNnrbNk#Hd{ zRK&EW3SdZ7SudOYg4)@_jQ_PkjdP(Ikgm(_TpA1AR_s;ynhFNKt{hN3xMwJzHMTQ?^xtRkC{W1A6@0A^|lXHj+?W+L%HiDsS;8R=cR& z#=9&*g}n;#74i@x_>Evi+m+CdhrI+F>_E&n*cfG?f&)-UB9Yl3PU0^^W>$rn*mM*y zxQ$GMZP!GL)q<#~-UomjW_QgN=(}+->tK^l5-b=2*CdP+wXAKzX~K{%SE+Sm8~_C4 z>a$1#NH+_YAkv;Mhb~-}2Qe#Tyozut&I2u6^|+sk7OEm? z7!ad@Z#CtNnbMpL0Dg|m;H%$ibYQbCT&ifGZX%mrzSu} zh$!ezidOYkY8@@#`-!!PXa{VS5^W`-cl03mcIm`ZlGC^GAq#|+BNXKM=QI~Zw<6zY z*GG4;oDqNsXze;@tKz@pOyE9uFI#RD#x!PHK^Z)iKzxzjPcYrt}snYA#a;|2E+D2C4nxAQ| zB<81oF}>|HGjr<(0`%S#p4~9Xh09BzPOQ=sZT=YF{W3Axx&$m>AXjn}(h-0)IJ$RZ zE{)Zkp|@|+)$D!~C}MTK5@3*)q&Y_Ui^2i&4&k$5$bVb1=xMN$EU8vCk@N1KS4)F4 zDPk8o5yJ1>3h}oqpXL(o0?VpLO?cnV7aa@++VpTVFZOEU2XD>&f_}X`&P=JY9}=|s zKXpS`zOUu~J}aeEuEy8AT*#`d!Yx9L6P%Lutsy(_Yf8mlFHVk)d3U?tPfGEc<@lJQ zB~#iPSzCdu_+#Y!?g2HAY9y9sf|QM0y%<~|D=859drT5qg1S-y`hH!7(K*+}!TLyu zx)^%tX(3T*KY4QopwBl6kYTUWWjCBBXKhwX?W0$|jR#v7HQh-%_@0E~DU zJ&Ku&`&--Ja*URw2-iZ@KJ7Rp3NMxSnXU2U+aE-t*4BSRq*Zdi6C@)psL5Tco}WF4 z3TqglzsD|oY#owm6#zeNsb?S~B>s2IeqL)?D&h!!+-Vzc4g@2&20b|Xp@&cXt)W2R z&cKYH>7_43pjmP>+I1KCv;3(b?@-uspe*>qHoV_UCGtkyiol6+Q}HYOY2fQg znR|aw(iPtX!mawA9pB4W+Z1f1? z&_4M^eXH>z;aA=KzCzw|>VADAzR(ibR_9!zaj9tA4k|}85|60Np~g^o^O=2J)*E5> z<<~0fN&sNDpT^$mrmbuo7*z|vtY8O9#^Cdm`@ieNt(MSNRO7P#)XQt~7ioGidqy{W zV&rI{+D?17i2{32PWI*V^*!>U8NrbdAAED1Vu&b8njM~6r2+$hC0$+gf!w$Jm|EKg zJqm#TQIRYK+dtG-(}BhiQusKd=2%lk_K$4b&)@L8en3agJcJ*oKMra{V{tvrs(l)| zk5sEnNypXhR+5VOr+uXhD3thz{@NFBoyUW)V1TCWmDk(yuOUW!q4y{I$7N6M1hCa@a3i7|$_zAH~c_9AI(IFsb|1 z(U5S;IcVnK_l>1c+3Yq)Ve*QHyK9fV4aEg<5c}qvYHA3^IyJtm z|K%~ylnO5?8o)VE+Vs<%1=N8d8(F!-l?w2jSOQ?J^k?! zo>SK_S8`o_h;hf3qQOQ2fJW>XBE&kp{uF~-sxLp^QA)qw(Yi3SZ(uDal%yo}S)p_u zA9!!Q6uCb1v+s0pRzqv2SpGy!T}68P69@#JqKcugljK8^{yAvm&TtD2ULT^%YZb*# z8Vj5|i-}2UiL?UXGcJ7a@2;cF9ns4mU!n`VUSIqWe)d66n!WT53TZ||=>;V2zED}U zm_7!Z&o$N>`gfaKC{)Tfd)SwM>!S!gl*S9sQ%mNZs+a*@fDi;x8r#KYhgbpz_Ko;2 zLiTKFG^?g^6R`BYP?uePU!2dwTlW7U+{HgpWrf8oxMLpi4wZ2xR||myYTYSJ0CFK2 zulgElEaJU!m9+6sBQs;vSvvT}WJ`t27wVQjNz{T(*#E}fw=$UvMHXLQqb~-72n^HRQHdjI2ba3%+fuhEtYYf^ zglm4C^4Q3(stZESO8%1XP7z>7pjzHpmsnnsRC#Iv<)x@bwTRzsNoKjTdPg%Ml%eoF z#ywEEc9*sYCF#otCUjNoRoPd|Vk7Mz98zv`g1^II2@RfdS@rq4@I3|=Y-B*AZZWDm?9}>4B>KTH-&u-zYMs7?PQWM$ z44v|2l=~sS9zo_WkX&(W7<5XJz(8FvGITem)DGZ8r)hZ5M0c^3wyGo;gI%HGAl!lS z*L)QZ$|_mRq2SDpI)wcbTvgN(F-gZGYDA{e2T$C3ak)gv!gFmDS0io~N3-QF%o8M$ zpth&VDFsbFo7JY6Z>IEs@pP*cc2p590Kr00a(cmi4&5|Atvk>amH(+q`g(uQv62s_ zWIVL$gE=aI+koxQMPqK{;YV}^#m`4`K|B1Wqfo4o4$-F&)$q9y!|`>Ogw`D8`aBu% zZ@RCSN#(bqP#}yQ-tP!AZ*|#xmOw-u66O71vsjG)3^2XuR7+k5BGRM>o%Xa#GBl16 zBy$TGsFq(+1RiWq%6bcz&O10t@Cd$5APpDOL-Rpb_0Hp>7q825N0C0ME7b^IU5=sx zOSeg<##^q0TeOgow>yK~_V|MgvESd6F`KfB=)=hVB22=Q$Q%*@Dmo$%kU&TUI{@Of zD#HN zc{dQm0qd?B9&n5*F&F8l*3&vbS7=^dC zuKo#|jp$7CW6Wq`ENe8$6cT(oh9<%gDQM^@%Ozr-k(7{+5*jqd!WKTx#vHY%3ku|y%#G_?B&{gDRCC6WsM1l8Ls z?~D4gzMWb+2W?Ng#9^V(Yj9ELU>zsvD-eWQLG*f1 zeOrp~8gS?%pjdVEL&k;dk z`Bg+8vg(YEK+;PLPL%0WvNx&=%2rR9gXibiRaJu<=x;iEOe>gQ0?@mQou~BLM$;@% zBNA|L@vH0mbV4yEZ5mE?t*6XH>ZgDa`o7=v#9F@YEVUDtT|Gl>dZ~NdVXya_H+VvD zOly840jMULhWoRRaVpe(T*rJcp$e7dZyz1C@d4=l=fD&I#E)9)5vgWjEuB_ym8nJT z-<&CP*wz4#00hyY`D&k(uiP4*-`ezNhCZ~?3IVwOfx~b;OHh_iMdSVgIy}G6 zpz-DrxIwpUKiQp*QWHg_wdC{w#MaLNW3t%*s=8TtL}wTsDdd&K>g7Xj|3wy8w--g_ z1&}8Q6LKynd-KVxu9_K;nuQlk4sNIKYwD2;b27y$^wC0!py#B;p&G{d?#i!L=2Lp> zN0i>(E_`{q@>!hkEPQ}aLiXYu>iHqJ|dq%7T zjvtN4&6vgb6>%W|DHjxjP|L&=V?bJ#nr8wDsH`kT3ijLg_APBIwrBcEa z#?Zgt%+N?-ubp31-CEuSZ{$pak;6htw8ga0clh*pU=cA4G)$(^}J`1aA?( zRgkv4=GJ8)jB`FUp_I$}NUp&kqi1s#;iyK9M|WvS-*`wj^|()5pHz+Yo55yeM;$Xt z5*M2AuB^AV7Fk=kJ$f<>2}{?QbCVj-gpYN9fyV^iod*#MO>3ZX@7zLL~le=bViO=p79D@uXQVj>7Fae5b=fgwWVboie zh%3S`7fUOoB1a<0Am0N#$eSHWf$Tnmi_Mn!hwf4^z@$O~Sx7xkZOQm9BsvZP(x9?E zgp6Wt#oik}sd*sywCmm^M!IA6<8sMCvjZtm^<;lBbr+JN^r!pXXO&ohivFPKd%}+~ zZ5z-y0ow{MyoDuE@o+sKLjP^blLZPh0NBrHx5t9ZO!1S*Wz(vhG!hd-mws%}em0SD zF{{A?vI2yIG)3a>XUhqV?hHV{DFF~obl|cif;m2KO?QPH#1LrFMOtn2#$^9^GDw~y z?@#0Ch-Zy58rN%j6sWj~-n{Z8O4gf(5oab%kPN*U4-wZFuae4iMBu|ES*zF4{!NLu z4G12a8ZYrp%sm-HAI3#{m(i4S8vt*9;Vm6PSuo<@z5aMn3;wGiDLDzdj&0f^%i>ft zN%hov0N3wv%JeDJ$VL@_wIZPk0+j+pT(uW-KcYHBmEiNVGO;T#y%*>CuX`w$$5UER zx;Wm+&KYhzo=xc~9_U00azyqDM*~z(e=79yO6Owt=MXwEa2x;_J1h^Ru{YI}+~PLo zQbZtt#JgAT!xiwf_Ko2mfS#n>*i25k9MADc$zvy!MC_Mwi7jm$UF|g(8y+BhJo9QF-UlCTyU(KG3`a3Tpb)&D<@qiOz#vq*h@7IpN*fh7Vx}Jm z$nUaH%8!I7M8Qvvh_g0X$qLZzmvTkXyJ$rgE)M`3>|ay!^Z+|_gyEs5&Cc0yH)a4R z>2Sixnm64p1GystHY6`@XDhyPZLX_FkH44$12ptH4OfI3gpy~fpDF%P7d~bF9u|*} zfYJP%`x&IkL&6U`cRo7wxvNNK!xB!(sXax<11#v=}_IlhIVy@Z@ z$;|E8Z4T!;BYkE1CknAJ^7H*+XkPhSk)Uom4x7io(b;PMty;A=)AA$`4|ptfh8%f^ z+b%1U?ng^59FaWL|BBoQqVfu4r0ifV^W03~-sYeoD%AL=4Ozxt3|-z0gJ=GO8z|*r zxk7PsLoxu=Uu$4nX&#x({Yagcos$=L&=P<$faglEoAY%aFJ|r?;4g(!?u-sY<-POf zow|mSl$mY1A9C3;0$*!<5}4Cq@6S2u?j1l{KaA&U(Kz@9g}n%DznB4>beOZ002Cif zPQaP&m#3qb73!B^Y-%tL&?%bQhi3K_kqPDfw)sgD5-E1fL#6>5>YZQD2LOJrvDc=; z^pF0gp6SC#&z+-CK1GA+Z|45`i|qOq1U14x{+2Q&S?sFQ`OhXBM9L5*1JB;r`}0a? ztLXPtfo941{u}%p91`G(4c8)3=|$|ZlxDPJlWvoeFbbvTQ?B^7_E88`v)6wc%FKYl zb@a)Rqp8&`9x%2t00aE1-(>fxpEv?{erivw%?n#&is{qb96T@Y{B$2uOo7j3$ZXi- zs2ng%Hh4gNJ)+z^%<503e$sB``#4#?LwHL&`qJ_9+y*QdJxS2=B4$LS<9aZthzXIQ z;&B#%$QO}CC3i+@WhAo&Gg}adxR>lCdsm^}o|Yg75`BsNcm>zpc`*f{(Z!=gS{?BIXnv?=kGNo&#koFYYco0jA$-6vo142+uK zH)vpZhV$k*A+{0#w*`&FIyhPPMjI-|mi)jE!$~Jk!}!LFQ+|E`Y|IvbWbG!<%H|Jf zd(sIc)&eFt_}w@*WU*RLk_7J|B~L}QZw3lRGdAmPz4V_DUjW{=h!K(gagL6gWVuIA z)I1`k@}O6q#@$pzHZ(X3V+!4ryPvDSifj#~YyWc_lYcj)0l-XrfYwyIJgiPHQozkv z)d{B-7UXrb>(j2fI8*%&!vT$*su79iYX(KKU&@!adzfLW4?sfdM zgICpnnFz@Gi50sKa!knZKC@{m+&hC;_PxI`Uf_zi7M|~y5@_}PK*ork^QqsTL-qYT zvzg3lj9BVvKR-~XSskpf8uze4XS7!K?~`Cg)K>ZJTNsu($59}0t1hDkYy zGX8gl?x7F4my~2~r=!>etXh7k?N>|7<5NcOzdxMdeT1jAWaAKn*BHdO?rfU2%Wtyz z{}Gf+__e-t#P)Lnip9}7$V;A5YnJodkN-A)(D0i(vj2KybTcb64t#C;|;$shOh<>w}8i0H1D_T6_KZsgjW`-RMdu*Z4E8DnR|O_djlPkv>&y<$zt+EKlfX{70Qv-(g5Vmc~eBSmJ1>`)}uBUMS+ z?Tw-`cbEegjJw6X)qlQlX#Xkt3}Db8m9x3-++HkFLf3DxJ7qF$#xG2wS8a; zWfgmDNZ3@r;Uw;j;FR zejUrfMg)?!*cAshx){g&=q!dofdBY$v8L(16pGSFbhynHCI)>AtXqi*2AS8#u_#%G zSxkkdaRe=RXWx807#lQ5;yY@yz~JVo5w#KrzrQ^5s<_W*xrZYX9+=gl5Mt)SS`0a= z&OtsR;r;q~Cu_RspADfx=$q{RWI}8($f7iX1-u;(z@{Oj%(+|nhcP-PY_aUOzZrQY zcJr%dmletAQFrOg^n$}>RR9CPM?rA9Jw{sXz+t8Gm;5|$ZC&&Fpx~cOut1O@WCA&H zwFd$9nxR&(`6F2@(z5AxPq95MYsb3xWk@SMYsTn&6>FcuwOLon7cZu(dtbDRwuQi? zWZZEtgHyp)J`ntY^e^CBAIERZ;WyCfds9~|`t=C4Y@Y_l!OIIBjAL;4@TDUq2vNSP zAol(KMb&QT<|cjcp)l{({(w#FA1EQ>+a$3|c{n19RT+>c&*t-XcVMnVG z5jN{NsFIUJv7JD_ZjJ=#k{-LhWSNg*MtTY` zTv^Vd0VKlO-XEZ6&(vFuuxMHyMmQPlI0=$8Q`J(8cCt%gf&wwY6AfF_Z_`yPhqd8j?P;^y$s_ zN4Kuqs68iavNt6--nxw^Wg2HmFe?3|tsB{Rt){i{r|hz>jD)puCLaPGFMQQw!q ztO-u$sMQ;8Dyw&zT#jv*%0UCK{J`H}d@+tON)P(=@mIGZ_pk4ayvN4;N-^Et248Ac z*wC(You=|zoKJsMFSLG6_IRx2p%v}%*|^?Wc*&?5D@CBZDG>DjeN$3*j9&uM;@!Od zaZ-qwdinjSHFpd03YM096hzlVZi!^@n}01*R?L0NL|Y*k&mKz(jlZ!$z%Q|b@Tw+L z8nV#e1F{FHKOR2R+_!La4Rj0zum-|PK}_0yN0~_jo<=k09L%u*ggJJY-JflIcxp-i z*bD-t*uw&!UT`2GEcu-wheOs2b{H+W5I1l=V{REr9N(6--yaS8G^>4W^V2Fn9Tsh` z@M$m7_Bqnz!(sGS!$}G#HQ4ca*!L;rz=ELwK?G3GngTkimA17JNu%^#4r@?5FUTGO zwZa^}OQew1Sa>t8&1O$^oKJj>=lN!KkQBa3)(5|SyqpM8b= z%8(+j_O%)TV>t))Wj^z9>1E2_J)?+Fv$&3YE^Usw?qm(tW34|N4WiHh$yB`CYGXvE z9lG;6_-lD%x7aJ&!HsZ{=Ck*jppT%#8yqHOn2#-`_rVsTR$m91SD-vB_BYB*F`77LvO9gZnsy_1tx0{{g0j|c!NGW_G*ee(8y-z(|< ze%}zu7=MPKZOD8b&41-k%^;#hKaQY6l_L}3Ld|Lt)(j%jtX&=v zSATv-TVikSc62bNB4_?@H2una+2d-_tDG_%4IuzVMTLqA{}`iQ*>YB4!)E)RrT_UQ z9T^g$VyLo5*<>^(38@G-sBjf6aq~X5+YFpW5f(j*J2>$2iW$Sw z)qX$X<^|1In8$J0l(s#p+ZSD$ue=)Cio^bJbmXdkD_CKAdfUPmaY?rKus!k;9ijYf zXGXYCh3WT)7VAvK@*iZNn@X)0P4lEbi&P9Ryms#{82ft8UNLQ3Tyn&&TA*W~@&@DF z1mBuLnNsg1hsMN%?wNRLze^4-i_eb5bewfC2TF3^-%H+yU;EAJhfv;}MIl?n8gWwk zp9MS&a)gN&9UnQQ_dU4^hfTn!j5!d9MLKy7gkr{}AKmcsE$Cu1jdCc>=uQWfvLYkN z7#Bb1eD1&`Q}HJ2JBve0%*fc@@>^f_F1tQIKX>=d#0%qIQ&0GVH}QwN93_vzD6+-< z;eI1qN@dGw>`mQX@$x)I3Yk3s-bk1PzOVGM&+-&mh+Zc9T|J!at*v%ZZz4!aMcmxn zyt))X!dIs4==Qb`eo*xNeGk$|RD49b@xmADp12PE{J7fhckh_@;N8Ra^bec&@#lI> z`_GP5uiFmF_%~ww<$mkU-sMvl>@&#{d%aWd*jf18=jsc_yyYZ*M6^AI~>O9(wnJoHPhz)g$G@Ql8{_VOOy z`I0h5p87a=%%ck%lm}PSBG*6uvLzY`Hv9s^lA5T)8lFm*p=uEuv2|*AOj};bWYofn z9Mp~pP@1}_$*=Ah>OiO%9w|866^$y`;#HhT=6E!Ir=T*!aKP((aYF9bbL3z^!f|3x zk@jZDI*;m1$F{rS(dXYya<~X1UG16UQq-7unV~h_DsO-jywy@d)lpdzU~tYT^}sZZ z{}l!3yjMGD{P~W&qs5Uz$Abm_KRkV9T$JDQ_Pxsj zOQ(Q17E$HBJ<8oM*% z&+f$-8s4#9h!N`#Va}ld=P}H^`LY_xY;iiZ=`tE{cQG1Mc@?vxaWNCKSS8Fexsj4y zpVo$#QJEDtEor+uZ|xUR7c5jfF-a3NFInwY)PKVOZja48J5c}@X1ey`W>P%b7db) z2s%C*v@E-%WsoNKn@EH2wc@mHtg2jn-MK!Zf$TEFA>S`s;MYtx&3m^T33IUj_1eI= z6Bu6^N;Chnf}9X+@gCGeCtHnq;JsVagPZ+5d3~ql z_~XtAYNGn`dgVmfPGd_ga3yw$c{ufCy1ZbQ{iDWO8dZSKOJ0s$_UzO%85K65G%?fD z`pbkgNV;XwF8c3m?P`Ga`-Wc=4aQRsjt$+Cv5eQq5SYPCn)Vh=DTMT_%l=qTDNYs` zN^IkU80EowZbZNXifT^0J*$Lfo< z2jY%tr&oBGa}Qj1-Q4hAN2aa>|2?Iw!$og5RMvZi37z*YPfqD?qiu%f{t%#yht@LTcZGyKccEw4xa-UEq?wc&s=$JgmYI ztf|x?FZUpfj;ZPG>=J_O{RIB!n50n1B&F7xEjRtas}P`MCuQ^a)WvaVMi>=dq`AG! zOtb%p)mArVar{yuYpH6#0Kvf%sRAeLKKRCL4m2JL*n2DFj(Zh+=7yf~f@#PCAK|Gp zilLd1T3MHDlMLkcq!GVEsgB43* zzIb0WirAkT|FWaiccQ;oovbksi-bSv2&&zF<#h79HJuzd0Wzk`=BjKGI6-&Jz4s|l z@i_*IqhfhN99*MP=6e?NReWjMSINKqPJU;Z>iv_=Cv5Ra&?Rdjct<=rFI^WCXqE|j zav+!eE>+ZLJz*#Sakw@j&c_N14BFnw%HVs7t8u1IHC1^m)&>N4X|nz>x1Tv!*ax?ZgAAuBbD{+=}i=Op9B9^LF)WGEEo3#9>2&U!Sr$ypvBr?(AMz$T(6-xm8{{&)0aN@}KlLyI+t;Mk+0F@wbHTesI}OXUzz|{b(xRlZ!`>kr(HBP~_s|^VR(Z==rIK&sy&8`?i*A zYM1@LQELGe=R^DEa>rLS8!7$)J%K4=H&LdA9A2kD%^GFHs+DSu6BQcv6x4-RFmj0F z9)R#ZN*o;8*gu$StMWBLFH z0Vd<@oD)zOnWtR!BB84pKC%)V3$Lv*SN2igRRg#?`Q!tRg9YqvV)G8xZj>SSU{QaG z&{SG)>u~Z0R-)}wDv3|u4CC;L$$*U7fT==~b5d7Q*-~=g0@=b*D|evl^!*FpF8cdi zmfBtX_5eYtJ`6oL7Jdw%=zD+(_@Sg=4m(w#!pi&)WJt(r zK%>KON?I16Rs^8G3EB=f$bbH`9tunX@5hzmm|eCHOfZ+|iaD;m00d^T0CJzg%dCGZ zJOHJ1I!#*5$n!7B#RaJqVZ%2LIjxo`e^8WLv!$!?*Mdl|!#Cewjt*(ug98J&Skd%` zEY39e>eq~yg;MFYOp!%@?~6B42j`mmONhXe3o4^dX6&R(`!M4OK{R^c_ zkNe%u289Tr~0&VhP^pB<7)J}?~z`rco zG!Drj2y_H;cs~HxbC5ii6YDa*&HR2V%byg$n?0sb_;Kp8_?bgTfIsT2#MrfO^gytn zfLbOj3GrLvqmM-y_xY3@c$xU$V2(-v^LJ1MEFw>#yYovawJ%N{4%m8ubZhIfr&?RN zmId^a3D|?!bQnR=2z>L(1O%o^uH0Er+i|by$I@lbLe+>pCooYnCzODSsj6n={AZ&@ zsNrLPJtSI$fV=Y*Xauw}*`=ub>j}g4X0Cb)!m|!y^8gNoSKhn}U+&*#0oCX7 zFd-4IzIp7sT#TyWs)?62Y^bYRHPM+LWv{%zco&?h6rh~gG-4@lDi-K&C`=Jp4vl^# z4Zj^r#7${A>;K~T{apvt`G)FUc6b><6h5qnB2{l`wFs@*dEpaou=U`Dk)yHd09)%^ zTpzR4b>8aELW7YY*S~#!xY=hd&bPf}xI6~w(SkTH>R+*srgCQiQIetOBkX=m{?KC7^;`iZlPSVFpEY0W{ePtd$%I_x8I?kR$V+XJ7$M;q3H7U=w`^bb-r# zuGOKFo{`hP0V2|87JvGf-~4|_eN{rgXQk_o3WO5!Gtei$57_W4UXLR&6Jno7`LC4U zjDVW|Wc+Y;Udqj-fxRRL$t0#&Tml zlnuq%yEwXk2Q7^U@=L`(%VFO^CCAXBn}c$O;sFa*plSQ!spw1k}(wz=91(UTteyC2K&O zogd-2AdaRadJ^83bsix^c(jSmsi9`CB5WP@x)--S`&`+S@ydexuJmREmD3-xK^_ z=`ajf0KsTYliPq>ovf5&$Ba&r?n{po$)5CQZu$#y4;w&%tg&;o=+mm{LN)Jh<((OC zeyN)8EQ2Sgu1dsPh{!*CLqI!HZVGF z?|&ZrkE>?m08{ix>n%VCzV{k4R7ApfnJ46o>&*x19Y2~||1dIs#j9_KIyt|Edb+o8 zesVowmZf#$A%O^r>c_Y#P?CJ!XB0f2tu;HF@_QI}>plW5oB)R4d~xvMZuWZR93tI| zU8;17<>xu-TRDc9l$hdwu5kwVIQmzLuZe$+lIrVVMD z(w{_WDUt4NQ4ntiP_MwQX7uHb)K<@Ucmn0iJApqDsXY&@+hYHl|aOAQf;xSqltg`oOLyp28QG2p; zE7*`p;ot1a6i8YagfNhi+)zaL^|Zy+j!T*fkV9lAK)&SB9n_ix{LVXy8^_#Plw0#I z)ViLlIhX4xN2px5A9}ny_zz)%5aDOkgv3Q zeC2R)4FhBXGEOf76GKRq-yCJffA!}rN9_0nFWdhc#g!W54Qe#hn$n`d7sVgQkl4)y zz3~RMveFGR5TFtIn1OIv9sZn$32nZW7Dox=sC<`*%>PL1gmt%y7RD;$F;g`C({F#d zl%E~_w-uOG0%}*TFfHfVyUXRu;I*_)f|BEun@Rn{m;3&klo)gj4#9C0|CPp4Cd2$_ywx7YVOWt0=dENTczs<$5y>J>J?kb2f)2h?r$|fLud%I zh2&bUu|5RNXANo%1#F7X@yU>-i^@Bn+jO}%hOSKac3!@WQo6oCtMSKi|KnLUD2xr3 zJ*A$c$i}m9S}Le!&e--dqYcP<0=Vg2Eyfb9N$>T?k=YddMo5eNdDLVtAnVo(L)oir6K~QROGg#PpWNs+s#*E8d+3j8u@y ztc!gRSk*iV`D6|u`yBCTW0C7U6?fAL4Cn*`_>*l6K#sgS7t4&w*1^xJr@nr7 zC}$Gh&iJ3ly0D=k0N=NT70WV(YYTyZ*IjC}jU@9Vka@Xn1UZtEO4g#~9#8vd;b&?= zeD(`W`_z$MoSGbE=wHDx-B$JEtW-HMgtLghTWT)7~! z;VGWMM-{fecRh~^-P>kOGA2d~{2wIM^TgbUfjCw`557OP01$4<{R)_AVRjzCqALgl zN>qOH@3alhc8c(Gj<|N@e1*FZOFWwx>m7?@jM+I}xNCRC`Ujtrm|usW7eI|t zXJW!d&*%I^?Jay%4SF#z6Hw%UK@9EIeOp#mdtVej&--Ojy{V;O-xu?FC|wDzts8o) zVnZj$Md92cg%*5U!W@+KWC!pj0Nxsm$YKiQ?@`R>HH4qU>2`w0MMADrt3l9_2VzyrZ-1XfA;(K#(g{b z4;m2$Ka0fKZ=woNgAdC*0(c>zT~59)B#)(Q&WFnIEh+G7H!;5IjL5QwndOh(AI-`I zv>TmC!T-PaKnKqvJkZxAVugUqgj-cy+;`_v1^#lg z+}io@-L$)2whn2uyeT;mw?@bau2BFjM~f0!j|jWngx`8fjVn(IhLcm zeLl6G$gX;la)p?XM=YvVNxXQJ@8Yt((ZAx|b`VMMdhY#{IA-$M5Mh;GSp2`8I4c5y z$W{_9QQ=h8toC8Vz?z5}R^S+PVZRXzswM@9UtIUK2yNZFh>^_r3PMg|3_k04OatP> zp^8S-)(@-Xf8=Os+j`Zlb!nf^eG7fP`;EiaNmcP*;C=yxkqZlah=SnhbpPcMstoY_ zaq{2ly(zKs7}%u&51)P_YyY*H{p;d=ArMavq_p*EL?!0PwHy{<%Qb>6&z)&iZC9>3 z>Pf_X7U@;hsZLOo!-W)B44u+~e!TlLlpDk;rl*=)^)tr%T7nOZB;(k`1VbzvMw=z$ zm2=kmAn5zR?sGi&OqFb=zpy}IM;-AtRUhEG4)ZGwpwhVH`pvjD`gi4ZO{am-*umfA zG3M|S9(zstn*x$NHh+KvTDRj@->Xs!+l^te{39@f=lio1&^3Dq%m4)2rglH7lKt(; zE>Y?#4NbdQ{{ZOivW3}p-jl*_6r!NtPB~*lam*vXF);9dDr_wX@CCj|&9>(8xL(L9 zW^Jc-uevJJQqlknR^CfN?Kd>jbwDEwM4zUvJDFyQ99lI?!dVPe30b{w=v z??KW_W!fT(Uvu)~MAWa>J=~iOb&To#o2{wZ&`dy_cS2$gYs?L-+_3x=QoW%f6`Bn@hkqyuf_;`mt2&afw=0##r}Y zSI@{IAMNmWHvGiTT>r*|#S4I2amiD&U$J`d#6FRgGa65pVDGUT;a~H-|)clU$o|Fmik}l$4WS4v_HwF-Eu6S-!htVTl zCh19!#R+c2^6i_FSP2w%D_#tw>bm*#I_80~W5zC9(0eyZ$UgT&xF$OQz3%ik(Z{3% z#cC%qAa1hhkQyAH0offOMn2kUKkCXAKImT!1tjkd zyGxcUPer94BhGrcQ_SxbM|T$&4d--!>bk0eIN2*Tsdcs^IdcWWZe4RgSkzBC#b22Q|7@+j912I?S<EKn)CcyHHL)p`RJVjyfyJh#fN9JE`7hc4a;@R&@T zJy3o0oC3xIJn?$?+7%k(^dpK1`=PqAiP|Hu&iRCX!IC5vI<61EX;yIDOATFFk*foZ zp|?KK)8ET*Ek6*mO$0r3NnI8DfvhvHK6?2h$m{>GXkMBC({FsT^2dt7I9O$i*-qL+(R3% zs~RE9>oNRjXwJlkU8e43Yjy^Fa(?i0SLL5FTXQ*k@#2I31S!Y4YKNgKO@?Jaiuo`$yRIEa++AIVY%4J#al7b7H#A zkKMHZ(Ix>CkfDU!kUn<(_^FOpK)Rb%lpTVum;cbC?Pbs$6R-k?mpLxX-Z@-K=Xfn4 zrJ|QG8vAd+H*7h5pki$TeH`^uKb=DN7EhxMkYNz;X$&mfN}t1pe z?&6*zcLWsF>kFTD?K1dyf5f_>V|qD2ZIyO2QZIUKT4ow*0{Sl|(&2%6LB&Nnub#p} z2hFrk(7&6C&t`?s>>6SS^_RfY*htt1Km_{l`g`L z!QOI<=U zfg+@0fr1Po_rB+ePLG&r2uTY|axA0fk%O+E(iCvMQ}^!RFWd)m)HxvGIJB zN7{LmNFBAflafG5V4JoV+DLpkJ)HeKwv*G25ZuHTuL4BXGP=I|5Psj~Vq@AVtsL>U z4Ed8IP)31d*aV7fn#~ZJqoTTXyp7unsByrHE$pa)^gb}0mpI{DLklL?;9f;CfOZ6W z)XFp_FKw+PY5{~C?=2>k@kUkay2}yW&~bW-Y9nd>%&3r%rkKxWtHAW)MAb-Sqr>a9 zZydjT&sevby|a!@n{&FI3T!DO#RKs7KBdCuC7?Ex$S?f(rf>Pc&KH)KzZ~lU=_jO< zV^DakDEjDYY{2FV?_mepP@r+?gD=XS!KcVmF~yXxD!O2INzPz)1-3$rI^dTibIoILJzmpk_(%0qqRhw z=42DU&^c&&-!>bOgG#o>C&KL(7kR>D!2Oy`Y;OZ`)QQ;=1o$W!;A5CNomns zYzz4DZ;-GrA2)BMy19}K-1pInzC%t0Ar6Lff_jID`bATyEHJA{_u2;)fcdZcl2VqM zrS}L*F~Doq`N#XL^0CK}4D`O;E>7lZJI+_re=Z~z zA_Ex(OoiD)?kDjUNAipd=!Wb*sA;8W%uG}gi(|@hkrad2=fa?~s-y>x6l4EU3@mCj zN#_;8qUT#bcj-A=C1foTI8gwg^)&XR2O@A9lK?;Q;|#WLF} zzqmj;0q`vA!RT=76x^R%Lt6QE&%Ie>F;u{8?s z@7X<9V$PbDN#ZO(EQ-`j%^*j}*t0;C;$5so*H^Kcstc}`>kGlmXN$MLN)bcs;oUD8 z2Q0$ekMeC73??P$?(G6-hY)0k1?grH5&wO5PG}JM3$m>bV--U?&8*61qVuV(fpbMiMcc%`Mhf7LPC(Jn$Ie z)x;B_*J%?xTJ1w|ul~h%XGf*VLJbdbW6fI>m|f<&ZbN*VV&!XP@3DRKxrbFXFzMh= z!22=I9iQVQyR*QL!GM50aw-yZn}#9Z7jR<(8XzG3%h#Kii;4PdeR&|52tZ2GJkoHl z_?-uXdsO-b+s{A82+MWTbe|VhiYH|o?9`L;*RuMTLc(`>TiMF8226eh8UPA9utc?{ zJoZ{OZ2U=K!N#92sX(HJ>Xr3`dsS?&!c71=t+Z`?9*`mcaNY0F2U}L2t~YY@@YK~l z0(Lo`-vdLRUsM~JoLj{Bs2wu>#8c(DShcg2Syg8&}7XKlc!sVS80 zxbQRtko+O$YLEC)@u7ZH@7ZHe#cuyZ7%`wkjbO_<-6_`zK2NM#s3-L0bv^FBOHL*H zY{&CF*jk<67~CEaEd42(yqXoT)e&9UezUTyeD)3NLw>Ym$mpE<_O}C&oXb-YhcqBj zRsIgZ0+4!iJDm}Y_6$sG<0qHuJuBDD&Y=+t&>l$~aDt_vn3NCZhN$Ggtbew9XppI^ zEI{9%4~*QWtM9H353bE#hdg~kvK4nE9pS$kD@Fi^lI4in-zGYdJ=zbJ!j{&K0OY%8 z;U7lirua|nMu6%;aAO*{7r;+skaJ$#JN%JXiVYwEJQ<&&FRYIN*awYJ{{}k-nOeX0 zs3OOgIJVx*W%?OR6~<51g2i?E%rcnZq~~Pd)1|gA-+~;hHHV9*?~Pggq#)Omzs>E* z27u8PEbF&*@6Wibw{t1aq^JOHsyLs!04S)MVH2U*8w(hU0=swE;r$Tqll4h~9?v}Zt@Rrxr$Y`>>jrdqs$1vu(^R!%cQIY{&P zNs3OFD8C~d>o}0&4jj0{vE0!pAj{`KpW`8dtpZH~4(8!Y4*}7TW0S4k!uLoM1D{HORxXR1DN;R>r%(BIO~9CwCa@#^a7pHEI* zBp;Xs!}*B_{F~hQ{D%UAiWe#!^a#2kfs7Pbe<~ccp9w5B-{69vuNJ$p*btNm_&uAj zUYfgpLjt!py-=noo|v+UuH1ty8G;~zGcG>`=noyIT+s98=;%8nrP?Xt z*$cTqv>ab-*C-xtZ99DqDGWWLi+(d#$oLF;6N0sj?^^+Pg+Yzj8%-C!Uz;g&9+C{- z$HNxpgj3EPH?I@y?K`lO{!P5hJU-U%Os)WFP1F!gzWF)ZPh0ZKWp3(C@QrH(enXV7o`= z9@z3DP5qys6BhB0!o#V6rp6o%IX+Oske{cI~ZdCG&R;sN(*3zxylZZ1`5{ouNah!ed zx0LHF6#z_uGrx*DnBUblJKg)31PHuDVu?si2FS6Qgg(_I2iJ0fuzv(`{hks-A@kH! z03~>S*um&Qv+&hyDXrf3l(`#^SkLPI^jWlWTf9qxxXLIy%lZyRSnSI~zajFOtS{xs zpWnU~7`^&REBkJDjwCo7Vgx&N-akO?eP|eYd;MpAa5h9;qDHgzRc^j-=(t3K_8L~3)oG03sMdV#hU>pHoET6!_#rTp z*~JOgs(v{RJs9q|z_L`>efYL{J?qstZt2JEhH`0<@l?^kSPRs~{@3(d0xDIX%9vTN z+c-v^Hmz2IJ6@C+*QpUx#@5-@s{e?^9fScGFNzPtWV-ElR%qOM+;%P2jO!(Zs=P}ff3J|>`DZS8LkIh`>rttH(OG}1G0G>kIj$GBZnK({O@CG~+k#GCj96F_JQ79LdqYH4t4 zdqHaCIYeO*8W32sd0Pp(WO|nc;_U`NHq}lsd(LhRQ6&SEf^lp^0BLQkB-Fv9HnJX_WW-7R<=c18KA~D8N zo}dRq#=U%{@|n0uq=bRtatZj*x5qprDj@55iH=vA!SN)@qNDsW`*^EBVAZ@Tbk`2N75Vw3$r?PTu1eu!pHP%RyklG^P z%M~VD0LiM6@#unVtws@ww3Z3H`ZZz1Zf7&|HP#G0_$k0H<(Q3crOC#_B&Gi(pd0+C z?2u^F?*}89vbZex1g02GU`tcQUsJV16y`Q&rkYY5%h9h*!s%3Km^C$Kg*R+h!tD(Q z5T`L)GZwba|-(IgX%4SEWfMps@{^mmMqP$r;?2x&};= z$m!cLf6^LU93TGyN^SJQmuY%VP+THqkZ`9oddK}p0dn~!>RC4;)gX2^Xx`yyohq{^ zWsRp{XY@je{8>UCM~Q!*=%t=M5&I!KtMJa`GoLVP@Uf|z=G|zuj^t>mxSK;+Uqvjf z?P~90MTslZxM@{9Eoe9jl(aV7{P_INhlVJ8bj>WB=``f7*$WsxxU5=Js_^BHIlfHZ z)}Z-XFZza`oTQG=yo2PQZTDO~uwRd~HYQ{bI`4{Lm7J;8(G7U1QvjKwJ+S_DowCx{>eg)O#AA) zHuFu_brbBFb#%Pqad@0uXDr^r7AF2_f?nM2i;f0WjYu<#nG2;sdhqJv>5)Soe~Myw zuFyN3h-MPSNd`TYcf5u9i}=rGBc;RSH)el-)}J1wIIx0jashO#$wG=?>(_Z7s6gmq zSskzh89YsJE1J{G3H9(bz{p^&6__!8B>2)K@9hm7DrkQS6>HYJxN&>kakgGMBeRaQ zC=jBb;y+r^K7s4>Z2m0`s(5@x9W5pEMKv~**t`?8$B3OHHc1W6%Z05OGn)oasGy3{vAqlOZ)riC8}@c$KwcQ()^*u|DF z*6=;U*KBuK`aY^Su}&+sV&1YF*7fu-o#vdtrPqlRt8T!>d1LC6{w%+4U9#@sVw| zlKtpvoy#|O2XtTV3}poLND-lZh|qcX@pUvvN08){?Oh7wzS)Dsh`+x*^Rd+kMFxna zd-erE(0$&Dp`hD`_?pS}^wLyw_1o&)MvmgaEnYnRM*;2b(VP=}Qy?Vb;H*i%-~I!4%Wp0ueVJ_D;>&7 zZe$>C!LzM3OuT+q_e_{SriJEGC0@6#TkFmC)1N1(1h&qY|-!vMv00JMTGHM`!@jVJDW z&$|&78Z$Ojp!xcNhq8AV*svPIJYq@a$RCF}H_vo-d?u{d+Z$M6dXQ-M^f6Je(q8mY z`ir`a7@Nr*{|M{bE1&4zrUpRadak_1)pzF=v>u7t;I!7g5%Av~!fUZIdwWRiCWL)w zN`~BLd4@#@4P4p<6hWC|eT4&dJhQ()Ygc__+i_1^LF>| zh+TF+TEL1YyD25$vpCv06OY>nAU%RY(KWu|+>w<%OlQc4V(u}CkBaB?b71}h@`y4W zssk`-0!E7F@azpna9~Sle12a+eQSpVrZL zFxq&tK!Smy5vwMxti$43&7jDbMyXe+8W2DSZSVE^7d8_XDbS+?dgn+j$$;0p?xMek zlm~u|&htu;?8(Pogalyl`Hw}<&`jCm+g^^ZOCJ!`0NkRG8Gt%c6ik5rh9P=F;BVW> zTkK#_qNrp1jV2Hw1JF+5AiwZX;>@q)T2XZR97LC4My&S)H`oAQNScCiHOmQHJ&dK~Wos zVhvY>#g(UJ1BJ8lc84~$Lz&u0Z%Kec_V z!%K+4O3yOoqcNl4^;&w?tCT~!9KBGnAQlv2ceIIr-+dg~z;vx$rdB%DSWC%0#1%K{uDvCmAfn^9O+3(Lr2Y_{OTvsv+b6>Jdc zPE2_60T=8VG6qnnY&rMyK&x%{bPnwgj?=$oWHFCw9cT0>$c;8A^$pDA%MTpMgUxNN z2$s>7$D->J?eVzPN2dILmA{WK<#kIFgRUKS)im-cIo-cSK4a50DOENm27UD>XO8fr$K=NL0-w^)Y1T>Yv+QQxmz`zT7S0i1^1>aZH#72 zKQ+cl*gbi14xub`!kq3Eh((2mj>S2({7q+#pr;gz-7Mys;D5Kbq7sb1+@A(i<73$; zFMtZmJ};mpjtei5hAd6f)jhFRaKkIhBZOS^mES~BbY&nh#sBUCR3>0L_)_yqI*k!{>n&(_#}uLwfa+V>>HJ}?TSiR3XZ%} z>RRV%x$*Ujm--d#WS4UBwymu zb23B{qtxIBNxaJ04Qr2Wn^NP=!h1V9OY}F0OT=+S$4U2x#Zt#vMJ|MvbJu4IA4C1{&VkHsYxQLEym!|=a1dGSYlhK z{+AVZyBAw&37=(;6ZN_KsDA%~sSmj|t+R~(?~yl7gQ%!C4*2&Vn0b>tNe*Vtm-L#MW?DFj;!k<@Hd&IQfiQiJM9`n(( zW5dRY7Mz0-O^_TV{} zUyu5gKz*Z~@ieFNwM}6?s$`DD<3;4a@(c?E4q9>zzy8&Zf5dB`BJWVp2TZKq;x8~h z5~jAZ7dtTMEWXfN$x*L((&85SK>hsL=J|wORBcxSWR<-9P-hM`9;525v`|RPbaGa|6FxwyV65OJs*h<=?AC72t9z&|i5gb0dui)y3 za%}YrPdP!^j&n*S5PKz@dYQD#Cp&({f|Azi*WE@UCGS|qIb$RhM0ZrMDsiwT34pi~ zqeVurc_1RE{p8u0=b>EI>((jqWz5z#;svzjI_5duTI%M5gO>>1wy&)yi{W_Z0A<%s zNVsl)jmd<=dNyqul{x{vBTEQ5zIHjhF&J4JV~N z7^`zB#%4+S!|AdbU2fmz#2k`GcQSWe3L^0no}i-i)<>paI+O=k2zNnXIM(|eGOtCq z)1NWjmPc+Gz1z?D`9WfYecY2XtA`uE_sKI;X^jL03H|2JToAa_=1&M9$9B$qEu}_- z#6A`r<~W`Atu_`o4|6E?&ChKWa=Wrv0rPV!J3=}wAKhmTx+M1_5aF~C!hOBfZU@JVu8wpQJaUc0GKZB{QD?QkTxhvT0!jTO0vDY^h{{pamNl<>)T5 zB0$LV%!Wy9rLeR=)4mxI@iR(LiR}#vCDdco`%P|VBvkdCi;Iz($zb=2e>FoK^4?}u zr58ngk1oS8=Azc}7W7>z_NqQMyt84K8`Mguc`5gKt7tjjH<%@-;>zObi-9z%W?9mR zafa6Y9(Hh_Ew&>IPhZ)8+Vi<0Mx!+}zqpRqJgVU<-Wn@u$QRW+&ox-6D=EbQ?Bn!A zuOM>ZVSGwtM1hcrXP#h%(kjW_#a_@xi)&b=-a4<+BYS6z`7&?+lFMoiI5303J+*(i zax{u?-IlyBz1zgPjL_Cdj*Ig;Jb7SD)h_xr@Xt>2H+G5+2^qm3_~jP!TH*-!eP%eE zy>oZf%js5W3QNRhbn>0j?8d7*+h9oNfV2-XtkP78+-ub`1Sg8WFSro?*M$P<64V~?9PM3xJQ%>tn61deI4>;odHfy@? z^3Fpyi!)lC#->KPZv#n5G@rh=w5x|LeGq@h=fXBLsihta;S6^gT`pa5I!SvjeAz&d zYF>8g3*_ZbR8B@B55g7Uc=iF=u6j}x^xdZ60OUiKVcX*j;-h$yN1or=KLpvFm^Q;P zi-gHO&h|}}Tr#JsH%7}M2SVe?Dvc9loqxtw-4rCmm%+ErlWjGaVT%|3FDPqdzLSV}kqt!=y+j5Ap3ydS|?JJQF|3}ta zheh>8ZNq1Vp^@$mr9%`+fuW?kQ&Ob61qP&%P`VLNq#KkFM7l$yyBq1A@9=xx@4DXa z`Tm@L&N;L9+H2iwt$W@3!NjP&82~H>S@rZdu#*|nQ&_1z`J!&WUEd*i%KN-_m)mwV z=>fJi?TK#pQzDC5FsPhHSMh%9w3Vj5=QBSe6fS>X&14RU*^LIVSA9#cy~)sohF6lA z?)v!G5on1we4crLDI%a9hcu)1L*4^_c(k<4O3H1pNRR8c^ZGxdj>W>Bj;JvM-%9jO%@5_-A2|Np_^3J9N`Za5uX_g$DYCstMza+?h!euHw0jRB9D|< zActcki1=G=w_}M^g@C<^T!ywovUBz6$uw~_w(xX>JHvQRlT-9P1jPfx0H{Z-o<%VM&16o=^EN+tSbz#V0$vkt6h zw6g$qZ~SRP44nXBwi13I8Z3?tLw7@yVok!0E6`XbxIM&|ibahOWguN@5}i%_eJ?Ry zpKgLShN4YXO@FY-r^`$8pGmlb{*fUt#shfu*RJ&C;&fVfM{)f@ZDj3TyO1@v#l;W3 zyNW%J2GTPp;@<^y!)$Iyqlhn7EO7)-Ce^24)d7=_aK(FNfGq~M1UUjcU*Fth?^?+H zqy*TyaJ~QAsi@f^DZ@HP{g(Av<;5|o?Y~W)z80}Il%(fp^#1ftXMxBd+}ADki42<} z7a)@Id5sNG!?{|W5K1jmR~)R{XFDIhs`+yiC*P-uG$~rt(!BlMVFQz*Un|W=-`>1y zdVBaK+MWGg*m$*;SN5X!pH}K=v`ZLDl+2^Gvd>L8iR%F4bH`m@-^ggRBEI+nE`M~p z)Gae7=i*&ED&5`DTBim!@U6&)w+d-Mx&;n%%kE!xK84UfGx{Py{>I_Zk97tJ7LUM^ zot~;P{7a)NhT);G}x1*uS3e7Gpi zLgtR<&+&TK4&sN>9>bJCIw3Td{5UK$dbGfE{+q29SxElnRnAR)~LSJ;A5fDZndimmn_0iX&=4L2q5S!+WG()wW*1 zBJi|iJ??AP9o<;x&HI2?z?#7AoH-V#rIL$p4|>*Luip2-Qm5Cs8?z!2ywtNlepjBX z2o(!i1#6VXA6!^(E@(xz0KR50o4KoQym4^Eg0LQb`m{qVH$eL0840U~?3r9?gvfB3 zf(UUp0s(9hAR%K-shUu~p^S1PY>7CRH>v!gV6epk2MxmJI&P-v0kG6QY2{&YxY~YJ z;fhCo*@k*AIsa*@)oIjz_p(bN!iy(c1|%D(oqZpR1wFe37%N7)h~uL1`MwY-4G|v7 zmQ+;fV3or3S<0!Qwr63M^DVts?J{1~MhagCDbkkcwD)6L7U1KSYAIt!NMGmL{!WaG z#Mh?Re$_1n*!m1hG=4zwMySy(DdS>j$@*wrl>Yk9p-F)bEj;rrhUz^Xzn$HsR@*rB z`od*g4n_%swx_`6UF&$kizEz9y2p{dfos%GNj<_Nt~WJgv`qgH(P}3UHb+lZ?JuRh^tuepLLkvW-+kXYUc3`?&PUv*NDb7 z9bFPob~uh;NBu!o4vW^SbNDv<(yY%iIo~jy?cRvaJ`%VxyvAu4L`kD>>4(YJX>sfP znj#D$CqBj1B7aFI?%HPmdMIM#H~gJCohg4x8>uD&42`JtpvB|5{zdx;jR08kQ&8`n zXJ7extg;7-fW*lU+yzDVFWyk-X}=*jzjD5LrE+3e$T_w+y7{|6uvy37H%)U*3md&` zGs*{?A<)rzL>ThWkO@fyZQjt7HSmts3H4haFuE%AX#62ZGG?F!*5em@T3&izScKd; z=2Hf@(3*(FaR3KegqNsFjVWbv;tjjyd@D4=Lhs#f!^@2d{MvHLEFeKaatYLJ?Go(k zt`(JA1Uen9$NY#Wf0qxK_I|euMFM8n(s+ix&t5T!HgRW9=KCz#YJ!mX9%LU;A5%S2 zIT-mpA``T9PS=(+8jt&>T@nffhiWEPc+drhTNm3Y8oyi%MLEPkL$@~1=Zp9iF-!Qo zLtmZf^wuR>J{ja+8k-LEXo>!k@H?qCrH&vz8$D&v>XSFUY^1fZ;{X*ESUhjm1?@ik z_SJj2T}dl=KBdk}yd(6*SLM)e?YWoe8h?IT>XQuGIOy57No{oz?FSXV*q;4soLCT+0dA_M#dtEQz%~);}(d~^4bgxaRn#Iq_-~#qS zt7KN(E-(>B3p8zpvu79*9w4H%sE;^p@7?wUY5tEsw~*mOO?k|@g~dh|rO9Zi%QL2w zP2z%r1s;gt)-VkVWggi6`a>}lo!fhkbp@rb0Nf?JD-C1D4qz(od9U_=bvO5bTnW|8LYN-29DaBbQVXv@w#|k$34_YNX=TP zAne19y>@E+RCD?-ra28hPrkJ%jFny|=e9)`|CLvqYB%Usk!_M z$4I85zmfBkNfRgqkgs=PZ1tkH1%*ys2kB4JKO@%87JI|}+MUZ;*tm?iTlKcB3UE+N zRCh&37ve5hsHID^g64*t%PIkVuhuk=-%Y=O=0!LllBi*98_Zx%^Br?4lZOM$FxQa$ zdLX~~9PeFX`@kET!BB)?HKP?>ZT5^N z3F)UxBa~-+m{ugy#}PT-K(-ic+mZwg4;=%Z6>O_XTO&5>Us>>3~lpz5-CX+L$s?C;;Mvjfc_1HozYatq}eTic%P~XX>E?bm#ImNB29DE7yZv zJ2qgQPho4bxPk8#Rh`$Yq9~u`P~k|3$-hdq8z_fbBsF@x#dt zq>^4czbV~1hgB?mune?T`01!t02ygAvPxh0(LjiyHcpFb^0(7hS6V=)d$Ecc?yth5 zZN{2}EdwXfX@N_`0N?&Z^c?)a7jb2=hUdNtOQiy_&Jvm$cvjIT{-O~~e7N19)4$gV z-TnLb#vovaT(rveW3|zt*^AxrLL)}~(81+)Zf|~jH}8bczALhsJQc;xLnqBLAi0SI zt=HZja%x)iR`d}Gqxfub6Kmw zl8TzdHae9Fz3Zual)H}`sq6G?tv}9+ngBbuUF&Nn35Yu}09(2(n+Uq;wuLIs8fFf# z`m=e$?gSE?U3;vs!5wel*ZUZ1^wWCMp?~Fz`_F{HjBfU;e@Qz#xxYQ`)ancz0|PK7 z-!)o17wzW|>;e1|er24p+p*D?X~}?9^rD-TA$6!(K&%}A`JPjUds?4rr~Bhomy)EF zG%pzw=xaI=8~#F|8jQu-U#6pF{;%qaV7M`EsJ9sIRKJ7;xo#2{0ry?M?AUd@Mg+*4 ztVCOW=>rRIRbBlf8+eG3LBSMdyo2I6W(ek+cn7E9FeDspWMa9HP6!0}^d!I{4`}pA|rqefG zV1Iydybz}V)gfgEr$(H!>dY{+VpX{98+jz)^mjp zqX*?yvS6FpFQBGSSb|}kWIB;irkvX|Nq*oZfX9%%;GLvxAgCzX&9teXPfd`e=tV)u1`)1gWK6#O z_n4iXQ5Z94GZRdmd|rd4He8?cM`B$i8N9d4WeUAq4c)I0WadC_dSUxl_r0QmuPrc0 zW4S;f-9kkYs*agAi`bj22tN*8-O)^C2c;EG49kSf%|;4yZb{IMMt7dDa#!or<3~VZP$*UA75>O%2?C(ykrcZUCO{`0w@@OdW-eHOa$96^ZTu3!0+7!47v{9huAN4_?cJ&xW0rfAz;!2S6 zZ14f+aej=swUCS_IE;(&EB=4~hke;tn?F&n{uEa{juUAJ*LP(MyYE&Xx*!ORyz-C%U3sJIO{Xmh#5W3(k5pvdvrU;zQ@=HaeIdX zrD^FEb`>&>?+(V|0}zH8X{`iNuZk)+Iu&eTxj}gf;q_uf#a0Wy%;lzV@!cSxzcvE$ z{8K>OKxg78e%+r;7Xc5Br@!<{IBwmAq z7PI@>K{ysB27LjLS6hokgQ?Y70)`;>mFpK?;_06L-|wqX5oG`qMM(7yQcQkYC+%bQ zJl6#ytc|O3!&ChM2o1MLz#!cFLTbI}J}O?pc;_JVLs#dJ=EB8vBtN8Gjva?%vfG;q zuKnSCQ%;ekcZiM}mI*-OnOY+KH%(YQZP$-JW#APl{A2u6k~nK!D!EW;g@RP zUTaeg1@KJ}sNHcRStrPX%Rj^ot$1$%ECdE&XOkHpRd-N4k1PCtzeB_I^hSAh@mB1aMMUm}>l_DMx6&g3>6OoJE{KP_^|N6f8MdDi)y=!Q~{fKsS z?Wvl!MIPBM^7nJ%HWS|bnY2qmcCqc}6+Nt@Bo^SwStbL0g6k}0N7Q8`<(UmNnfGXk z;K*#oqziwWfr6Yi5!-8yM*RM1PlnQKEsEfo@_!xYLw{Re2$YZ3Kr0X95Z`sF`0`m} zQ`9zZS*}ISiMvBNM}L+)wGV9>NMrEUVWR3$+s^r^rSr1CM^Dhh35>kK!ygmC93wbA z&u!*phmOs}*9J-l4NqTesk$VV%Sf$<*?3C*U@`AM0WL$oc}cRV{kyERGzQlXV&8(x7XdHfHoAqlOW zznH3hi4>4FUvo^(;>7wnFhPInZ-Fy4A^FU?(z4MQnc!fKl z&_!|l&*_I^OZ@C4{kcS-!=ltI`UDf9Z+EDhmfa5Q#&M=Mp8;{|SGb@h_DrE+f{u70 z*YkoK9sQu$d#IPibs>M+HNB-VEbEmmL#tqI_-_Q>kNT(R0 zG5J|u2%uw*`;hEPEK!StZTHnFHj$HG#dTXK+-Fgu>JwokbTOhb$H4#51;A*_RwPS& z@yIMgRqz}lV~USi9{y`T#(L4?-%I~ye4XMHOB^Tz%n6?*ge83bp0jy)c(SaFISs#UA)7^%fpt ztDKfQhy5&12Zd|)mnM$>*4gE6Qt?6)ocZ z%WiiY`rfZ}x$?K2P{WE+a3ysrtH@&UE)UP`^B)8oIyIjx%-)|-af$dSZNDcoznTQ+M;R>9$U8aPC3f|3tVcm+R#}MN!bK+* zei9LphNi1l$nSpA0ipmc)2Ad@m}Wk+Pm9%abCVY)zstF-w~P6hVSO66yjGp5DdK}Q z-}`U+H`@CMU1!pVucmQ|b{Bp6-&-y2M%cf`sA__DlbPR^V@g(N>z8Y*eBCS~+paME zHjLz%w9CUVSh%1lF2t0Kkcf{FfeA5yQry0#KU}uZ#*4I&K9lM|hs4TlbMzqjqr!hv zzU~k)eJ0gfQop&&pC{nxWJazU!8MF$e)*g%NfN@PTE=bD@78!m&Hy-u3N%GORKtF( zKFT}lFJAD{tdzgAj7V}kyc&No*`V+nCY0U(%UpGCD@>j~hQ(hAD5BUF(A-c8xHovp zB!`G>-K7|@<_KeTer`WuzJ6Ta;|V9=+=7#TBwr6(+)I@@CAWiQMm0Hd47g^#0DV!mmikA z=ntR^csrB@;ya<+#GIIP;J4kx3b`)IVc!Jr!nCXi z*D!CkVqfNGZz7gNf4T;Z&EO?(%Iqwf;$FV1kf$=%#>@IemtB>j&m(olpZ5I1{+ruF zbsG1-_4z4L8egf=9wlGrAn0ch?fyy)ECiGGm<}ZcR@hJtW#Q?}H|sW#4R1#emm9xg zy(;ltq-$e*4yDb8GN~4bgCq61B>JvsaQJ`?|Y`hiJ(iI!Jau_9muigR2=dP z!J1YQuEl*GnqyFtNRLZLJU6cP(D zAmx$K6h1FtER9(z3KL9=`yN58_593R;3Y{z#swFcw2^_#8{8jul+F3}GF%3Y?%oA< z+;6+J=@BO*)jlDjs-m0&_Fo%>=W$4)Z|5V}rtYbxlA!|;u{zPg*wFBR_%gjZ;fW$L@O<{O_+w|9X zYv?%XtP!>1t=GdW)=~A9yRb>?oQJ*D=L3|NhS`oFN4Su{j&wY7ck<<(`kzHm1!+C? zzq7SV`H&@%5~F(vP1J)m?VYYC=GuS5hp#`xf1sKDM&hxm(ff(^?IH%eaWQXI)&}IT zyGL$T&T;kZ;*~o4@Jzyw(7-}(SXimi)_I=#0%9UC8|*_LJAyS>YS+mZ5hUZ_@J{WW z=0w;B;19aq;0lW`)%(i3v3uN#nXaIym6mAh@y4kH{?ia@*9W=y zL_Cm>03K3@_eW69tp!!Gf5hI9gCz$9YBNo4!+dfpeamR2kSeqGOa7RFd2&VtfBtTV z=328S5_Kw0yZYsXpWC#>xIe9NdB$?E;2PbMJ%~SW#T6U~ffDGyg=?Pt_jLdFG?$*0kI??4^2sHn-mQpVr1+G99+>nyfRD3uB8zeGRKdoRe!0 zUhOL+j&}O3mv72mFB+d%;|Fte{x1``!(vUkaTD=3DoRQC^mgv=*(q)y#V>rEOVbI1 z^gQY@)J{1~hj%g9LjFJON*s#<^lu=B{KJzrO6n2|HP_wG+xy47e&JlN9*I%-o@FL&G(2P_3tKNe&TN$#v3ccQHd4l0Tx5Fhlv_||X0doxrh}KjZ z@M@n*6wXO%kUacCa3>&1lHv2Ie2r(LToLn^FQa6oj2FU9DcZVN1DM_gDGbknm1kLs zNi5#-?|M0H0#?23nK1;m84fdO7CtsFf|`X1oGWW(`c$fA`guj{jIUk|;DUjD3X*Jx z3r1H;YL8Yd=9gN1RN%ajS)g`Zr%{u_@9!E*FJm!BG^yx!-BQfIbo|n`9r3@_25Bf0 zm0M#AX0g)9B#tqOB$c@003lJnf((%wXOdcu5uOFxe4nQEtg^sp>dF=x&i`x8C^w-` z+8MVJHum`#a}8+lhg4v&`#2f34}9CXUX^3^-G-0pAzq0^TXhS-_sfqTd2JSP_nXv> z?vn)yy!E~_UyoAijcs9V`?sA#Wk#HDBX4NOesQ2= zQLNDcL05Rf*^8+D#p{i3S4fGqt-#~we$eLWC7)j+&RkEXGw8<8hQW!%v(yb2ng1-< z>Ajj(#>iLfGqW_)KYF?jM=eN=g+J+Rm#O_b0LtlVPotLC+F<#X_Dgv$&0{KPl%A_r;;JpUo{vZsqcN z4bD@MUXbTnS#Ft4Vd?vA6x2T|Xy2$DTk%(XqbLLS`$hWDOi`f&iWqpslNR%x5 z{c!(0VFFA|ktbj>@fIB7r2Qumf#FfAMn%R}P5}8s_N|Yc(Lq@i<)I%@z-45KR-(6c z@w;XPlkH9XrT=F~3ve*M+%Z_Z4eyLy;Tb{NSXJSta_OK_5wctPqmanyATTi(X>%R? z3|0Z&=QC7588RCL>DA&UIE^N%IEA7UzvY}Cj{Vts*;z>gK(!;s(RN8W^ZX|)|D{83 z{k*Jo0fFxqpC{r-?n&=whG9!>Ns6=*1)TmL2BLo&eZyMCV+-{CATfsxi>K8Wi)-+? zUtI7&$g3CZr&k6&;uPXkBvglYBBC%@O~roGFu(lm^JZA&DZ2Ck_%rKYfauxF)ihBQ zbAb4lH>l<#XON836cR&pe`xo$Yv!x&Dk!{A#xOwo46y9TGNN>KbGDLdpLXyw=}CygiXG9 z?a#dMg^^F?R4EP}Cs0tZ#+>3yi9?ny+y^!jAC^m%h9hhX`;3lRua$)%Hb;K2wXRBCvA8x%rE)rqDxn~sZ6Sw9^Xy5cfx@Mm;0~r%sqOtnO!{5mPNenJ zu~2G*&wIh+EZvUA#^j10ru`w~9z^&EcLp0@YJ6Z^&FZym{g3MXv(9`KTizQEY#tSY z0she^(rDE`s!UJ(nhicPbR`d>ls?%~pD}RHC-+im`;*OxBS@GZKSn_Isv7Ta0+E5J z(80tWtu)cF>pB(S3E_-o~ z5+w2l2U1?+d?WF@7N+I-ZQ4RP1oh|RbdK%E+*Goj&4ITz!AwNY=BEZ~4oik36pr`d z|7%?Wh|etpPb>5JSn88q`^@8~Xm1X4$Rb33-e@>O7;5)q5ib-4@F>~4_7)aNN&GlF z^v;GEKCQk{ntwv{B;4yh1p~-neKs!`WkC;$Kc-3mr54F6B=i6qG?go*W_*V3W}k^x z&^?i>FxUI_*dESB->1-(p~E-AVuq&mrA~^XEF!n_@0QeD&@cl%1MGXd2uLn8NW>O& zjq(f}-bVt>im{QIYi#2&n!t02>1%)w8^if(4X);XcJh2q=R!+jzpQ%ya z+oZ-ZYfeK1c&ao3rS&<2&+@*s?vdJ0vxfb=3O2*Nf6qpo%tX{kOu`~=mY^F9q{0*y zAHnG5mp--P!03JUs*e>^`kw8sxxrH2ct~3K?V~1sL)9P8tfbt?4r=9VOiGN}l+B`l z<+*EikcV@z@*z;R-mDvXMdAAjSo35l%3ID{Kd%?B7^*8e8eFB=?0gE4Y$C(SLJP{)p7ZuwM{Wn zZ%~B@U~!(=BuNE04|gSZ@4`G*hM#|psFCgf-rg&yOtlv_8nOjN(_m^00L)CVskGe{8@i~Rdi!T?6xWs*kfGd* zK&Cj7rUu7dayJ6iq~Eu+`7etrEvT$h5hZiD2K$hS9JEEPBDC-#9;SPvTfMzM0qzu0gLhNa}?c zY!H~9iOu#QCD)F=N`wo)n&+_|+Q?JYsleaVEDx-iKHuX+3o!uX4@SS?A$Tg^%*8Z4 zm{xvhe<=~rs)`XV7^|Pk(%2<|plQq&U-9PcVKABB$#>mo3*<`Yq0K?QUlMfk4<_TZ z_a$H*>L)_?*kkWHcrN#x;ETb5V2f&l8=nf3|3TqlB!wNjGTv}!kau43y z!N7dV-0g`-cNnBHO0Vy(3?D&a7Yr#5$AZQ`+rgzqw9@AkjKDo{-3?Z658MRG$cA~+ zSr+upYxID-^sgdT!N(OnMzqY!g~qyQp>w6@ko* zPT9ZM$x7*%nW6EVQkUmb9y-KYmwfy*Nty*lpvnpEV`e zeXYcP!X62@q7_&tDV!X?IJ_UfIVD5)*cn@4^S2m`a=6p|cw}8D&X1DnaQj5Sw?VXH zxBCOXpS;4|eS=Gj;CYMgYS@#n?(dCS1QmdHG1{w+Ywll;AU#J087x5DT-`fm)}>H1 z`rjO5!M{%;4;hQey~UsSurYjI>galXo22#TjH!?8Xlc%A>2Yd1ql-TVH|`6^C3@cK z=I|}J{&D8YazzfQUC_bJqCJ@-G7dET=&Q(o~XsBY0

2(`HFWIIrK-*XIYfGjY74)X6) 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
J&N|M|wn= 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 sUA&(6Z?pK%Vt-2%>sOh;)f` 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 + + + + diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/UserInterfaceState.xcuserstate b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..7a97afe7b8a277f9222e6e0101193536144e4a89 GIT binary patch literal 17324 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 X`NZ-`vJFOv{K@YO*sFn$@+toh)m7|K literal 0 HcmV?d00001 diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..ee3458d --- /dev/null +++ b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/iosApp.xcscheme b/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/iosApp.xcscheme new file mode 100644 index 0000000..9c8bccd --- /dev/null +++ b/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/iosApp.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist b/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..fa59f97 --- /dev/null +++ b/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + iosApp.xcscheme + + orderHint + 0 + + + + diff --git a/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json b/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..41a92ea6e762fc71e84241b523441237d133b5d2 GIT binary patch literal 1494 zcmV;{1u6Q8P)BQ3DW2UV$vVBO^#MfH7=D?RxVR!i(}K~OiFBy zO)QS0Fu=G0DlU;}VF-c985X9dsMBb0so|E=pcr+(-Uv>2^}vzH7+9N`AqURK%?k zpoBkvM_f*(z`RRoe|5qXI8*fa8XG^nli*G16LV@Pt?}nItt|q%?QEfZL1RoOU@)bv zaOn%;Z%c6jK0JL49|X8- zhQrBPC6FJVIU$gSrrTh^qP z+S=jkS#uGhcEe*=S z*c>ujKHqoc5@L^}qnluLnO>njv1A3NsXh99OitY`n#NJfdo~to)i8mZPf_ipCSc>a zofQ!ykX&jCq3P-Z z&*Y7*Hl4Gog&m7o?oXT=#fGjl!7ez}{ z*i_$bmvr3^Aj?$i%e{bXTd7o7z7$2!Yq%Y97ca+XJA3i-pi<1fPS#Xm`Y#E}0C^rK z&0UP=#*P<98w&Gfs@zYLtff-fN+qK;mM;4rcj#;sy*0?rSQ>cbnG!5Z!@P_X(K=&f z#=*)8hpBOR>*;Tvd%wZ8|Fm+TP#OftHzv{~ST=6LfI_{KggW>hp)Mk!UOk9Vw^HP^ z(#3jMMA|x-84Ngu)~iDi(IP86>Ua`lT`Lp6`bOOX&oM{{i;z)Qt7#=!Do2dZlX7o( zMzYRMHW-kn!^XfFc#l>sUKVZ=ae$Um-nIuads-G)ZoZfiCUCqgY%V@2GR5-s zKmpmAC21Z*uJsEMNR}I3w^B+k320eUgN!@w{0J`}ET@v-b&GdMhWqqfk*sX&gSR5K z2bN-OgcyT>_^e_8N% zR?}pPl^3y%MMv=wrCpa9+{HS*7;!P)Hwd3i3zY_&OM=f!#3KdBYnro4C9By5TH9K? wIv*`SBZ4hQA9{+10F8}+((^+pRvN*70blgm&(&cR*Z=?k07*qoM6N<$g55CA)c^nh literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..41a92ea6e762fc71e84241b523441237d133b5d2 GIT binary patch literal 1494 zcmV;{1u6Q8P)BQ3DW2UV$vVBO^#MfH7=D?RxVR!i(}K~OiFBy zO)QS0Fu=G0DlU;}VF-c985X9dsMBb0so|E=pcr+(-Uv>2^}vzH7+9N`AqURK%?k zpoBkvM_f*(z`RRoe|5qXI8*fa8XG^nli*G16LV@Pt?}nItt|q%?QEfZL1RoOU@)bv zaOn%;Z%c6jK0JL49|X8- zhQrBPC6FJVIU$gSrrTh^qP z+S=jkS#uGhcEe*=S z*c>ujKHqoc5@L^}qnluLnO>njv1A3NsXh99OitY`n#NJfdo~to)i8mZPf_ipCSc>a zofQ!ykX&jCq3P-Z z&*Y7*Hl4Gog&m7o?oXT=#fGjl!7ez}{ z*i_$bmvr3^Aj?$i%e{bXTd7o7z7$2!Yq%Y97ca+XJA3i-pi<1fPS#Xm`Y#E}0C^rK z&0UP=#*P<98w&Gfs@zYLtff-fN+qK;mM;4rcj#;sy*0?rSQ>cbnG!5Z!@P_X(K=&f z#=*)8hpBOR>*;Tvd%wZ8|Fm+TP#OftHzv{~ST=6LfI_{KggW>hp)Mk!UOk9Vw^HP^ z(#3jMMA|x-84Ngu)~iDi(IP86>Ua`lT`Lp6`bOOX&oM{{i;z)Qt7#=!Do2dZlX7o( zMzYRMHW-kn!^XfFc#l>sUKVZ=ae$Um-nIuads-G)ZoZfiCUCqgY%V@2GR5-s zKmpmAC21Z*uJsEMNR}I3w^B+k320eUgN!@w{0J`}ET@v-b&GdMhWqqfk*sX&gSR5K z2bN-OgcyT>_^e_8N% zR?}pPl^3y%MMv=wrCpa9+{HS*7;!P)Hwd3i3zY_&OM=f!#3KdBYnro4C9By5TH9K? wIv*`SBZ4hQA9{+10F8}+((^+pRvN*70blgm&(&cR*Z=?k07*qoM6N<$g55CA)c^nh literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..ff64c69da90c62babcac97ed45364926fb78fa5b GIT binary patch literal 2137 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 literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..9068381fdbc416aa43d63ec7ec5523e41fdea683 GIT binary patch literal 2830 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 literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..455225204e3548b8203e41067cab015642edfaff GIT binary patch literal 3716 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 IM6N<$f}5S!cmMzZ literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd8c8f1eb962090ba571912d98f5f21cd4429bc GIT binary patch literal 3170 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 IM6N<$f}5S!cmMzZ literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..761f82134f04bcf3010fdec4b7b7a7e69c3b0b11 GIT binary patch literal 4420 zcmcgwPKqdTQW8o)>qq+=k0%#HXUNRJYb#sQ;LTHKUQX%GVe z8C?>B#Mj?H@q2Nf`{JH^&OPV3=XvoYT3Hx@8F(20007v;Sl{{|NBke?X#PzV52XnJ zfE8q-uVWkGyzLZTz+u299X!f2kP-4=K!ptD(Wi$|Vu~U+@;Eef^tCf6o6y%)qy=>j zK4xH>JaXQy@QXS|@6L6+4^!(rsU(AUm5(l?G&H^)nV;A?MB8Ped%-bgb<_kJwpIYG zRC7^c8-P~1OPZ*YQV(hX1vWeq>?f1Euuf>KBbAP(MmVqoK-)%xiHh7|Kv6ISgQ-ss zzjAC*@~`mH9jv!W%mLy3iYzOWArAk{Y5&Yslhkzm6@&l+ahsU9jkT71@C(gmS&j<>&pwwZ5 z5990t-KJmVa(PYGC5Jpv%Z;~LiUu&#SCTxUmRWNlFFTk8KI5K*-#j~(QVm+>y?FYI zZM!QXMJD@x%%%6V75{i@5ZcJT#;6{L7b)0Me$q0TW?pk)Z5SsxkN3O$I3*cC!Q4Q9 zt$!KBtE_X+xq3=W5;K0$FEm1ecSfan8`Ur_+drP}h5G$8q@dw;aOM^Y4g4B& zm}YIsYcj`cm+@bVQ|%11#B}-afX(ZCzSFBi0^gziAJtbVeqpMKwJ9hu(EOvp%?zx= zEkxtpOx&k#PW1|B`RW42geC$6Z2#&EdsYW3Tb`|-4^sQE=%kL({gbb!FK@t#XDCFX5ynlF#ht+6O9mKyhZc=Zbudaw!}n^$i3 z@Su{?Qgb!+7~WD*o{bh`<}iOXu=)2V2H3}JLq>9{PE05FbJ|H|xCt6*q2ji zL|r4eV!1y@PqTfL9by`Ir38ta2{4&%(kknO_@aw6Bgt8Xe?JqUM2Y*F;)+?-qc1If zZZXA{TqDJ*7nXgV!v1|oJmYBQQ@Ary_DDgHf5A5R_t;-s|6^O#B>=J+fp&PirvDVOL2xJ%D3{Q+0RN*{_IK%W?#h&n@*cZl|h@2SG`_6=V5=y zP=Y{zib%@lF`FhQM0VOB9qQ|;fqggmYYGGf@K z8|I5A(r)kMNaIx}`4!GLDfQXjevmE8+ zJd1kcNEb%_U0e6-3HC?cq%iYmu8xoNebNwp442BfDwUG4wEiv#cITcyVhNsp^gFv2`>?UY} zMhc7ryQy{m^<1_C_5;@nv%5BwNYKoJ^_y+7@^gpUT-qmz5-r>`BK|d56`EUf;ptFogEY(pOnV5dQ6y zZ~;M4MHg{c|L&4@ty>wO<(5_Ks)GM==69rf(F`&|2J_Fg;d%XCas>BRkpI&+7iX3z2H2B+D3 zGB#%xh8_%f6*(g?W1G6Vc!!iv8NkaVJ!ACb>GUIXm>eYZdvs#}W5TCx@vOP5sMv$} z@YAQ=hG!4|imj_xPWc(WPs+|{<{6au^T>Gs^&EkgO_zv{hmN%ci92F7wD+hJsf|jo zPG>NJC%QfPt}vbOQYT1Sf!af(AQdTTACGSygOTDz9YbeCbeV9*8ycCj?x6ma&(lLi zPqz;Jd1xa-I(D4>$^w}@UY-%MZphZz3rCv#yk@9Xyds^dDrTpu?l-yFV#RjarPh$- z{NQ25r7<7Z0W$_1Ap`R-r1@pf7r2)>OyU)FW0=>5U2D>ha#xl7CC&vFkiRS5+%#(pUPhrCR;`ZY+F`y_$`)Yz$dRKxPe{SL}axIUJf$TyrUZyyvmB2M4hTL(~oi?#-n01 zt{H@Jjk2Mfa#ftteb4dKwhMJNoHhA(4?YB;We39u9oACK_rgR#RT)bV7+ZO%kf@zV z-qSzv(prt#VLMzM;L$fZXN;WAsKYZm7~CDR7juW4BRbpXNcTunf-gh$(m#OA((+yk zP_y=?krwB+MCZM-_VG71wwL8=K3+Wa@V2-zlHXKjWhoOB?*9bMN{_1PxNx3r*Gkq_ zGc}y2lz}!hSci$6cGs7O7HCr@7XsCijrVxlCj)Xv71rG!RGojKK|PlO2xle8ms%*f z7=Cwi=V#mZ-hc*-1Nqwxgl{r27pK&E_1)f%lMl;3o9^XA%YM8IzK zMCmVi2!mEg7h~^>3xs)zYT5n=(4p3^r7yqGH28bq=|d_Ux|dA*Agu%L6K=i9=^zSl#g@+g zj2-<3SU0t)I~d|1s_q*B2m>bHmbqpAoB$BU2AJ1KPnrk; zEtZ~-m%4mXQ4)EN*F@h5dH1+PZ2w)=gwrr%!^MqZ+SF7tTUM@sPjQ)WN4gqCR4YqL zP8Vl9sK#r|fNx;~0(4(ZS&WGnFa$CabLmZCH{6k8HgJuKu`iwzN?p|F0gYu^6jx@{ z=h2>N)#~Awr2(6qFG!e`>(k4g-mT1e*tVzq5@9N;iA_{b7DdKP3>H(FCChhxf1OL( zxTz6y`{|rXdZIn!pH~YBn;PdHdGNSUJi!r{w5tECJ&XP_u;z~~73>?fzctWhmO zI({%)be~T){lhoV=J=B)9A%^hw#Vm-WNqXykon~;x&J<;{s`ut$fBlpF*8g+mFc1M zkk3TA{@&hE-p*v=Ccb|5OdQE69WfEL6~lv(PCUWI(n z8T7*mg2;~fGSz=??g{;R8NyL~B{s`LKme|~UIr&0lTCHClzpVABQE##rugPZsUA!Q&JraHU5wY7mx}=6TQA?MUyK<76Dkx&Y}zA z9`yjV?*Oxc9HZGySS8Y_jG?DT4}Q-!-6Wyu5Ms-t`|gGfTOe9imOl&?wna!*DA|q> zD_(wBVpB3>T0u(VMbtfWZ*M2%lWguIHkYznu_f@8@HiuXN?)v@x z36n^1uZJOr-Wy$!jegV4h$We~Iv`!o$B;xPQa#NiPRV%9bTL4<)7zAvN=6L+JgJfK zL48_^U{nG_c-e`ca&x}x%@3rWz8|a0ITnfH$!h*|EJsQR3sVuD0FRy`IE*Az`6Yjd zWs|`NLAnd5YqVQXf{nWw>BOl8unoD&yj!uP?y3A#ohzvmZT6g5zcxS4e8FV%QBOFe ziCm?>^Si*yvp{+tn|aGzmH7t6-GuL)!ayKrXj!Z1l^rsg@6#*#i0MTm68}4cKBxfA zh$Z;`H92r6$DM_A$ECm#Jk*i^&N9_Knr}^`r3)Qq^}5aE;ovlLYJ&Z@{F# zem$+7iRWaeq*2}CoXayGkdd(&t2{><>LRs_MeaDrH*-K&I`u0IspEPrCKw;Ox)Fhv zrSIh1KeC=b$q5yEWXDIn_O}-NyCB4lvPi+1N=OINP{=ikZ{I(?s-j%Xoi7Pp+)MkS z+2S$U%6Mpggi+r1wTiTK3_KT1CS$Fmi8_#;*B>|1XYgUcEZ#WBgToG+Qh zu8lf|;ziqa4~;t=!mWSc8;%4frBuqE!$Nb#dtP7bST7+JBXN^QAoaTZ ze=g4#9h0TlyjF}YP^Z36#Ht{Jm7~dU&z> z1pMur6UmSxX>53R=dg3{dSIZSB6(OUj1&|@yHV#7qsTpW^cwO4nqeGxPFc~%6hzT{ zX9$iJ*uBh9z!{3~4pzIi0q$1}h+hvUZ({{x0qSlR#p literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..41a92ea6e762fc71e84241b523441237d133b5d2 GIT binary patch literal 1494 zcmV;{1u6Q8P)BQ3DW2UV$vVBO^#MfH7=D?RxVR!i(}K~OiFBy zO)QS0Fu=G0DlU;}VF-c985X9dsMBb0so|E=pcr+(-Uv>2^}vzH7+9N`AqURK%?k zpoBkvM_f*(z`RRoe|5qXI8*fa8XG^nli*G16LV@Pt?}nItt|q%?QEfZL1RoOU@)bv zaOn%;Z%c6jK0JL49|X8- zhQrBPC6FJVIU$gSrrTh^qP z+S=jkS#uGhcEe*=S z*c>ujKHqoc5@L^}qnluLnO>njv1A3NsXh99OitY`n#NJfdo~to)i8mZPf_ipCSc>a zofQ!ykX&jCq3P-Z z&*Y7*Hl4Gog&m7o?oXT=#fGjl!7ez}{ z*i_$bmvr3^Aj?$i%e{bXTd7o7z7$2!Yq%Y97ca+XJA3i-pi<1fPS#Xm`Y#E}0C^rK z&0UP=#*P<98w&Gfs@zYLtff-fN+qK;mM;4rcj#;sy*0?rSQ>cbnG!5Z!@P_X(K=&f z#=*)8hpBOR>*;Tvd%wZ8|Fm+TP#OftHzv{~ST=6LfI_{KggW>hp)Mk!UOk9Vw^HP^ z(#3jMMA|x-84Ngu)~iDi(IP86>Ua`lT`Lp6`bOOX&oM{{i;z)Qt7#=!Do2dZlX7o( zMzYRMHW-kn!^XfFc#l>sUKVZ=ae$Um-nIuads-G)ZoZfiCUCqgY%V@2GR5-s zKmpmAC21Z*uJsEMNR}I3w^B+k320eUgN!@w{0J`}ET@v-b&GdMhWqqfk*sX&gSR5K z2bN-OgcyT>_^e_8N% zR?}pPl^3y%MMv=wrCpa9+{HS*7;!P)Hwd3i3zY_&OM=f!#3KdBYnro4C9By5TH9K? wIv*`SBZ4hQA9{+10F8}+((^+pRvN*70blgm&(&cR*Z=?k07*qoM6N<$g55CA)c^nh literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png new file mode 100644 index 0000000000000000000000000000000000000000..761f82134f04bcf3010fdec4b7b7a7e69c3b0b11 GIT binary patch literal 4420 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 literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png new file mode 100644 index 0000000000000000000000000000000000000000..276a950e65922b414281102ff5c13fd6eff9bee2 GIT binary patch literal 8223 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 literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..9e23219b3306ceef03000feab0ec2af24a384527 GIT binary patch literal 7382 zcmd5>Ra6vEx28J;6r?4G7RjMSx&~>6j-ge$lvGl>!(m3cyP2V+8|iLlND%>P`2FwO zeZDXEVW0hQ)~>VGUT5#`i+&4IAtjeE7{b9D+e zs`p>1^^zL6ezJ1wer@fzL_dzA?>pBn1FO#XPCQ}I!?S(ced)`zuwOjYWcx&@&a;}|%uqEEW^kEg<-aozAp{K`WyK&}~_ntUO`R$Zo~ zIBp*iBGxvTP)zJK=NBQ<%Y}qg#2X~fe;ZDC7sk>+eH!AV4fbHhlg0&dqA(;QSP?;GU$Z9p-)|-ZiqS?hZwA8+w?N`3l zjy@4tl3^xNKf>`e8nQIK;Z$KK_lFF)#$m?5a0fGaW`CsoVm{_c*J8sDLZRvjD-QR% zp|pC-luh3BCA>%-aN)l@2^8{!PzgvTg|c%EVN@n_85U6QTJ03@Jk^};HxaZjflB~R z)}}s8EjLxrr&FFjQdnP<)gK|hSd3ZSPO44sb@a(2!1@h?Nt-JGY)rHeDgmoX$@kcWOncilke%RwZWHS27&Br`6 zb5-=dQzU+#+mibiOOWfok<6OgJ>QR}L&P`u{1-O=Saik|{;J*8GP&E{^7k0{5&S=y zlw!JefsglWceZ1yQrXD(?WZ8iP7K*<_;v=I1e&j?E@C;AMr2Rf2F+axHS|DL}<(%FL9Uq1aMd$E%HnK z4SKo!_bAEy<})t08MZ|Tm967pBK=dGKCMIV*`xX0(q|f)wp5H>Hl_K63TX#ZWxCHw z^@=L=_1_wD>8PtS1+_?gOuJo^<8kzLuCa+j&N>qD1nYTQ2WiAsw8yGbT)_pQ!LD1N(-i+Fa)!i=`5?Xo zzF;}5qj@5$5Qg3qS;f_IIJ-p7ZT6h)vA9&>;?B>XWT`~m7%rYR2K##T@elRczw>%8 z>x#CrQP^XBXa@MO!guXX zsdYk#Y}|HMOIT^*8$YjsSg0_CM$YQ#ok{VaWp;DYwnnPR>cD`!iwJz9>DqN<#@i)` z;>8#csLkb_I=VM!d63o^&W}J!>J+(N&BW#mt1$8>z@{yh45|bQXGl|zKL>jaFU@*P zBZTd4FF)1YyA$OE_jiN0GpB?QXeHg<5?jr$9|SjP_1d3M`_>Zyh6kH+#yFUZ2>pZz zMqu@qd6kxaLisb=Y}*?JhK@n&-8!j#tk0BXDCgtCg8!(C);u)pcv?Gvimfu;IeRVr zH;S3_&Gda7S(W#_)ZD4ftCIkfRxq6}(StMHoV553U;Ye?Yy~N3Nb$$F>A?U8pqo!MUd*fYs{7IG!UT=@e`DJg3i}WQV)V8+E z)pbVm0UgWvd4vmWy-D+am9JjzQ4_`eTyCLBNp{}YpY_EHMN_Q=0n(=xTDTrsv+bTc48Crusc|n|wjj(sWzk`2#*SfbCO3%M2vE359@dekT7}dhW z2fvE_az@9Y?N?!kPnFJD1?HgP3VmZ?ZCzbD|CY%ysH*gVtMgke{fEV~N@SCDCCPLF z<&Q`uifz0S(uDFSIZ0ARm9(@G(LsL}x0n2a_T~04a}98? zKmTlpfG|LV9RuQ5ybXy{n9gFz-J(~3Si9;&w!gF5-|ZI@8SPie-1K;{|kQ&&0>QJKT{XAXz0&JV!@$(|DVx45Xb z{1x$TTtz6871pF;EW>mG6@$Kk+{ygBoL*J=`rvg5<%pZ}DM?RJz_v4SM+P0dqm!zsCR|8W@9us-K?I>f`fu|vLF-^c? znF!uxO%2nhKMR|;jQR`%Y;Sl;c-C#p6j4h-Eaz-m7QWQmKB&7S6qOplDm|)Dxw6wu zG5T_C4byDD(^~vcGhDsdTFLHiYn5|1CvpFTW;}^QopJ;`z3T~@+4T7ol?0SC zr=m})5rEe3i>$Qx=#Ugp+_1(GV@LT z-WxmV;2>@efIU%_@a>o?tcDgLS`7r_LA2u1W$+2SAs}#bC!ij|&pTw0o9gwX-_yIs z6NXRf!G|;W?GmE7ZQnDbE|Qp>*}-UaRDcn` zx0=Cfu+Rk4Ni!`z0B`(r2MxeGedIRLcx3h56J(zh^Sb0Uqtu166937&H7*fLH<{0` zX|H`Ih|}ta3|k__H>a8{v`W#e=5513pnK0-g;dooWqI|iyZr&7-(yBlA66etuFeTP zD-+*b{g*@-yM-PSR5lE8y6eShUKtXe)YZa1nU@rGv0tVeZ-kg$Txt4z@=i{v&k;s# zx7m`3)bR{_QxFPH=(!tiw)DhuJfZW3coeUJnhSyB#hMj&oN#xyEx9m2^lvksFwloM zfQ-xdP_IGQ#Bb1jN-3l8rRSN){rjOGC9)jkVu(P7ZS0JZ8pv@~rw!|Tl>^h3+{!BK6zz2);!&EhA{ z85N%~FU=6YP`6u*dzH`|H|=Yle=isVyjvOfxGpUQRI-ih#&O0AiH~6^3eU#P@?gqw zhO87=tJz!-H@{0CTMy#BZ4|kxQ6Nhr;?PjH<-lii0{*Nc_7OWMtkCpSjQP&r+`pRj zn4i6=RFqNuuix^X%a->pq)?>Fpz_IgJ>u}dG^sROPJyq?!nFA}RRU6a8Y)?woNx)1 zslB#*q5e%+P5Qk7N31oYG7p>hC^(4`Q^|;Sqe`40k|!a^EXwSf%Oa${Q#sl~RY)Dj z@xzRHNCiiX+gzWdYmpt3z#HH>`AIt!7-_i4=V!D{t@C^a_xns=bFdvUpfucmX}L+J>dlTetwe>v%Q6VJK_ji()xo^NItW zS{-Hi;Z#lW=#Xc_hBsl_OUi?l3e*0G3F9eIKTF#elf#*zyJi@1?m2kw zQ3z1ZXd_6HpG7}!s;^UEi^KqEOE*uvaH{GxjUKik9my#aU@s3?c=QmiXC$OTBhR7J z#mMjeli}NyOfE|vGa;nq$hl*zedEFiZ@=?89gRMnKJimL=n$O}RJ3}exJX7W zd|PbE>$I^bK$AM*hvcw=E=R!9b+73t+lrn+zjT!d5TVuFsS>mKOCNhw2}qQ4HgzT- z$DLfe7E&MGW)W2j;OQ-lEWdb15d{G}=XQH>APM%Z()W0>xoj@6@wFr)Nr|8@Uex{+ zA#HlJw)4@0UEQv~W4CoH?q3?uIbHA`hM`@Fm)%R6v<^O8k2+FRDOw*Wbbpn|s5jo# z_xXF|*KLA#m^Ic@Oi>+nv^>w1PA(9=B4U@{A$y}auJ(7K;v2mHVCCU8)}a}zt|=9* z?5n2cAPY8bMSZ@lIyTcP8v5-mSLTg33KwXYU}Rv9Yho8U5))u8 zM?n2ya<$ikdgQiZ7w*6CuC%jCSpomc&k*5G^!X4-jeSlu1dF0)P#0gZp(LCRLd_Cw zhu#$jM?Ab6%}P-ox;5?8+-u&yN)q4L*^F9{UM$OB97{H3QIWeR_bjkYN6BrWV*${< zz1r)KbO$S^nq3;sPNLge(cgKzFDFg6WK24OPw0}=_c+Pq{t!WH7&@0fB?`M^OqkmD z%8fbM%N{}bc?_v7C`ZO6v`1nlVDFYCM#`{*5I3<@6kmT;JJ zi$@Y?a@VSEVAt4H*F=Ep{d5itDd|5@acqQ?_4So;zM1J+;K;&z0w+WASR-uLfKraV5pSkltv7r?Q9sh2GInKTNBQ=qs5sig$*r$ zGYlN8?I!=u-(s ze=Nv{?a{4DEXwO~WH|qQ@(e~@jYE-luvF0f5#l~XJ9y&%%T(IPe-~YFpp()TpRp09 zNgd=nvegIcsIkYpc8ba&R;P`5_wb=vVZ>6D0BWWy`yUlg-8`f6TLbgGKM)p0R;L?Z`Y#pQi%Ws1r< zwfIaGURz#^0QZSfF;RXt5~YHfFw=C?_?_gng5Z9#yS;zReKb)GHUnZ#8NwDoLt`A< zy?wEqoVX$6e1{@cnOenogC8+SR_AcmvG#8-MEsKl|B^-{)3S+z*TrLDRVyFXyhXLc zM5puhuX<+wmm;Qwy4!ec>!$G zTl_#B61aRetuZOviYzH-yvV!_cDnCJ(ixxN58jHS{BzIKgdjHS?4Zfa#!N%Yf81U$Ikc2eo=KORNowrmjmH_cAv)9fmRoC)-3aC3|ffw7^Oj^Drw6mY~L> zlCEt}C!cv8gTINXUhb!a#k*xat?pKf7~6?&PwO0nDMuoT|DN@X;@tD00<+iEWOP`i z%*tq98fuRNR@+?ukeuC+_{hr9i1^0l3Jfc%_^WgFx%~UkOpfDp$-HQC0Uf4Ir6d{+J5PMxDK43Wa zSXBCT`ngblN>|sn1f5M*w{Y3nHa(n4{o^<3w`bgz1zlm4IIOrd*5iudd%u!+LNRgR zwW3L!2A5->aw;$Y@KqxO)YU%Ewsujbbin7CnbAyo%9P<#47;j;;g|j{Wz+Grp9G9G z+PDCEJm|01i<}P7CzRs_5L}?nlccoB#`ldeiDTG-vE>>#A#46~ixhz*_u*37VIMex~HLL>#)9pWEqtSyX&I)F|=k(Oe_OJWqaw zSo~X>Q+#bNXeNovo=p7n-t4 z)kK!DmQmA4I(G($BhlqB9#FJXWnd8(J_szWJrAVgX8nQv!kzSV5yX*#HzC&)=<7L- zIWa=4z7s1kO)$?YFtnV0$RWge*cC13QDDE;;+63Fl}qO$Ex6aSA&S?uun-ms{}~eI zvhMwS=VNK8XO{hj97KeN+2B{{Vcd$|{*=R9D3#J{bL_r`828?j1^Lrpd$!lyW<5C( zrejLqBP#Mm-`2cRc%cmEh>^~<X|BY4gNXi-LhgkU`z*S;kH8DM($Dzq>?Nuw|qEf)Pt@oY)V>ULB%D84lj^$g< z+{a>Pvi#YP3HPv;+ny2X5rq*N4m%mZH39Aelyd)Dn)t!eP26Zz{R+)?>?)^2MdCIc zmGQAvbG<6i)1=|41BnFO_(Xs-&n6?buVGQC5_!m->9L~mTePL!+S92-RKDsZBTex> z&(B&UgLbD>ee246fx*hH@Wx9G>Oog@`+K@?Rr26l@I+-|?$X*$t>H1%l64DNhbm?2 zX=G4Qd-&B!9`$&7sz;(J(Y^xfcgT24T!~chTMhm{vf&z9Qu-^tc9~yqzheM$m2FOr zhy)%cRxlte;(LI^zf(0XlSMULuZajI-eL)FT?M+#{lse=U??KPL^yEn{_{ZuLAPprd;c?W_{WY;<`m(D7P#5um$9Hq)I_nyi`6zG%aVs|%w3ba z^mVA9%^os|S&&vcLC1xD;EAdBX_;-e-e--d_@zroxZ}jBPf#Cdwsrs)=u2)4jsx>MYH)j0YEa3bvALqqXPK=;+t?_s-g~1G>Ft_9XddDrvYuK=SyvmdwQ7 z1tx!^CEH>=re29rOs(zhC|kT{{fv)oBND^%cdqDy0zc5|PE~PQ?GBHvFivcXuI#;C zoAay+r=_)Z&bhz01OFkIIr|KW_ zR3UoDbn8s^I4=atb|<}6*lrw6ziqO0it#4mp*Oz0ATqt#xR>VO*pd%u8-t^|Y*fX9 zeK-?W##inXAf@-ZuUk$#E{70a@zqD2ra$?|>w$UeT(S1bVp*e@Erk0_ovk1j?>bGZyBl#@;t?YsU@zrulcskg-_OdrkYQ;Tv#8= zl@8hkS-(cunP36Wz?eScdLr4=rq`m}HrNe(f*h0qtW*@Tv%tewjx}xb|Dbl^+20{q zVZqwP=M_3qdC!{(y2Ct%2`!BqhCFigV+l86^Oa<8pEdBcC>{NE#+G zeh6;e;$VH`{>4K=P5>#@ezaegUF`7HR%C0j=#D%|Ot$jizYaF-e5_KfgZUwomJB2Q z3Q=zYe`+CGu3un6Wh>s$p}T&DWwxb-WPsdjv-3qjBVPL$pp@)7-zQ*I2pc#|+dqW{ zp2o4?w8lE~+12sh5{ICQ1S)%E8{+m===quT<7k^+)3KyX90aL;an zkGX;5)6b$U8nc89?Hw|)Wltd3K&_Ds^Dk~lwAViUD|yqf*qiJLIVW0^0$VI#jQ*;U zr|>~Ir_Y{U(H`yDX{1g&!j-aXfB9>H)xXt)Lquyl`$mQO={uGVHH>0cUP{!N(uf$MO0x4F#vHJWUzDR04 literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..761f82134f04bcf3010fdec4b7b7a7e69c3b0b11 GIT binary patch literal 4420 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 literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..59ac0abccbdf99480c75b05f7c73368147714b85 GIT binary patch literal 6476 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 literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png new file mode 100644 index 0000000000000000000000000000000000000000..ef951ed2c218c78916f6ca8b1efbb62217dcf885 GIT binary patch literal 67276 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 literal 0 HcmV?d00001 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..1923af1a67ad838c5e7b2e149a691e50dba32689 GIT binary patch literal 3193 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 + + + + CADisableMinimumFrameDurationOnPhone + + + diff --git a/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json b/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/iosApp.swift b/iosApp/iosApp/iosApp.swift new file mode 100644 index 0000000..0e4b303 --- /dev/null +++ b/iosApp/iosApp/iosApp.swift @@ -0,0 +1,21 @@ +import SwiftUI +import SharedUI + +@main +struct ComposeApp: App { + var body: some Scene { + WindowGroup { + ContentView().ignoresSafeArea(.all) + } + } +} + +struct ContentView: UIViewControllerRepresentable { + func makeUIViewController(context: Context) -> UIViewController { + return MainKt.MainViewController() + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) { + // Updates will be handled by Compose + } +} diff --git a/libraries/play-licensing/lvl_library/build.gradle b/libraries/play-licensing/lvl_library/build.gradle index afaf0fa..5f9aba8 100644 --- a/libraries/play-licensing/lvl_library/build.gradle +++ b/libraries/play-licensing/lvl_library/build.gradle @@ -5,6 +5,7 @@ android { compileSdk 34 defaultConfig { minSdk 4 + targetSdk 34 } buildTypes { release { @@ -15,10 +16,4 @@ android { buildFeatures { aidl true } - lint { - targetSdk 34 - } - testOptions { - targetSdk 34 - } } diff --git a/settings.gradle.kts b/settings.gradle.kts index ed52ce9..0481b86 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,5 @@ +rootProject.name = "ScanBridge" + pluginManagement { repositories { google { @@ -30,7 +32,8 @@ dependencyResolutionManagement { } } -rootProject.name = "ScanBridge" -include(":app") +include(":shared") +include(":androidApp") +include(":desktopApp") include(":lvl_library") project(":lvl_library").projectDir = File(rootDir, "libraries/play-licensing/lvl_library/") diff --git a/shared/.gitignore b/shared/.gitignore new file mode 100644 index 0000000..92e0b0f --- /dev/null +++ b/shared/.gitignore @@ -0,0 +1,2 @@ +/build +build \ No newline at end of file diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts new file mode 100644 index 0000000..b7fdc16 --- /dev/null +++ b/shared/build.gradle.kts @@ -0,0 +1,69 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget + +plugins { + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.compose.compiler) + alias(libs.plugins.compose.multiplatform) + alias(libs.plugins.android.kmp.library) +} + +kotlin { + jvm { + compilerOptions { jvmTarget = JvmTarget.JVM_17 } + } + + android { + namespace = "io.github.chrisimx.scanbridge" + compileSdk = 36 + minSdk = 23 + + /*compilerOptions.configure { + jvmTarget.set( + org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + ) + }*/ + } + + + iosArm64() + iosSimulatorArm64() + + sourceSets { + commonMain.dependencies { + api(libs.compose.runtime) + api(libs.compose.ui) + api(libs.compose.foundation) + api(libs.compose.resources) + api(libs.compose.ui.tooling.preview) + api(libs.compose.material3) + //implementation(libs.compose.ui.tooling) + } + + commonTest.dependencies { + implementation(kotlin("test")) + implementation(libs.compose.ui.test) + } + + androidMain.dependencies { + } + + jvmMain.dependencies { + implementation(compose.desktop.currentOs) + } + + } + + targets + .withType() + .matching { it.konanTarget.family.isAppleFamily } + .configureEach { + binaries { + framework { + baseName = "SharedUI" + isStatic = true + } + } + } +} \ No newline at end of file diff --git a/shared/src/commonMain/composeResources/drawable/ic_cyclone.xml b/shared/src/commonMain/composeResources/drawable/ic_cyclone.xml new file mode 100644 index 0000000..f1c45b5 --- /dev/null +++ b/shared/src/commonMain/composeResources/drawable/ic_cyclone.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/shared/src/commonMain/composeResources/drawable/ic_dark_mode.xml b/shared/src/commonMain/composeResources/drawable/ic_dark_mode.xml new file mode 100644 index 0000000..0ce2444 --- /dev/null +++ b/shared/src/commonMain/composeResources/drawable/ic_dark_mode.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/shared/src/commonMain/composeResources/drawable/ic_light_mode.xml b/shared/src/commonMain/composeResources/drawable/ic_light_mode.xml new file mode 100644 index 0000000..b7331d3 --- /dev/null +++ b/shared/src/commonMain/composeResources/drawable/ic_light_mode.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/shared/src/commonMain/composeResources/drawable/ic_rotate_right.xml b/shared/src/commonMain/composeResources/drawable/ic_rotate_right.xml new file mode 100644 index 0000000..1810671 --- /dev/null +++ b/shared/src/commonMain/composeResources/drawable/ic_rotate_right.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/shared/src/commonMain/composeResources/font/IndieFlower-Regular.ttf b/shared/src/commonMain/composeResources/font/IndieFlower-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3774ef55d4dd8d0d272f602542bbbf444ebbbb23 GIT binary patch literal 55416 zcmdqK2e>3@T`yd3RdrQ$b#--hcXf5nIh^iuI-Z>4TO35p+v%ZCeGWkEy)L;p>+^iieV&h{r>d*o zdh7rGb9(!5jN>>T_b4ZDSJ#$TRyjYrkK>sPn7IJ)=m_$cQuz2N>& z?rnX5Ehy>Q{78_$3Bke+n>s{GqeYzbbqW`#8q0V|?cF*@rfN@SB@|&v7Q+S$N{=mFqX& zHuuqg<2dcxn8SVb+UC{7)(i108^w4F9|rgYE<|UyVwm$1VE=FUhVS@j_8BhY8)N6_ z+7ldC=iY}ik(2BAl397-#mKTV9+>+a=i)w$d-OENsq`pU!5i>AX8!Um%qTv*^~lys z#53Dt?1A(To~EZ5xA>Qb?=0NyoBkIrO{n9z-~Nd=eE;yc^~fzvJR^J=-xZqN{-419 zl)V~n=J?;`-+(Kxa*ph;xeiS^9L8~P;keczj@x5Dg?}>mA2-is{*8BF6TZy;8JB;Q z?z89ddua$Da;6Y)H0`y}QRMy+-^X!Zp@(W|lK=&*pN0Z+`gSc;KGqe+w(KI_t6twvS!FlmE^~_>c0RNj;kS zdM22OWD)?fl$qG|B&fFa7h50N`i-p*Zhc_u*S3Cj>%CiV+nU)b-g?2Ui(me&FW>Q{ z=`T%uY5YrrFLl3^`%?6a@A~4*7Y?XzlFr&|!At+o{|8bx_CCS651o1^W3N2@1l#)l zC%Bg--^;l<;qJRep5Ry`lUcdA{5ZP@U-$+t)Ur4e8kyC{h2rXwQ~A@G$1;y?-1k^! zHFM$YeUFPp`-mHxkDYF19_Nmpx`=;|oytBwe>(o;>E`LvlbA=OdGH8^KXw{3Jg_|j zj`pS2cQDA+*qeD=C>=U=_|)T%F2^6AUp^hrW-}{~fAG+$$3M6n&z?SwQPPu;0%GD` z2WA;COEuhAoLP>ZdVD_qICuK7$7s%@r}EjyAARhx_+wbd_V*{a4?g7rqH%osnACiAf2`XWVqfB&iO(eOOa5|-Pi>}tE$vP} znEo)h{9NWYv&rmZIW702xliR^k^epX_h*Gug>M(H75}mnEB$=wE9Fb&=U1%CV&#Eq zuDV)1QvJi~7pi|#lWO-ER$AFF?{{_Td?FdB(QrO|E7H@-9Sx6MbI zFK@oK`KIPCHh-o0q2?!>pKU$bdPVCeT0h%*y!HOp$3_#QZySBr=m$nWKKdu4Umlwr zd+XRQjs5D_Z;k!o*caL_>nwLZ)cIuRvz@PYzTO@0KDYakUb^@8-V?o#^nSnh=e@t~ z{d1r1zqJ3#{u}yl>%Xi2fkAH2983;Y2S)~Xjq~G=jsMvA&y2rg{C(pe9sh&z&yRm? z{F@W}#2Y7zlVg)JlN*!AC(lkkG^I^FJoSB3ubTRAQ$IKL?x|m&`oz?yr~YEDNzxb7pF0ZRV9Te>&Tlotxd9eeUcRX8&gPTXVvkZ!SJpp6krb&F!5#Irp}? zznuH0x$n%o=R@<^`H}gF`IY&@^LNf)oWD8$l7;NThZa7$@Y#j0E_{9A)}p#-E#?-R zi<66gy7WCuKd|(pOK)EK?@RAl`tZ{4E&bWjUoCxOX=~ZD9A3^Zx0a`t-@Q^<>8{ML z>{~gta^K3;mG52o!Ijsoyk+I>tBKXhYIpSy*UqfnzjkfyZEK%jm)7&^C)RJSKe7JR z^{=nr+E6#Fjoe0aV{&74b=aAX_W4h81~jND1UWZDi}H@1(s&-=DMhk3FXYjAJpeC$J<#lDE=&f#7jpQ~IF zpCJEzclXJtTnxr10bC@pmLMO(Si;RY z&d>Ysjzf4SkK?Owd<*9M#MTzZ`7u7oeiS(PNgO{6y#Evz-o|~1-Yd8<{smkH&l%kF zxiID`upj4E__uR;=H~)}#EI+?E=RcM|ClSX63$(mf_Z)LASCWnTmR0%0^r>~_H(d_ zpXJ)@W853Kj|1lz$G??J@Gk`(mN^L@4Y-fkcqiOHHc^|7nlJtH z=*e|#!$)$DPnY{D7v_G78)GN9yC5G)TONH}+}0U*&r^?2zPAMV^FseYH*S9-q&w-u z?&9`f?ihP?>!Ub-kiQNc34MoW6QnEoZ*6Uf4`cn91LJP+y{&KYf4TLop;Nr|Zmt6g zf7kyg3WB%Dg9}8?1zDG&hoLVx5A>3k(*cdaK}UevCgKMRD~oVZF2=>7-;!L4OT)9x zayc%~6}Tc-;>w5vs$31xLxUUPnp}$;<;J)+-rnVUT%Q}jm!9AzxhZa%o8e};Ir!xZ z+#uyi+zIIVQ`~9p40i|j9PUo; zF79sb9_}o-_pRK^xbNqFjr%d~uVF`C$^9_*M(!85pJhDv81&Wm!Poyf_YLkxxF6?! z5RuF0xqsr`#Qh@oFWf(K-{gLV`+vFL=6;KN2X`-bj(atCANL7vllvI=aqjoH-{F3j z`y}^2x%;_46f_kpvP;tKjHp}`(y3`_cz?%aX-X80D3*hJ;Yt&E^}|;u5i!g zu5#D7>)cK52KPMfVeV_tyN_@$fQEk|_q_8O+ZDEXYh2VipUt2#c~9i*w)R{ufKIBulY0%djlV zu{X*R=V z*&Lf^3v7{loO>r*V#{oWt+F+?j+kc;+spQG|AsjCE8JhQ{p9HoVOuWdeWQ#xxOE(rcNSAi_c@1U zyyxrBo7*p3abCD-AJmm6pH?@YJe60r!Ps<;(uyf8q?c9}z9y;p)tDWEV#k0Qitmnecxp?8;v)81J8y7F#w<%q;5Awxr;5QuLFFM%T z*aq|BHn#TcOyYT9=Um&n>#f>@yS_;K&Yrt@V^g|hAGCeDZfTcxeUbJ#2)JY)#C=$u zcnSYV2b||GJI^23^@w(P*B9x4^ZaE8ftSxxQsmkdaD;qtn><&xS9s7_;T8MfJ$T{f z<@0B+-F)cM*_$`KS9X7sjyUhW=DhpJuGeYTc72hKIPbpZ9F96qUAGUOqdQpgT;Dm@ zj_sO2yRqwwbj+FNhI2UXQ0b;arQ_Rcxw*ZT?dYzhYu9&ukxrh!b{2B`uyZ(RKPo+JAKWMJySRC6^ZLc>?uUnG(rIVl z3+#iqa`W01&#vhl%jbozN0v%-*jN=g9s%ImX2m z@`3H^5@+T9efwPDGPytBK6mdrS2;fS+3o8Z*Ui0c``nwm3XAB#qvMRSL>FK&Zoqm> z!g97?LC(RBT*UVqIB()}5jLg?3v&&2s0Hh|3Ol)k?^j`6Xykc&h77FmIoRP0EHByL zQCQ;)Z0beWsC!}Cu3;8L1hBT7nDb%$dl8n4o_g>pW6s|;qKR3rV2&z$1J(W?qFe$JxWM%-8UIW_!dX9M9qVWsKj1mCe9DUdEB&$zc2id+brz|9$v= z5No2byJy~a+YGd(6ZX@D7kYaJYi-(}49<68yZy~WcxWwG@uUL_;pGypJZ$6YtPR<4 zam+(vmPh7O2r@I900z4KvzX2)|9RC%X4)IIJk^d|I(VKT@ zaR}bo0ef`^aXf~zeW25lef22*eI`m|06TGE-+p!zIJ*X_6JHSj5qFNlC;Y#=N_zVt z_?Ro8+EydPJbvE+|l zfuFhw2_#)YvNMF@CT6{AKTER?*S7O4>7dQ+c^xU+#LRU6nmyMLlCzlmtPSl$fc+fi z8cGq#-(}$OCXUXk>8_(oX#JOQop3?gh#(t2=RoMd{yf}w@Ig{`zYPz zch<(!!#0c$Vw9ub9=5gBIsChW8`515VLb68>3|GixPb4pX3|l^`H50PNSr&)oLB9! zH?RiMWArTPYvP|By>Mk4t8~9<-`mY!4u8;_h>oOz2&N$&Zr5D|(U3CEDAGy}+&A$Y zK}HxPEZ@YrquuDrLztPq-@korXJyVx9mfQY6Z~@`>9G-X9F?{1?dnU(f5TBEt z9rF8--p=#HjbsxX?9i&n+K|q6aI^`W(7pTc-|*UhgbRlgT38d=tDUv&(3wUM9_Zff z7I4Tp4i6JX2p0sqLkD__-c1y|W@CoNT*e5JccS!AcMNemr1lWE&xVnw$FuWxde_rE z@8IzQRzp4l>6B|WcR83HLgL_;peNiCk2t)u+qw@ivm*(Fffv{^JJcVybNX(0Y3}EO zeiv;V?Px$p2R)rc&=Vxpj*RYxgz)ZoEVsXpFmMG=5w3?TI}7-(VpT*PM;8s(L1WJW zq8(UvwB&I0+t>Ua5`M%+@WF-miOznY@7phyEQh^Ww?5RkhBcp z+R-PpKF6!QJsKcuKv0uRINpOpo89mq#4Hp)5cbFtJ=LRoCfJ93H1tCp4`b+$J3h(| zCXNCpw`)en3n2f4EGXfN*67fg>=nWORIBt~;ltf)-H*53ZVPXZBc5rkLpnX3u5`Qz zx--hkB)yt)_XXDd}#8bX?zA;LGs{8EYaP$ zN}df#9=+WeJ%rVvz-}s$A9FjlZy)n)oZ!d}=|qx2dXK|3s(;NQ!zM5Hlk4MTq3P2B|>cZ82?&nj_54bs!+?fD(+MsILd zM4pdx&9UF-@r@*z-s)T@nIbHZ2TN9w85q=^ZB8cmQoa!cI* zR9<&5Fr?oz<7x*36ssLUB(nkQKoK0-i41b{q_OFI`Md1LAsZs{+OON#a3FKED$$56 zfkQ(F0|e*LW7_e=9WHWsg7OoaHg69p=y*oAul)*UCCx+}G2{yJ?uR;T=oviw>WL?v zH#vS0eINS3FWB~3C_-?~9r_I+-0=hHsU1Jr8B1$_Iz2>ViT54LK{9>mwx@@Ah2a>o zf;)2$?>Z}WBA@@W)shvs_sNKExcVWcNDhb5#1OOeE`ryIwdnjhG8E)L&}YoH)d#Rz zC!67L?{L0n<~zq*B29F=#-UkAlhfPjolg8lu|MJI>9js!ltxqT=c%^Hk)mhQ+m63F z^aC8fbjMG3IM{)U=ym@t``xxz|6hOaf1Y+vjW)kKE_o)7BTjR;>Aw<#5O)8gD18Sl`HvRy+D+R66~p?02jw94(icN0$>!@C_1ie{vB z4kI_>iD4Y*c!9U`=+Gx5IEmLraCBl+vWBFoo^QjnWQ!ZmXVVtb>PEL8^dh=;#C;dav(i`bWc9V1f`Jsg6VMIB6 z-*5#E6!+RQlNUfXcxP3FXL|bS;`1xGL$KZcp4;*4#BSsb)4U|FWN{sg-|lfaI`-Nw z`RQzH53*#>CZ+!sS#jRD!+%Er*X^frC#E6n5H2aEBi7M#~YxG-Htzfd7D1N z*mP(+Zub)$jwJpbatY~sM>3sQ#Nigw{500V=FqMao{5sfbq(pgJA2i&Deg!u$-6V_ z5a+jhl+U*Iou_t3GQ0h_oe{h9uRApV?zqCq;yG4%7|%Nv!C4JyQ)iWq43ljp4j|n? zd_WOC$v#PqBX=aPP7Z|V;oKqpLDKSUJnzinn+!QzMIOZMQncfv_HN^zXQm_J zjVMEM5}X*@MfVjH4xnw0a)yQl6GLiL}iQ{&(x1r+Pq7^{nYR;+LT>M0`wEe+PPs!;T^* z+XvV;pg|~Vb6{V`IaLyewYH-;Tg94AVkFh6GWL@hyJ~e1HP8*adukcia~N@S`+m;W zWhZg>7`mzsqJQcb?l^NC!8oepoyHZKJ7a&RZ+kJGVnpKJ6?9uUl`)DWY2*?7ORyfY z>whcTF{%;MT&Ha~SMBoy_EYp6VU8eOz~>PDJ%W)`tvrsW=o?)*DxzV;8Z;wTu~f-2=As5)UkHVhJxNitD}*Gy<@n)fLZBzdh1^MsskC} zgs4og?94(w0KMCRgYbW1dp@eF)B5+}Kbo1IC0_Y%NHVy05Toe5H2Wfs4)zIeRNLH* zp93}r?C>DLy^Qw|#I*7qs_%xFaR1#@csed1yb@Q@Ttpwj$UYknM}ff=z)v$dSLk_? z3F7djZ5%ptI{Zy|9gcOd=;Skqf`>s*2lLK+PhADA>!gjf9lSf3CJ2dB=#9f%$qtq2 zodoj`9^zW!rlBnCV1?w2AfY!AwdotZfn+T+v|6IpN^I5x3HlT^g8g2qx zP8F2=huibAPJajW42%KdVQigd`CMtx$`&Dc(%6aDrK8$h35Z zn}!uhsfOk~TLDghqEalZTf6(m-=yLqqvC|LUe6Z1sDS^P` zz9UE12O973>7o)cz1UyJqZ9cX+#d;T;H}GX!KN_7`h)(U)9wNy!AvqqmV9_|lP}LQ zToS_sMpJwPFXD|N&jSE&K$ApXmIZ;AJ*xC-!6T`L?)7?QN%QEIUsD9WkQ?u`lO;Z2Rf6ilM<#F z&>aq$Z3pF892QvTbtX%4C_KxzJMDgog-pB!*IABk26-7xAjIht;^Qt%#bRQ2SDVpYbD|2gJk;$qmFqiCNyyi0mmrG4~4ZqvW#FGId z9}k$S7){1_my*tUb)I>6Rnr6>-z8BL1@#0E8l50cVKTpj?qpth!wEpg%eoZ}p($Ae zxm^JdFELLL3jnbeJuDCjD0(nv>K;XUx#*TfqfpEnn9;3DYS2^_RgWpvdX@mh6QUxE z#2o@2$N$)pTfjFZWchK07R9?&m5+=>c*Y9^AkV`2Y9S^n_XtM7&j$di#Pg~fSo0~o z;6op~3Vv7+-h+PY*Kt3Oj^RHCSLgy5k@d?>*T7~?9)uQq(?YK)JjodYGi-%T>bG{N zmtY}ch<>MA0-JY2DS;*oKm7o}pmSC5H;p@vG8 zN<#~^3C)3rEtj3e+ObVh|XcY4OrP;2=s~(jFlBq&m2nhL6ui0(a+=ka{Fi8>w zrg$)!+XJ2#m|iRC`j5+s;+8~@TVj>fGVk?jLaZ@1S-JRJNsWYbmWY@+5Qim42C?xy z896`N?^+flEZ}3uz&U()ado+u6#4r6p7{oUL$R!YOU+fA^`NOSFc!0N>2yi)dfXx} zxOnC=qZ+X3@yMP)2)skO}}{`AHv;;5ukBrB`7l{n;~70brI4Hy$fpYsNp8x zu~i2f^oR5V@u605VfUy3X#mUCFgB52lWs4qu1?e>QDQ98@3&1UR;Uzxx}wQ{<_RV8 z<&afQ`V%7)DXSPa#+0CDRkI+D7Vuh?q;cz^V9tuf!eiyART_&~BZcs!pz4}lDMa;1 zQa2JoH5pvLh%V*Be8h96b@!;Nq0D82%>7G{l0|dH6jVyGGLd`2l?2#fl(9W^l_zaisaf9Qm zWJ(ehMLiBV@t9^fRfzDKuJMW)&?aP6SM)|Xshg%ti$+Yty{~if@ZlyO2>N-oJJs=s zKA*-!GiRECOs6%LgswI6kW^PVl}kq@7&YF-^dO`Ne8#h6t6C00r-^#CUV;ka@AJn~ zaX({Hz_d~>zv1EeWU;FIa`}S6r|X?&p7!FHu&}52zomWq!D;Nq7^GYwlQ^y^bWKr_ zJdjoq2Hb$yx_JI$l3P|JDOGNblr-J#PL1?Ov-Uh&pJ8vpUNUSj2CE7~Hl&G&^PrtT z2C`Z@E73JG)m`3Gs^r|JUz1c>g+Sz%XS*dUJHAm>_)sh%x7M2Bk7Q1qKE4z(72WSv zEJ=|H)B6waPmRtL{4PP2bQqo5(lM;Vjh#vn{w~xVxiBd{BAnC&JCHo!?I11Q>Q0Xi zS{bW27MEc!0^U?_q!9Ijl?M}1tV}SKOlxv^Z>6+6H;9O$>Xm)2pR5%Q#cylnt!XR z>lUzFZrQE**z52{X!=MZ>Vg^vFDVMIN34hrIG7-cvfHP+Koth&45X70FRx?N1aTW< zEq5vv5frbY#u5<)=G*NC(mh^ZGO6pj*WhJZgVoUFbhVx{iHj8MG5rX87h*MTV587> zi-1FzDza2SC~X;n2iWVh$D}Ei7Qj~9-f5kMY$}jn#CkBjLis&rxl{`JVA*|2wOLhM z*!Dy=9`HkCVBv!$)$ljR3;~8najX0r1W|zx!}A^wVa+8;?1NaJBB@?CAzk5_+v66D zbjC0YctBXK`Er;zjN=8ED6giz9dCny3&k`|lC#B(Y;)%JF*y0BIwYi|dV{9)RsmkP*R2RFkghhG<&5Gra(cB<_OK7@wMtIp zRb7{S2OoU#qYvLP9wCh%1aG_vJ1#@WX%(=m&DFxsN35KBg7dfH@5Qb`HhcOBF8=$t zVLZXret&dq8+H$3S^6j)wa2uLz2E3tEE)`N0&8pXHDUUmpjrf8d zK@a-iYxG-Qz27aTiaAlu=w?2y*Jf9{l~Og~3df>~3JWCrbQN08L*P4{z{ilo;0DkK zwu-kY3k`uKIB}PYlr5H$v}3VZ(!dTIhfMN)9sdB9-ef_)oE%$e1qz8kZDHShorii* zE3MH=ERxQerD7r+^8`%yYr^G(FP?>)l^)c+TD;ziMMwIpFXWlzx8Q)f^hmJQ&j$=0 zE;NH`K)h*$l0jN0gjuqzFk)jVl&ytA3Cl7dY@Sj(mCU6_;yUjNx9yePVn51X#9md3 zASmv${TX;JvSSr!nYM9t;3un!_|vvKO=w&laY3-$%jy!sUa0W^AGCs=a3Pu-jAX-L zr-%Z*PWmijdOa?td|nBg9+d$MgyIkW>m!v75NGoZpO1B5AfsJ5>uA~->0;plCIpQRpDk>Ge=VMM9h0!d)! z;Bg_Mu~{rkF^&a(LkN%k=RvO!tBlq%Vs?3uOSR`$mXmNr#BjtC8SD=NGb`6pd}*$Q{oiUZ zGrFy#evZE%zWl1K`$V{++nE!xU1i9Ym}I0qlwzmk!o|H798`g^%LXGWH?t16qdWmKPsO-acHiJ9lr3{ zC9l`*_CT+MimlF==~5Ii)>^1E7b=0`^geTTT2y0=T%cA6dt+7bUlO|Ob$kJtTaMfn ziZj7`?ZGJQFa8f5ro$l_q=Z2NDnSZO+Wv~IMnFfHUy4oNqg&balt+#fszrp)Ft;vP zM;7djck>=SxUla)M%4lwBl+kWJJrOh-JYOVZ&1pLMg*1i&i9{y4~rdnT-WMheQq13zQYp zB8iNtWed3&{4Z}b5U^skO3Cs>(vFJoI~q0qJod?VVZ9w2X~IsDNo>O;28ZTc7fhrcY{dcbgsbGBq7RWJ zy@@oIYL@!BM5i1fe}@;XfCmENk_#*S?1ab4gw&9mA)4`pB1*f(K9ZdpiG>R7MD^}_ z?$~H6npB(HyHMvPEj2z7D5itF;u&pMMKz!+P;Rj1$Oi9YXJC&~Bq{LHK^4SdWm}tr z0tnq?sYeFN40trzfFfp`;u?n?eEB50(%n$|-0c=o{W=ghKGzL{$s9B`p|E88U=F&q86p zsKClgdO+phl&zO)X*He8xV`m|(VduRCM3jKISsik-i%?0Zp9!+_=z$0Y5bbX1j!LH zK=6MAWO_sj6jCna_(CSFtlX3b`}st3e4-mvXH-analD zmSbutgltx&KR4UYd$sqlP`XknXo_LLZI{V04Mfv%Q}iXXg^=i0WCVzc5i=v?)*_{& zxV^rBW@G;4>^tlgpg_mLJVhu#MOe-Pq#_s|`O4m`fCR&~c*~=*M7GG3`TD~2OvxCZ zXep&zul1Tfg}u~j@4bFnizwBZjROY?zH%Yz1C5{&gTc4+c6Ln^0+z|kzV}PW;lSVOjSj{oO7p(^;)d}kCJ&p@l*;V=e>fc2SYBi zthj<&AQcU3Vy-z>OWF2_w(SZx@VgYG37_Q7TuHEF%ThjvTr4u-LnnzWnhX*T z^^6na{)*){bf3=*UJNGSe~))e%koGrgbb;yUYaPI(Q-Y&OJ*_cQgGF41|=U7DWyOt zse8g9_F!tf-yck7x*b&wFct2<5!RJ-XD(Yha&RLhs!#!nN0O2Cgook7PwkO!^c|rr zycWM&z-6048Q{Xwz&8ZPf%j}pUAA+RwrAm3AuL58)koe0)FE<61H`d(gv*5NBh)?A zLcb~ENpb{9Wp*qG+oMNbepjEx$5xKq)y=H$U7zm-5I{277cE308R#get;)z)v@lVz z3JZ7ijp@loK+`j&(bULFGonQ*F|%6s`P|TjZpEE25bPj0Gc6@iiFtYGzT-zTv(J0Z zATx3B?hE6^wbj*v8tEUr<7{s8rEk8obAD-=9ec;ZuiV-yYDQIwJYc6E$3W8Jf=ZerQNUl?=0S3@6N0^eGbb<;)eWEF% zU{Wr%YKqVUJ4YGz;guQ)vIA@}gn3|eSxyx0*A;KWKJua6o z67%g2)zavpw-`4j149Gs%W(kY+2<(bu)N^x>+vD2CKc-7qKsA;OH$wsWR|IC4QIA1A*BgJ|!F>Pt7 zcmRbG(}MC*bmQUoeDA!=13Sl3YQXP9al?pa%wQze$j3E4m}}3hRchl|pCEf4HB%Po z;0jgpV++l6JQc#5JfTe7%0)CS(0SyA&$p#;i~TeI=&r!j{yTfQ!z)d%PZL!a(!BUJmUw+)b`~(2TmQm; zmVX)Q)Q*NrAx*kXgEG!7nK(2L4yHs3w1bZUx?Tw(6VILZ%AzAN^q*>?2bI%`a<)#mv zxqHMNi~463zem?tcKTqmurlATr=oFm0c(I1O|oI8@6E5;jy&XT_P%7qln-sCBt*5sv}Q+tFG>i0^0`1mq38Tb=^QC`ZI^B6_$09Yan zX(fD+_>!AEDRkgC=zKZl3L}&&eF#MshN_K~OvjO!J%7^63cBFCVzEM<$-h-G&5>XW~J^AH=641d5 zl(&~PpA-sf{0Q^v-eh;J);O{;GZGhhkC`@Qw-l-j7WY*Wjik>N?T^_~0oASe!4R6; z8&Lk0a>Bgq^~kY88LKoP1mEHR2kB*|yJUF%GK6|N!$X>us*+Tr1j7dr6-?O)Dkv() zC5Io5x+Jb+os`3;`ZBZvMYFJ3Wp>G(Z?;E@$P0_`L~pmN~Q z!7|FuUS0v`E4SXsgTzv_)A$R?r^yn^a=d7UL*nsYJf?OgdmdgY$-&cn2#LRGG2Nsp@9q$PjoD{Io zhvZmg@}*X)YcrE^#qcV+W_gfXkJra12bKnF#8^)Yn?WSfNP3_dB1NW*OfBV9WD0`; zpH7a4>Wa-wPt>FF>R1D!?+OJ`F@HEMb&j7scQ6v+jn3p$D+TC+sGR*4e+r#Ku+uIW zU*3)bd1yF-l;{pJgW9tI4Q?&|FUhv_lQURij~VUp>3&TU1*BYbkPhV`P!*{PB=}Jx z5=ECw@aAi+(b0%32V#0?Y%~<|Ce{wrY85TuX5N_U&7!Vc3i!vm?MkFFyJxYjWLDQ# zQ#OkIe$i-jx>3E^A8*8&3_I+LcDu2NRbHBo#bcro^sD$C8+#>3kgX_!h9t8H5p-fw zDCZ7^3*dB=XGnwdLD(Qv+*Eu74UsHFMfLo)Td)FlR-w7SpZb~n>C;DN{eFqBEFL>` zvY>`dBs5vT70{qY_2QiKMqc8tp|{G$U8xT_ARi9)ky#K-+fNl2!-j&gx?>s=s&5cj@%@zF&ylTHUisam%NH8s*3(UFqW zL#9|-DR=JMysxdOqJ%Xe=ffWd7B|QbAgA9kbg%}ngsyG3jFcX&2EdaAAYYYH+t2oQ zJ}IF-3ZOOQ7*!=+>MkGardugrx{#K1Bb$nuo7AEE=3V}#m&J5BrQmDS5 z9j&1P6);3k|Jc>l?sOJ`b#?v1GD-y%xHrLg zG15LTU5g@l?{BvPrk2nz+A&%O5$b4GiHu)V;xtg1_N8^J&%Hq*`577y)T3`m)BL3R6dpWC*n0w2m(ib+@QjJF<8a&Bb~DL@AVjeJ44GtzelM_(q`i#(6@k42wR0gH3k%}(Le;Y2_bKtHKRgm7`^JlnLByt>J5C7IskTK9fxC<#9u}l2 zepC*^SO(xI1^hats!-Rrt*JhkU+U*sVsc@({FkR+d{y|8C};qxPV$DwkiSZ~kKQ->BUx7+l>_q3w$#$<0Gk}=_`XDUI7 z8PMPUpsYttza$}J;SMCLy==0PvHURiEB7o`6KHqP_3F&xJlR2W>tFfv$VM*NnuR*v zpqax64B>Q?5hHFJ8!<%wh?9SibO9w9Bs)FL!`<$*xiDQr9oz4_^=TtzYSo#wl-_8M zm7;nQKYd>c1*a#fr3J9XR95XCy7$8U$EM$-eH}wLUqQ9Q)l!d zp&CK0kwa1yjxWXkJ!H$!J0T%JLMenS=(eWEVj&9CtFK>1OB(a-*?jo9v zx9sr+-QY|ZCc|YS2gNHIQvMB46@rbbp5pOax@z(PzpOPcU%S@!M#B-5s)bCwsSnPd zzX*7dJL4z#5p*+Cv`LW}90Er{6W7c_Jb~<49(!DX(*cFO9I3T(+N8FxcqS#p zmN(X?@H4lOk*SPW8*h$gnj@}6Z=;%8UtjKIBS}s3MG_ICx_JELVL(nb-PiL0bl3uN z+n)}@A)1xLeG9HCd~(M%a|L}$FcS|cLLeNC7=q-5(lZR7;zRdXI0<>@RpyE%G)AQqRNbN1dt;|f#928ge{{iQuiJ>peTZ@rzr`#|!1))as=*YCmsk}5RI%y8?|Z(8s0ex_DS z!V!g8L}I{&He%#HsG|opctyd&?Z)4EQ4PBMrE~~kE1D-1cQ}^zyNlJL`m%RE7!GSp zLGu+JqO<}Xpo!7%1lIvoNI{HcOWCN)g(kYuir2}NdK?|Xeja)l<#CFv$iUgUgSdc9 zz+tsA)*maoMfh9D(d5Th_pA=Gl1E4IFN!BU?b(&NwkBn2bsq#``p~IU2WJ8j@{v4p zf@r3pF1NR^pA(MIuXl#Ky?$?yZNpvfLxh_y#PCo{PM{{EeH<9g=1Plv5D1{v`{E(J zGq=#oiRIqRpepC9VV4WoK_rf5Lc|q@eCr!Ay@h^LUeU$&iynK`%WtCNjZ71wTP#zO z^X(K0mTPxDc=^HStOo;%M-gqf+I)eIdO`5_J7aMGx3%rw*J6+%8tbcMQ|hVH92M)ILj zf83t{d&JNL=A@rdg9+WvXd;x*Jdn$v~mAR&s;#^lQ0k~}um-fGNO4NoAL zjW=>p!(AeZ0M>WmuWpUPi`&&d)*!#G;rMk_C=bA|Yv7pJ=^+DeL7ckeHIY6S`U9|@ zvqQtq5Tiygb)aF6RAMg0BX--R=}HI@r^ABun#txsRbJblwyT#CkwWdtY~=P ztRk46IzFBqOUqJieosb=nwo%y(um$0RJ^ggl}ELa_a+C&X5Vd$4f>JE`wxsTt$X)+ zT})Ktu~cEQ975ULg#ZDHHB}Cpds za($*5loi3_il-71Ho-)4XqQ3PNPTfMK0hdg&2+95$&FXc03RqXuvya+gcdF>PLC(B z6$d_#W~3_h3fy21I&375;t!yoGIiwC@#R{)F-W9}sZ@J5qrM7#8xmxd{>mA97+neT z*#E}~=+=2WCru;0dLJot_EYYat^$Ubb$1 z4MDo-j)bgQE&&}HtMz(qzfvEc?q<+o5-D{PjpyteRo5=O_+>BdhUXR+I%zFd8k=E% z7s$qZmFZkQfm*X(9KhLSTVDsoUIU6D>MWvc?dV+EJLT*JK;ac#Mmv?Q;aZ_tMeKrE z$0jfq$aV5)%m;!QcBY`ePebO~?@(I5|B)YBPn6TyFuJBCp}o@1Wpa^>l%79y=Ga@mn=lf; zhRbK7zwZnhk1R2*s@=19-_z9-BP+-D&tOZ9%z_aW@vqzNm3h^z9`_agIR1(Tyl(8W zL*oTpQ@GkBew5-YmHUv#PD;|TWN2`}gFZ0!+R;<1O|*8QwIrIz)cQG(4<#-u}70kWL=hB0kjtIoFk`nOUw+FZK%*JD&QbcbqtJLRMu_o;-8? zMK68ifxTrhAnGV3gkmU)=rH_j>lP^cdj1CXcG^BT5H!uBj~W2?iHpPVE5XRXn5-iZ zw;7x4x03>PVqUO!sZDhUCisJX(H*iZKXuA@upuEHOXMtsyLzEoO^1>rK@4>N?V)I#z0AN>z0BqU9T@ z92f0q(}T*|kG%2~tBQpFWa(AEesdgulhKL)zrx;$U-m#h0+@yZ6epJiwkL;Tn|mDV z1tse^G)T2keA|WNh=zJ7Ut4q8YS-2Xuy3F(wN<(S3zD|bm^5=FNU;e#!>~^+or0rJ5ZU-ru&sJ0;ohO>~$d}g1BF{ zVpe`~eeYV#T`0t9tHk~vxPKZgb@Ov`^O@%QnUg3XI6duu!hRm!X64y?+6y}ten=PI zZrihFMF=T$cX0H;*|FG2H51k<%O^&f`zJDE;p%wCKQ=a!lB0{0*|o{i?+lKN$Aj5= zvt@M-4U)<3{y}=87KP_p9qaYRLc!7``AWB5hZ5<1Ls@hD>uu{`=W%W2;3!wLw8F_J zdtsSlGF*BD3UI`Ojg7Ot`r-Lfsymm>ER7dJ<%$`!j9x338l6sw=}MzWjgsi~M_)Ud zq~Xsh=o7HQVGFy1zi;kDH-p9<&N*?{Qw1|vSrQ!FNUW9jH~ zjxPFae;#QJzBqT})QLR^k$~S@?`4l7t5e2b{@LD>=@>T(7X(`}Wa`92ncFEFwJCNT zM)FML1E#@`tu#XE>Ek_fw30}{IpPC`i4-g^`Sec&a*Pfff7w6mQPbCLvS&_ZzwLN?C{#Zb1E`uMCWxzjY z*ze+R7jd1T9=3Non|3_yxE7RIM81*GEWs%!D=STkWP9GGty0`qA!Cx$B-giZb>QQFtryc8G~>yNE=wTqqj|S1dW+>-D;EH9Umt z>+BD)iyyHJ0y{E600XKPnf*RFK?wQiBAEqrkHNP@9gcQ<@bDkd-K)3*KJ2uNrDM5x zXu4lwSp>gp$U8Hsvvz1{gz;#y#a|&3OYMnP5~1Jd1!+gv_JqKH$EI(Xg4%M6h{un9BBr}3+;EXUI-UCM8q>`1cAs5l;BN3IZAM| ze^9B^^MZ1oHgBL6#e?J|`iD;VlT6DM3)l((zdoG6ejc8kk`15ea~E6Hkpfz}k?QqI zzlz2)(i+Sy_4gcGYom>0;pFjkn-^T{>+DP5T(S|g+a(FOoQ=g|4;C6`?#XsMBmvMZ zX_Llj_Ol&-_Gmbpt7Zz5*mUVpth7blU%cXv6R-tE>}W8H8G5V`6AzdMQtU&2731)gN@ai85^-NA5gKrB8PtoHmg& z2K$5}@kHFK=PQ+Bn%yV3RhfCJ-KmLwC^a!TTTn%h<&)dXduA%EzI^!5l1*>MzYJCp zJX-`?im1Rl0S1K$8w=pYcn0ZYh&@sT(Nxgi zswdG)3zq~`Mn`U`*f5zdipB$36^vrSCl`v1@uFph@9EcFqw9CvbviGp9?hT5LD;2?Dl$k^ab8_7kgBvCoK#C|B=9BrrdumyRSf`|l|zcCU-B@tzCAv#h+ zGeo=JZKR}lh3FTW7;kw*Y<8Es$WyfZ!E`Z$7WF`)Gg3CdxkjxOv9PlcHJ?hO<`MFZ zktiQ^g)@a*)?;?3X5*?!JIDNpFusfk`!M`SCv^@bF-r~5O@L*a52T^NyFfdo)TvTS znQ2O0>Bv4e#U}m8fUh;Zm`hX=0gnrt2V4Rm^OveMvozPO#Hn%DCt@pZAXe(-tkF8k zbHvtY|1q)Ig%8%2+vZ?=P>_QmK@m_Lh-P>KweYrek{> znjwA2OxM>2Wi?Xi_Bs|eC>y!XbSH=X7}cm$Tq}hO5HfdRykxEydyQgsG(%nW)Rz*B z#SnK;GFJ}8vq5=ecB3$IXgaU><3P>-ZthH=CA-Rcf6l3St~zz9>eM{mQ+4YOedn?J z-rIfqc6U16otZ!;iGd6ai;xH{C_@-ToKOTc#-P!l2#U{#Ph1aT6j9^}M4keoAkU?! zOrk(gpF-FBefw0^t?s^^bVrx#MVF>Go71QE*?WJ}|Ns90`FgAK+a3JbLN*gkSBe$0 zxj5lW&No6C={DBYP#V#EnyZ2L-y#8{rFEDC&&sJ zoIssOQP;FyUjJp!?`uCw9=MOiQmfrJ%P!+zQf|D8M8Nz%IERWts~p>QMR)lYYNwJ1 zkaQ!YBzavo2bs&RxqCEVN##PacziwepBsN#I=qp~5v##E1}@H4%7k@iY;>z?=K9-|s=}TMjRCKIs)t#}5-hA%YaY!=GIR^%X3p!^@ z@`h6Tm5(b~%(em`h`Tn-V=AB*SdM8OuUK}GRAJc2PCM@TYn;Tp?kdk8?%=BfuK+@o zZr3xC>1?&6qN1G6`oXH?I=z*Bt2s|l@yG)|mFpA>Ra{c`czwQQ&im|?|3xqEoZK9T zkR5QUdZyMuBE+g@B_Y~b3wDlQH94^$N3@?3jm3k23bQGWjBa+8Q8w_`7J{wnfeIDo z<{SWP@j1>K|6qKco|o!w7Do-wLSEjzn&f8zVHGi+<@t?(a^zeFn96tsr0^t#1UF8` zs#1%SJIxzlg;)(`QU|%Quvx6eta`1H1KkQ@7kZ@G1YQryPzT={0A(Hs7n=EWwluLh zRbH7WV7^$7M1HK$S?v@=4+YZ8yM@>tOj3ahg@egpxHE^mg_*L72i9hj*~NTor&X97 zpD0@6_3VviT2<92$Cj9E02!p%hYn*iC8CF%;V1zrfQlnO@muUTW(-13Q~cs`rk!oATl+r9Jrh0=W18mnYH*|C(Bn`!4Ky=Y|k&%Rv(*YRuiSChw&*N?6{h2(gS ze)7#CkWWAnWcGYLpqO9m$QOqk_Q(xH|M&j0O6LGvH^zib!oLN<>Z7=lRQT#d$sYU?PEQ1Xi#k|lS;NikP|KSutj zuNSvA*Cr{v`4?KXj_#Y-JaO_^sh-T{^Yz5s+S*jnXsjJOam8vQnk%P@5;qo{8?SD( zkcJA{o$gFsVotNtUB7C+91nP-&FPg|W__uhDtA9l=xMczC8s_SPOi?@CTvha`T7J2 z%36|2WjvoMH>BQOo*(BUT7kqIElwe$IX{*W(TWb+e}X3A#x6I}dJ6QL^`T@uEu zQaZxg?C8Ixp8$(tk>!zEhnNd>+o+!p_h;ZKxqsdP7U}mx^$LWO=`aP#z$2jqjCvxR za3X_p8tL0FcmaF*BS|adPsBozM9R-VbmY&%i*5G4WjstRGY=c|4*q6mLxAm&5P{Z= zz#^r53@%bdV}sXP03k$lS@G~;IPDZM#B@x1n&|ZamMX2BzU|af(Hj_FKYGPZapRs7 z6Eol^uj|B@w~y@~^RR(R~O7I?mez+z_8nsL?zjoSqP!|R#yn2^NVf05Vj%~*29`9ZXSRW8o5kP zsNwUtq|n!6hTEN1EJ0S+z##Rhq@F~%(XzNyBtafXLA61hj=BJ0o9 ze};^<#@!Nk-F`Ij;s)6f9j|jqpYcuX-(E#sj}rA1)(?6g=>|i;jYP57LL&`RV<%+i zED$Hqob4#j9cY^H+_c)1tgSM^!p;yF$weehyn9KSa0bV;ILOuGoQ2o#brQtok*JKL zP|+{qq6_#6^Bb3cgs=f90Cg;s*O+E(0nK2p-3vtmktyDrQv9?Mn+;{qV5fbiY+@^ zvL;(LSRG#?k<8XB6|;0`&8hBNoka?5x=vv&mL0F8e4Qh=+|uoq*wty>;Uuk3xhLrs zPSOHJiT+7CbpZJlK43u7Q?c@NCF=DSW;ZuV#iWFJPjND_yDczMn4O zfF~rJGqX;v+^V;>&}#u8`tS~5$e$`#$8=gi9f zsOlflzd}!TZA{4_W+jwXI|K{9>?}!H$o1JIB;#9&9Y?}I!XZ~fXjv?Lw(8}xxnGeO z2MwXQCA|}$pB)2tB)>q8?lx0ogxI`jG%he;}M~&bKF4TEc5uG%hIvX_|5K&5>54Ohve2 zCe4rf^TM=2bd^L5A>#`qcpO@+AYM zAD4LC>kWFLk_qI^K*K>8i@u<}Z=zL-Tcn&?oAWJzumSw&xRoegd-JWQO2vQ?^i1FS z>{A;ZUnDTTdBs*2#|Z_+R=vJHjg(?6RlNGvJ8r&mMpdTf=r8}@^seL(&bR(^(PYY> zE}5YyN`X8-@Kqn>YN{RKfSHWMO-V#)51suGb^IbYd`1x5*XO*3D{?k4WNWnnP&J}>x#qtxR zLUgJfVQ;O7bj{?1-O5E%#is1Df71R^`z_;M_LZh7F~C3dj1&Xf z(W#~N#ZFj{T1s3XsB@>rO~eH#8vD(tS0r5k6UocJ@|2KIT9$`rDb|d5O z;@?f}wY@J+f9~KhRy3!N_x^SIS#9)pneXp?+-N}PWPa~k+Nbw9^IK~E1HF&WzUiP} z-2h+HJe?QsBk#)mXzx8n*Z44VvVe%9^^c7oR`Y+f_nzrD9{h-U{)%QgcXqE=^KE90 z8Q*5S!HM|x`#u(On-!>fI(bo0*hvPpt7zfvPRDV5wtNZ+S5J|jT`vG-ZNtzxLEwQFVn**Mn3d|+Z zD6u{l4lyVb5*YA{Qt%hW2VUmz>tgN|5{-lxyhjOK8J05Y+pT&#lPp?rMnSxn?B=-y zd+z$nAn1>gFbU`N!Ue4SJ1fON1^_`gT8QT}QO{M`dX~@~u%%UlIq8jOj-5-qk6bp5 zzo;1eX@J4u+}ZN^w0->>d0P)Az%d{N70b9eq@L&Z&^CC4`$>bDBy4F}rzM;teNK|K z)J71^M4g5IB#;5mCzTWeWss)=wIGGmU=jHWDj6)Hjs%*Q{BabJv#Q`<6+x@<#rNsH z(NAS8VJhKUU%8nTzI8e!eCumhgl;X?*ITNVQIb5o-S8>j*$8&GPVVIEooXQ+M3@Xf zGy;H^@%>zZ1wy96+zqdMb~uxS7BO@7=mnn>y`hlzy_6l{ZsH@u+6FHfOae6vG;Jt* zVE{2?9%1R?A$Ujtlc^+fr&<^e#pKhPU^*{Hqrv^S4)P2OsqesMz@7!D9do(fz4Je| zSdBDRLsSV~IJ6o=qajB^7y=uYrB#5h+_y8hPGV_Z=Z^%ERUo{SZuC^KHP$MlK#D;v zh)BU@=^BW@DS0i7Q@)+EFJhg93KbVUgW@I2ALwCg#F+X0t~FEG&@Xu=xQmF<)m`^4 z?HleLrGLrO8IGUP9v<9jjDP=NoV)I7?V;iP^kAGjZA<%CtmRkm!5;F&8J~2Y-}|)o zDaQX!#*J?d$ItXWr+tv|Cm8>{dcK;kZ}uLR=lAgOw1*A3d)?=p?p>|@yz+TmHHTO7 zp?Cdlzc4%oLJs&rT$n2Tuslt{byw0s0#;o(e50xkczXT(5V=vgV!`kNs;cT>B=C{{ z7`*`#Nl7~e8iN~=s0FnL3pjjfr3|FOLM{t7Sjamn`ao@WZ`B7}-wPxpsMv6lQni?F z0$U7QriFNOp=J{pqaB86BL7f1xtJ;hqTUxsOo;qI zJCWlC;TyV)*gs&6XXRVzJLCoW-`2R^_!GwG`g`OnBjX<(j-Sy!x;u_kv^(FgZ#Ei3 zyL!Fxv%~S7jqe&6{~yEWoTf9(Lwwr>ZNGlIenOD4!YjZHmjF~{xFyONs7m#k@KO zwyIHdx-NtFz)E%?Bbr8xb$McOKJt*%;O2vAZ^1s&6R05$}%I!6n5+gLEkp%{RIO@^9Ghn_jVBKcxO12KT}>GobJLHqfA8Hl9h*S_;6fpw5;9U~SQzNT>w#1`x0ei%c;OPLeaZMqzRcnN zmw!;ZZ8$Esi#vWsdrxjW;eujW4#!|Yaie!&9K zk}O$KvqY^m9%~KxC_e9Ae3XDMf|UOVALU})7Gh9;zE&v&viQl_Lc9QHcN;f3YUaz- z;Ifo$InaN*Iknhhq*c!S7C8w;oTn!Jz>H56D=;BuYVnD! zF{c)_g$Yr#<4Xe~#CRr*YJD&P7veq1ndRl&+MVsN#}^wif%MlDF60Z*c!5&5H~cg- zp>e-&vexQ)i{ndhDjZM^E~^44S;es|r-E*3ZGN+E)*9I?H$qDhE6l)H6UqDl{4U`T z?UXN|7y%WCif9e~>Jy5ugQn*o%h3lM`rCcOGFm#>o1P;92@5}(4|$F9Qj6q6%HpQ> z^C7yYQ3TKQG(4WTHRa&z_&_!6rcFNXLuc32Ro)~4+c!Viup+T+>H76c;QQbsg?*A< zu_h-;uSAliX8$&L(s(DQ`&j?>c%Am*;rJg9$Ioa#q`hr8F1Lrw=k@?3Ke#=fG~O^6 z*G_jqiLy}rH5j)rFUzM(&Cl)(T#k3&qduBmQC zm5G#Gjg(AsF0zCcHe_9LY%YKr;t9$|lQ~jK;m~e)vYtK^AJ8TVAnNoyJ84&<$$}X% z+Zz+k$&F57YO|HDlqz%qN{`hf$LTLt%At6x1=xqXEa3-MPMV&2ai}!YwKADZ)i#sK zX-{!xtDbDvfoc>Ah4~%*aj!|Elcm)a@E1$8^F^VC(DcYknYQ$<(ap2}E8of^3+N=PZ5xL1qMSv=M=)N?StL)#8Qlq@ zJjOWrF8x!+3gc+TsMzz}BjYa|j-R2w(AseRqy2Ht`oeoh=1UAK&*AyY{X0NCzc3ir zP7~J1-#dl^@3ekXvW*JXYxr**(Vv_Bn=NheK{p4de+oU;dG3=Nuzn8Cq1b)(0hO`C zk(We}%E!6LBC%O+=7-Pf6$2)JRR5E0TiL2|9SA#D^`OsRj3;%WDt( zF!`-|pS{qI0!%hTiS(l`e<2oape~Zi@u_U9@I5(8kN#3PDwKu{2;rdJa%P0ufGkxk zLxGWR6Uu{S@FoXT2U=mEu#}2VxLgOiQUrWq&d zse*K7kkA|h%Srq4P)uM?!0c(8qXrj3`DhTH|82CA805$ zG5mec>Hj{zcDf0MnQ=F_`&PzV>UZC#JzGC5Y4d(!`R998qbNoy?82e2!SFF|%;Z ztltZGw2**!B59CkuH5SL)?%4V$JzhD1-ZpHlT;}bri4QWL?@8COf}ctOyQ`ItDZ>O zIBj12H}}jH_TH%2>)=NEtElegr*MKrpXezA3sw;56gX0SS^uOg99(i?qhHMXKZn`= z)RBahv27H|v#0jIOb-@|*)crJr||YKiR2yt^B;}aPS)GsxB8Qw!|X$+e_o%^O?N+o zy8L;@3D;Eo{iyb${`iwBj#u-EIpL5miN@RwBH^?k;b;iNIIei$oRGT zm#G>_4b{yjatZ|>CpLSS1>_vK6?0&Mf_oTB#R`%uz#SzSh3qnaP%-9EId;!9dvtJVnc^!a4`p)(|!tK2UtIZG`?GG>abl9RHE z-0FS0zW%%9Tq#wV_-fwJMS1!oq<%zDa&~Erjz81333CdtPyrdIvp;Z-~ILoecv+DP0x4OHO)p=57 zKvlG&-FM4Nhr9Yqp2lE4xB3t3b$O1OFIHFP%WeNo?Y)ENd;G)shZt9W+Vip>L`QX}8$!@$-1r3qVUEIxK0qSD9!DU?(XyNMFh$#a6kWDV8`g`{A%T^Jtc@K#>4ry3&L$M-y@N~%n#_-&=Wwa7)lS=^Kr%} z`tN^2`y1we9n17)&phL#4&?p2SSUDXzb518Dcni~+OI5eU6B|dCnJ&x0DRpHtjgHC zA`4|o@Jjp%9Nq5Srq9cMamBIZc;%LEa*Ie1Y6bK*qNeZ^Dhwf7Cn5@3DRfJ64Gr`d zkgy4{4gkoql!BwlQE`Rr-r@{Ff7~DHi!&TvSmtT|Chl&?st#2e@&FWB8{#oNZAcE* zt;X&2ep0;6-p5#*IpYx`^g|bm&$(uHi6X}Q5;+#hssM}}5JmO~&>t#{J1uLMIx=R# z9I?{1bPg@>4X7iAr%xT(Gu`p`@JW!!AM!~op^(sqN@x|(Nf5g4(@BippRgl7W8A|p z5DmUP^FaNN?kF@JH{-li683oM&3;8NS01CULZMqMmh{x#c?7*6K4(Tu*bwPQDoFbs zRV{PZ_+alVAlamoOHcb%1dIv&(S*xntDL0PyI1=obfb9}mwDwz7h<#7=%7Xsk!JVHS!g4l z?gkBy?S=^`9nn5?4`pdC@D4p_@c&1>eI3T@g=*7CX#h$CPpBMt*68cK7iy0gcatZg z3dDOMRVW2Fl_V9p{`0eY63t+n&Xp5+_rf(Z(R45yqpJ=jtN>WwQGt~fFaewDHly|av? zp2GMkcbp{=`y_hc*BW1C9JHB=V18J8jPLVR_+>xh5hMc-ka4gIf7O3Js@whfJU`_= z$2|Lf?GEF3e?H?sJNo?344$uFt3BM4$VN0!{?zyik%v6ruU|`oW%qrC&(~f~>Qly< z52E<^V7~Tpna_TSY61P#sO~LFjYi}xIeQ|DA&gT(cK(fie~PBm@T&$J;_ES|eHiu( zO_4%KbjJO2(FhFhMA9Fht_O;f@<6G0V&zQaDj@ha& zjaEDT7-=9A3`4Bd(|XFE68J%^S*^@~Aw@@{_de|HZyGm>|0_%?%%#)jaPF$SeGnGXdDPJvv)JipCi)4^0GxwGHwk|Tk%|uFe>ze-fOSIRp#$|j7w7>`R_1mdU z%Gxt7N-F*Nd|O-!H4Z}X2IV`c=i@tlkMc3x=SvhS&&PM_?=^S)*9L#DetYk)Je*OL z6}sN|AmelDeeNS0CccWB869U_Wi++>u5%zr}2m8E zl4^oxmooj(Z-7OtwY+|-*tEp=z$B6pXKP{_;}0upPHud?b^MlD>{7Ecsj_gN_1v$2 zm0ak3l0T57zqmcaDydS;-78cOG>9Y=EK0r-Q@E0E!}yp*9b1q*H04r00kCK42V&;> z$~PAJB}T%oJZrf=TcdmOmdL}UqaHeGJ6TOug8cyT?sY9SvA=CUGTo}X$)qJ3St zMzLv|B@y1a(lQHn-Xi1d3?z8$Fp4YOzDh6Lv&_!qUQ;Lc%es%9oMJ!Tq$1}VPn^>7 zR`0Xaf1ke_zR%ay$tAC?-t+ghH}f2KzTo53e4?T6QzuT|AIrUinPI09c(SbSD51+r80 zd1Uo)`y^dABm^wFrE+)y9KtFf1W77opI)~|PT6@Y_*$I2AoxzjBnSiW6ea=EiKTp@ z8&e`b0VMLCiO5eSnUW3%LPn_M+tad$g->(SoX1A6BY{|ayoMSO;?&Pf4T!=;@WM45 z?pVo?x;u7Dd)>&6l@sCa*sZ?p^PK&JsKhf)nT`1RcI`>zftY*+fi%~ z8>Cd_m92E=Z-LMe8x&^yzf<`^GG8*V*i6Pb_6Bm-y4LC4Y}{>VvT7`jhmb2mFhgO6f6kY!A86kD{ZA))9}Z2Ml5hIOew;&#BTqaQO^S+r z_t5pvy0#jswUh#WI1((>5~h;CZ+nfrlE7b`+Siz#^q2b*_zN|!8w|;r?Y+XV(077^ zFQYdnM@vy?RbICAQ^05>Q~>&VYAA)`6m7#q^p5i$x_mvT zpq_NgOYROgep}T-*c$BcP3>3uJ0FE6Weae-)c9M}&T%n~VmlP3k@=>((^Sn=Y=_iL zu^p&C$WC+T#|HDkTt^gkTWPj?WG6FG*``0y7nm>EKX@(X;=ov}8Ho11(wL z5xFewFSxTC$O_{zl1#f)LD~HL(T*?=b)zz~zB&aUp`_<%7+XMPhHd&Z!m{&?6y^1{ z5|&NCJiYoCe&CK&Ef=hI_qAj3N(cS^YINtO=iOMVTwGvQ@Li!F5`kG+*PgIPUdr!& zqr0xe42RS>I68%!{^kDo8(2Xv^WTma|55PGN5Bi;gY9w=!%gKnO9BIX#Wf&60~H`) zjs}2Xsg}@=l`IBMVp?pK0EBU?!4FF&CL?f?Kvux5@*MuuaDFLDgA2o0I5E-h0CX4) zjX3SliP?~^ZB>T&;Zgx!KroVc9**?5&-XyFH~i?DUq@Xb#?87zaZ!gPv~Y5t05w7(VDGjoq=lLRv%zo*>*UkFLC2YW!vR_#I_69^xf*5iVlR0k7%9o;MHgz~H}gP$*m{beu8O(Ptz-yniSV)4TMAEOCqI2n&2c1w#)dT~WT z#kLwN^K)ef-%@v0w%5Df2ANtzkDG}v1dZ~(m6aKca&2y7b>{!a_c`8sm7W1Tqt*wm zN?%NZ#gK|;U?ytMjuJ zhy0X2wz|E>>WD}Vi}S^xQJG#{o=HSxan|;+Z)7JwA4cb~{*Fe=m>mu4PXK{@d8K?t zQHsKtNV(}vrH#>EP|AQ(7ZTlX@v6uc=mNPxL3b<%LxxVoqWnbmTi!z?%M8Og;dry% zWyE*jnWBE`0TxT^;jqp5c%RhsEM)6Wz3pmOsxS$~Rp}YlN~@*CqAyyg;0l9v4<}oW zgOZ~wZn$s{iVakLH2uFD--7Q(wpCsqM^3;LfhNb4OyKahI1A3g0kr{zn}|Wh+4DCk zwK?$N)q&wD}2rsZL=osXHNM#?JFSu7Z; z)uYi&-APL4^K7*a!k3gh*zyk$4Rz!$cC)m*PZ{}hA6PyzV#pq!ikWHhYw2)2L({Bm zD)_(q1EH8j3Gv*K{*>niYjs;-(a}o5%v9@a<>8-0q4Nf0g8W(mpZpnm7g(4}P-l9k zx=YVgJxSh>T#fz{pryGnFG1Pj@^mX2wAh>Ic3ZfHdL*L+CIU3N0{DW!L_6q9N6ku} z&Vh|-r7ywTNJeRba(c0E1#mpwI3O+-FC0Sv=+OajQa7u#^J~}ON;cx-lkJH9!FadR zfcwbbm$>Q$uYTaWZ(hOp3JRiUeAf6dcxU>k`haHU)6=g#+fjfCa5d6k)-jn0-i$CNkw-};y5~F5Z|f%zWPtZX%?cC_wCLJ zx~?XY+#c0Rj<674DoN8b+85gU_U*HqYdbsp&BoS|6Vru`0aApbUf3viXU2=M`Gt0Z zl6DyIJ{C%3bm;||Frx+3!();B%-n1toUu@P%jV;#PNGiVLFzIUjW?FZJJ(%%ZQF`; z4_$NeU~>J6E)KWujg5=0C1ww$qJaMW^iRUssL=IOr!CX|rLhuyBM_`7whkw)OqL)z zl*|!9dE9@zo^)fn6bWI3VJnB?(k&DyJPJeH9EF5)aHf<17axmc(S7l^*S6QB)0(Gu z)_aq2KWH}L0!yc~b2|{r7Y1P?O?*{o!2yL$!O~L=krh{vOhP?EY%WC)f;odO#oinr zK->jccbU)Ebi6tBO5}mi+CMVBwyt=gHqyi>u=$&ZcUrBn-4>QXGTi+Zmfn85%jDHB zdd(~E>lmWvov%qN;|44VntJ(B5KE#Vit@zXjf|sVw~cWu7xttn>xB1gf4S1{l zL`h+!-EoQP)P>!S|1 + Cyclone + Open github + Run + Stop + Theme + \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/App.kt b/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/App.kt new file mode 100644 index 0000000..e726714 --- /dev/null +++ b/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/App.kt @@ -0,0 +1,104 @@ +package io.github.chrisimx.scanbridge + +import androidx.compose.animation.core.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import scanbridge.sharedui.generated.resources.* +import io.github.chrisimx.scanbridge.theme.AppTheme +import io.github.chrisimx.scanbridge.theme.LocalThemeIsDark +import kotlinx.coroutines.isActive +import org.jetbrains.compose.resources.Font +import org.jetbrains.compose.resources.stringResource +import org.jetbrains.compose.resources.vectorResource + +@Preview +@Composable +fun App( + onThemeChanged: @Composable (isDark: Boolean) -> Unit = {} +) = AppTheme(onThemeChanged) { + Column( + modifier = Modifier + .fillMaxSize() + .windowInsetsPadding(WindowInsets.safeDrawing) + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(Res.string.cyclone), + fontFamily = FontFamily(Font(Res.font.IndieFlower_Regular)), + style = MaterialTheme.typography.displayLarge + ) + + var isRotating by remember { mutableStateOf(false) } + + val rotate = remember { Animatable(0f) } + val target = 360f + if (isRotating) { + LaunchedEffect(Unit) { + while (isActive) { + val remaining = (target - rotate.value) / target + rotate.animateTo(target, animationSpec = tween((1_000 * remaining).toInt(), easing = LinearEasing)) + rotate.snapTo(0f) + } + } + } + + Image( + modifier = Modifier + .size(250.dp) + .padding(16.dp) + .run { rotate(rotate.value) }, + imageVector = vectorResource(Res.drawable.ic_cyclone), + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurface), + contentDescription = null + ) + + ElevatedButton( + modifier = Modifier + .padding(horizontal = 8.dp, vertical = 4.dp) + .widthIn(min = 200.dp), + onClick = { isRotating = !isRotating }, + content = { + Icon(vectorResource(Res.drawable.ic_rotate_right), contentDescription = null) + Spacer(Modifier.size(ButtonDefaults.IconSpacing)) + Text( + stringResource(if (isRotating) Res.string.stop else Res.string.run) + ) + } + ) + + var isDark by LocalThemeIsDark.current + val icon = remember(isDark) { + if (isDark) Res.drawable.ic_light_mode + else Res.drawable.ic_dark_mode + } + + ElevatedButton( + modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp).widthIn(min = 200.dp), + onClick = { isDark = !isDark }, + content = { + Icon(vectorResource(icon), contentDescription = null) + Spacer(Modifier.size(ButtonDefaults.IconSpacing)) + Text(stringResource(Res.string.theme)) + } + ) + + val uriHandler = LocalUriHandler.current + TextButton( + modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp).widthIn(min = 200.dp), + onClick = { uriHandler.openUri("https://github.com/terrakok") }, + ) { + Text(stringResource(Res.string.open_github)) + } + } +} diff --git a/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt b/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt new file mode 100644 index 0000000..7c5ad72 --- /dev/null +++ b/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt @@ -0,0 +1,80 @@ +package io.github.chrisimx.scanbridge.theme + +import androidx.compose.ui.graphics.Color + +//generated by https://materialkolor.com +//Color palette was taken here: https://coolors.co/palette/e63946-f1faee-a8dadc-457b9d-1d3557 + +internal val Seed = Color(0xFF1D3557) + +internal val PrimaryLight = Color(0xFF485F84) +internal val OnPrimaryLight = Color(0xFFFFFFFF) +internal val PrimaryContainerLight = Color(0xFFD5E3FF) +internal val OnPrimaryContainerLight = Color(0xFF30476A) +internal val SecondaryLight = Color(0xFF2B6485) +internal val OnSecondaryLight = Color(0xFFFFFFFF) +internal val SecondaryContainerLight = Color(0xFFC7E7FF) +internal val OnSecondaryContainerLight = Color(0xFF064C6B) +internal val TertiaryLight = Color(0xFF356668) +internal val OnTertiaryLight = Color(0xFFFFFFFF) +internal val TertiaryContainerLight = Color(0xFFB9ECEE) +internal val OnTertiaryContainerLight = Color(0xFF1A4E50) +internal val ErrorLight = Color(0xFFBB152C) +internal val OnErrorLight = Color(0xFFFFFFFF) +internal val ErrorContainerLight = Color(0xFFFFDAD8) +internal val OnErrorContainerLight = Color(0xFF410007) +internal val BackgroundLight = Color(0xFFF9F9F9) +internal val OnBackgroundLight = Color(0xFF1A1C1C) +internal val SurfaceLight = Color(0xFFF9F9F9) +internal val OnSurfaceLight = Color(0xFF1A1C1C) +internal val SurfaceVariantLight = Color(0xFFDCE5D9) +internal val OnSurfaceVariantLight = Color(0xFF404941) +internal val OutlineLight = Color(0xFF717970) +internal val OutlineVariantLight = Color(0xFFC0C9BE) +internal val ScrimLight = Color(0xFF000000) +internal val InverseSurfaceLight = Color(0xFF2F3131) +internal val InverseOnSurfaceLight = Color(0xFFF0F1F1) +internal val InversePrimaryLight = Color(0xFFB0C7F1) +internal val SurfaceDimLight = Color(0xFFDADADA) +internal val SurfaceBrightLight = Color(0xFFF9F9F9) +internal val SurfaceContainerLowestLight = Color(0xFFFFFFFF) +internal val SurfaceContainerLowLight = Color(0xFFF3F3F4) +internal val SurfaceContainerLight = Color(0xFFEEEEEE) +internal val SurfaceContainerHighLight = Color(0xFFE8E8E8) +internal val SurfaceContainerHighestLight = Color(0xFFE2E2E2) + +internal val PrimaryDark = Color(0xFFB0C7F1) +internal val OnPrimaryDark = Color(0xFF183153) +internal val PrimaryContainerDark = Color(0xFF30476A) +internal val OnPrimaryContainerDark = Color(0xFFD5E3FF) +internal val SecondaryDark = Color(0xFF98CDF2) +internal val OnSecondaryDark = Color(0xFF00344C) +internal val SecondaryContainerDark = Color(0xFF064C6B) +internal val OnSecondaryContainerDark = Color(0xFFC7E7FF) +internal val TertiaryDark = Color(0xFF9ECFD1) +internal val OnTertiaryDark = Color(0xFF003739) +internal val TertiaryContainerDark = Color(0xFF1A4E50) +internal val OnTertiaryContainerDark = Color(0xFFB9ECEE) +internal val ErrorDark = Color(0xFFFFB3B1) +internal val OnErrorDark = Color(0xFF680011) +internal val ErrorContainerDark = Color(0xFF92001C) +internal val OnErrorContainerDark = Color(0xFFFFDAD8) +internal val BackgroundDark = Color(0xFF121414) +internal val OnBackgroundDark = Color(0xFFE2E2E2) +internal val SurfaceDark = Color(0xFF121414) +internal val OnSurfaceDark = Color(0xFFE2E2E2) +internal val SurfaceVariantDark = Color(0xFF404941) +internal val OnSurfaceVariantDark = Color(0xFFC0C9BE) +internal val OutlineDark = Color(0xFF8A9389) +internal val OutlineVariantDark = Color(0xFF404941) +internal val ScrimDark = Color(0xFF000000) +internal val InverseSurfaceDark = Color(0xFFE2E2E2) +internal val InverseOnSurfaceDark = Color(0xFF2F3131) +internal val InversePrimaryDark = Color(0xFF485F84) +internal val SurfaceDimDark = Color(0xFF121414) +internal val SurfaceBrightDark = Color(0xFF37393A) +internal val SurfaceContainerLowestDark = Color(0xFF0C0F0F) +internal val SurfaceContainerLowDark = Color(0xFF1A1C1C) +internal val SurfaceContainerDark = Color(0xFF1E2020) +internal val SurfaceContainerHighDark = Color(0xFF282A2B) +internal val SurfaceContainerHighestDark = Color(0xFF333535) diff --git a/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt b/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt new file mode 100644 index 0000000..9de99dc --- /dev/null +++ b/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt @@ -0,0 +1,105 @@ +package io.github.chrisimx.scanbridge.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.* + +private val LightColorScheme = lightColorScheme( + primary = PrimaryLight, + onPrimary = OnPrimaryLight, + primaryContainer = PrimaryContainerLight, + onPrimaryContainer = OnPrimaryContainerLight, + secondary = SecondaryLight, + onSecondary = OnSecondaryLight, + secondaryContainer = SecondaryContainerLight, + onSecondaryContainer = OnSecondaryContainerLight, + tertiary = TertiaryLight, + onTertiary = OnTertiaryLight, + tertiaryContainer = TertiaryContainerLight, + onTertiaryContainer = OnTertiaryContainerLight, + error = ErrorLight, + onError = OnErrorLight, + errorContainer = ErrorContainerLight, + onErrorContainer = OnErrorContainerLight, + background = BackgroundLight, + onBackground = OnBackgroundLight, + surface = SurfaceLight, + onSurface = OnSurfaceLight, + surfaceVariant = SurfaceVariantLight, + onSurfaceVariant = OnSurfaceVariantLight, + outline = OutlineLight, + outlineVariant = OutlineVariantLight, + scrim = ScrimLight, + inverseSurface = InverseSurfaceLight, + inverseOnSurface = InverseOnSurfaceLight, + inversePrimary = InversePrimaryLight, + surfaceDim = SurfaceDimLight, + surfaceBright = SurfaceBrightLight, + surfaceContainerLowest = SurfaceContainerLowestLight, + surfaceContainerLow = SurfaceContainerLowLight, + surfaceContainer = SurfaceContainerLight, + surfaceContainerHigh = SurfaceContainerHighLight, + surfaceContainerHighest = SurfaceContainerHighestLight, +) + +private val DarkColorScheme = darkColorScheme( + primary = PrimaryDark, + onPrimary = OnPrimaryDark, + primaryContainer = PrimaryContainerDark, + onPrimaryContainer = OnPrimaryContainerDark, + secondary = SecondaryDark, + onSecondary = OnSecondaryDark, + secondaryContainer = SecondaryContainerDark, + onSecondaryContainer = OnSecondaryContainerDark, + tertiary = TertiaryDark, + onTertiary = OnTertiaryDark, + tertiaryContainer = TertiaryContainerDark, + onTertiaryContainer = OnTertiaryContainerDark, + error = ErrorDark, + onError = OnErrorDark, + errorContainer = ErrorContainerDark, + onErrorContainer = OnErrorContainerDark, + background = BackgroundDark, + onBackground = OnBackgroundDark, + surface = SurfaceDark, + onSurface = OnSurfaceDark, + surfaceVariant = SurfaceVariantDark, + onSurfaceVariant = OnSurfaceVariantDark, + outline = OutlineDark, + outlineVariant = OutlineVariantDark, + scrim = ScrimDark, + inverseSurface = InverseSurfaceDark, + inverseOnSurface = InverseOnSurfaceDark, + inversePrimary = InversePrimaryDark, + surfaceDim = SurfaceDimDark, + surfaceBright = SurfaceBrightDark, + surfaceContainerLowest = SurfaceContainerLowestDark, + surfaceContainerLow = SurfaceContainerLowDark, + surfaceContainer = SurfaceContainerDark, + surfaceContainerHigh = SurfaceContainerHighDark, + surfaceContainerHighest = SurfaceContainerHighestDark, +) + +internal val LocalThemeIsDark = compositionLocalOf { mutableStateOf(true) } + +@Composable +internal fun AppTheme( + onThemeChanged: @Composable (isDark: Boolean) -> Unit, + content: @Composable () -> Unit +) { + val systemIsDark = isSystemInDarkTheme() + val isDarkState = remember(systemIsDark) { mutableStateOf(systemIsDark) } + CompositionLocalProvider( + LocalThemeIsDark provides isDarkState + ) { + val isDark by isDarkState + onThemeChanged(!isDark) + MaterialTheme( + colorScheme = if (isDark) DarkColorScheme else LightColorScheme, + content = { Surface(content = content) } + ) + } +} diff --git a/shared/src/iosMain/kotlin/main.kt b/shared/src/iosMain/kotlin/main.kt new file mode 100644 index 0000000..2d86d9b --- /dev/null +++ b/shared/src/iosMain/kotlin/main.kt @@ -0,0 +1,22 @@ +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.window.ComposeUIViewController +import io.github.chrisimx.scanbridge.App +import platform.UIKit.UIApplication +import platform.UIKit.UIStatusBarStyleDarkContent +import platform.UIKit.UIStatusBarStyleLightContent +import platform.UIKit.UIViewController +import platform.UIKit.setStatusBarStyle + +fun MainViewController(): UIViewController = ComposeUIViewController { + App(onThemeChanged = { ThemeChanged(it) }) +} + +@Composable +private fun ThemeChanged(isDark: Boolean) { + LaunchedEffect(isDark) { + UIApplication.sharedApplication.setStatusBarStyle( + if (isDark) UIStatusBarStyleDarkContent else UIStatusBarStyleLightContent + ) + } +} From 07877c3387fa3c31f24c65ba98add88118da0554 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Fri, 3 Apr 2026 22:58:17 +0200 Subject: [PATCH 03/26] Make changes for multi-platform compatability --- androidApp/build.gradle.kts | 3 + .../chrisimx/scanbridge/ScanBridgeApp.kt | 1 - .../chrisimx/scanbridge/ScanningScreen.kt | 4 +- .../github/chrisimx/scanbridge/theme/Font.kt | 36 ---- .../chrisimx/scanbridge/theme/Typography.kt | 177 ---------------- .../scanbridge/uicomponents/TitledCard.kt | 3 +- .../settings/VersionComposable.kt | 6 +- {shared => core}/.gitignore | 0 core/build.gradle.kts | 59 ++++++ {shared => core}/src/iosMain/kotlin/main.kt | 0 desktopApp/build.gradle.kts | 2 +- settings-gradle.lockfile | 4 + settings.gradle.kts | 3 +- .../font/IndieFlower-Regular.ttf | Bin 55416 -> 0 bytes .../composeResources/values/strings.xml | 7 - .../io/github/chrisimx/scanbridge/App.kt | 104 --------- sharedUI/.gitignore | 2 + {shared => sharedUI}/build.gradle.kts | 16 +- .../scanbridge/theme/Theme.android.kt | 28 +++ .../chrisimx/scanbridge/theme/Theme.apple.kt | 8 + .../composeResources/drawable/ic_cyclone.xml | 0 .../drawable/ic_dark_mode.xml | 0 .../drawable/ic_light_mode.xml | 0 .../drawable/ic_rotate_right.xml | 0 .../composeResources}/font/poppins_black.ttf | Bin .../font/poppins_blackitalic.ttf | Bin .../composeResources}/font/poppins_bold.ttf | Bin .../font/poppins_bolditalic.ttf | Bin .../font/poppins_extrabold.ttf | Bin .../font/poppins_extrabolditalic.ttf | Bin .../font/poppins_extralight.ttf | Bin .../font/poppins_extralightitalic.ttf | Bin .../composeResources}/font/poppins_italic.ttf | Bin .../composeResources}/font/poppins_light.ttf | Bin .../font/poppins_lightitalic.ttf | Bin .../composeResources}/font/poppins_medium.ttf | Bin .../font/poppins_mediumitalic.ttf | Bin .../font/poppins_regular.ttf | Bin .../font/poppins_semibold.ttf | Bin .../font/poppins_semibolditalic.ttf | Bin .../composeResources}/font/poppins_thin.ttf | Bin .../font/poppins_thinitalic.ttf | Bin .../composeResources/values-de/strings.xml | 127 +++++++++++ .../composeResources/values-it/strings.xml | 126 +++++++++++ .../composeResources/values/strings.xml | 129 ++++++++++++ .../github/chrisimx/scanbridge/theme/Color.kt | 5 +- .../chrisimx/scanbridge/theme/Color.kt.ig | 0 .../github/chrisimx/scanbridge/theme/Theme.kt | 28 ++- .../chrisimx/scanbridge/theme/Theme.kt.ig | 0 .../chrisimx/scanbridge/theme/Typography.kt | 199 ++++++++++++++++++ .../scanbridge/uicomponents/LoadingScreen.kt | 22 +- 51 files changed, 744 insertions(+), 355 deletions(-) delete mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt delete mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt rename {shared => core}/.gitignore (100%) create mode 100644 core/build.gradle.kts rename {shared => core}/src/iosMain/kotlin/main.kt (100%) create mode 100644 settings-gradle.lockfile delete mode 100644 shared/src/commonMain/composeResources/font/IndieFlower-Regular.ttf delete mode 100644 shared/src/commonMain/composeResources/values/strings.xml delete mode 100644 shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/App.kt create mode 100644 sharedUI/.gitignore rename {shared => sharedUI}/build.gradle.kts (83%) create mode 100644 sharedUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt create mode 100644 sharedUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt rename {shared => sharedUI}/src/commonMain/composeResources/drawable/ic_cyclone.xml (100%) rename {shared => sharedUI}/src/commonMain/composeResources/drawable/ic_dark_mode.xml (100%) rename {shared => sharedUI}/src/commonMain/composeResources/drawable/ic_light_mode.xml (100%) rename {shared => sharedUI}/src/commonMain/composeResources/drawable/ic_rotate_right.xml (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_black.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_blackitalic.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_bold.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_bolditalic.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_extrabold.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_extrabolditalic.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_extralight.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_extralightitalic.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_italic.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_light.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_lightitalic.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_medium.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_mediumitalic.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_regular.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_semibold.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_semibolditalic.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_thin.ttf (100%) rename {androidApp/src/main/res => sharedUI/src/commonMain/composeResources}/font/poppins_thinitalic.ttf (100%) create mode 100644 sharedUI/src/commonMain/composeResources/values-de/strings.xml create mode 100644 sharedUI/src/commonMain/composeResources/values-it/strings.xml create mode 100644 sharedUI/src/commonMain/composeResources/values/strings.xml rename {androidApp/src/main/java => sharedUI/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/theme/Color.kt (90%) rename shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt => sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt.ig (100%) rename {androidApp/src/main/java => sharedUI/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/theme/Theme.kt (75%) rename shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt => sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt.ig (100%) create mode 100644 sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt rename {androidApp/src/main/java => sharedUI/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt (78%) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 32ce3b8..cfabc5f 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -110,6 +110,9 @@ dependencies { implementation(libs.timber) implementation(libs.androidx.navigation.compose) implementation(libs.kotlinx.serialization.json) + implementation(project(":core")) + implementation(project(":sharedUI")) + implementation("androidx.concurrent:concurrent-futures:1.2.0") ksp(libs.androidx.room.compiler) implementation(libs.androidx.room.runtime) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt index 5d39c22..01c5ee7 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt @@ -23,7 +23,6 @@ import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Favorite import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ExperimentalMaterial3Api // TODO: import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.Text diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt index 0e695d2..e5a4937 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt @@ -115,6 +115,8 @@ import me.saket.telephoto.zoomable.rememberZoomableState import me.saket.telephoto.zoomable.zoomable import org.koin.androidx.compose.koinViewModel import org.koin.core.parameter.parametersOf +import scanbridge.sharedui.generated.resources.Res +import scanbridge.sharedui.generated.resources.trying_to_retrieve_scannercapabilities import timber.log.Timber private const val TAG = "ScanningScreen" @@ -354,7 +356,7 @@ fun ScanningScreen( } LoadingScreen( - loadingText = R.string.trying_to_retrieve_scannercapabilities + loadingText = Res.string.trying_to_retrieve_scannercapabilities ) } diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt deleted file mode 100644 index 8fdf3d9..0000000 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Font.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.chrisimx.scanbridge.theme - -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight -import io.github.chrisimx.scanbridge.R - -val Poppins = FontFamily( - Font(R.font.poppins_thin, weight = FontWeight.Thin), - Font(R.font.poppins_thinitalic, weight = FontWeight.Thin, style = FontStyle.Italic), - - Font(R.font.poppins_extralight, weight = FontWeight.ExtraLight), - Font(R.font.poppins_extralightitalic, weight = FontWeight.ExtraLight, style = FontStyle.Italic), - - Font(R.font.poppins_light, weight = FontWeight.Light), - Font(R.font.poppins_lightitalic, weight = FontWeight.Light, style = FontStyle.Italic), - - Font(R.font.poppins_regular, weight = FontWeight.Normal), - Font(R.font.poppins_italic, weight = FontWeight.Normal, style = FontStyle.Italic), - - Font(R.font.poppins_medium, weight = FontWeight.Medium), - Font(R.font.poppins_mediumitalic, weight = FontWeight.Medium, style = FontStyle.Italic), - - Font(R.font.poppins_semibold, weight = FontWeight.SemiBold), - Font(R.font.poppins_semibolditalic, weight = FontWeight.SemiBold, style = FontStyle.Italic), - - Font(R.font.poppins_bold, weight = FontWeight.Bold), - Font(R.font.poppins_bolditalic, weight = FontWeight.Bold, style = FontStyle.Italic), - - Font(R.font.poppins_extrabold, weight = FontWeight.ExtraBold), - Font(R.font.poppins_extrabolditalic, weight = FontWeight.ExtraBold, style = FontStyle.Italic), - - Font(R.font.poppins_black, weight = FontWeight.Black), - Font(R.font.poppins_blackitalic, weight = FontWeight.Black, style = FontStyle.Italic) -) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt deleted file mode 100644 index a99f7cf..0000000 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Typography.kt +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2024-2025 Christian Nagel and contributors - * - * This file is part of ScanBridge. - * - * ScanBridge is free software: you can redistribute it and/or modify it under the terms of - * the GNU General Public License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * ScanBridge is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with eSCLKt. - * If not, see . - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -package io.github.chrisimx.scanbridge.theme - -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.Typography -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp - -// Set of Material typography styles to start with -@OptIn(ExperimentalMaterial3ExpressiveApi::class) -val Typography = Typography( - titleSmall = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 20.sp, - letterSpacing = 0.sp - ), - titleMedium = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - fontSize = 18.sp, - lineHeight = 24.sp, - letterSpacing = 0.sp - ), - titleMediumEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - fontSize = 18.sp, - lineHeight = 24.sp, - letterSpacing = 0.sp - ), - titleLarge = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - fontSize = 22.sp, - lineHeight = 28.sp, - letterSpacing = 0.sp - ), - titleLargeEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - fontSize = 22.sp, - lineHeight = 28.sp, - letterSpacing = 0.sp - ), - labelSmall = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - lineHeight = 14.sp, - fontSize = 11.sp, - letterSpacing = 0.sp - ), - labelMedium = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - lineHeight = 14.sp, - fontSize = 14.sp, - letterSpacing = 0.sp - ), - labelLarge = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - letterSpacing = 0.sp - ), - bodySmall = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - letterSpacing = 0.sp - ), - bodySmallEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - letterSpacing = 0.sp - ), - bodyMedium = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - letterSpacing = 0.sp - ), - bodyMediumEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - letterSpacing = 0.sp - ), - bodyLarge = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.5.sp - ), - bodyLargeEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.5.sp - ), - displaySmall = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - letterSpacing = 0.sp - ), - displayMedium = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - letterSpacing = 0.sp - ), - displayLarge = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - letterSpacing = 0.sp - ), - displaySmallEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - letterSpacing = 0.sp - ), - displayMediumEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - letterSpacing = 0.sp - ), - displayLargeEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - letterSpacing = 0.sp - ), - headlineLarge = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - fontSize = 24.sp, - lineHeight = 32.sp, - letterSpacing = 0.sp - ), - headlineMedium = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - fontSize = 20.sp, - lineHeight = 28.sp, - letterSpacing = 0.sp - ), - headlineMediumEmphasized = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.ExtraBold, - fontSize = 20.sp, - lineHeight = 28.sp, - letterSpacing = 0.sp - ), - headlineSmall = TextStyle( - fontFamily = Poppins, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.sp - ) -) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt index b11e919..866b9a1 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.github.chrisimx.scanbridge.theme.Poppins +import io.github.chrisimx.scanbridge.theme.PoppinsTypography import io.github.chrisimx.scanbridge.theme.Teal1 @Composable @@ -47,7 +48,7 @@ fun TitledCard(title: String, color: Color = Teal1, content: @Composable () -> U Text( title, modifier = Modifier.padding(bottom = 16.dp), - fontFamily = Poppins, + fontFamily = Poppins(), fontWeight = FontWeight.SemiBold, fontSize = 20.sp, color = color diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt index 7424eb8..58c7cfd 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/settings/VersionComposable.kt @@ -58,7 +58,7 @@ fun VersionComposable() { Text( stringResource(R.string.app_name), modifier = Modifier.padding(PaddingValues(4.dp)), - fontFamily = Poppins, + fontFamily = Poppins(), fontSize = 24.sp, fontWeight = FontWeight.ExtraBold, style = MaterialTheme.typography.labelLarge.copy( @@ -69,7 +69,7 @@ fun VersionComposable() { Text( "${BuildConfig.VERSION_NAME.removeSuffix("-play")} (${BuildConfig.VERSION_CODE}, ${BuildConfig.GIT_COMMIT_HASH})", fontStyle = FontStyle.Normal, - fontFamily = Poppins + fontFamily = Poppins() ) val editionNotice = mutableListOf() @@ -87,7 +87,7 @@ fun VersionComposable() { Text( editionNotice.joinToString(), fontStyle = FontStyle.Italic, - fontFamily = Poppins + fontFamily = Poppins() ) } diff --git a/shared/.gitignore b/core/.gitignore similarity index 100% rename from shared/.gitignore rename to core/.gitignore diff --git a/core/build.gradle.kts b/core/build.gradle.kts new file mode 100644 index 0000000..6a9dba5 --- /dev/null +++ b/core/build.gradle.kts @@ -0,0 +1,59 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget + +plugins { + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.android.kmp.library) +} + +kotlin { + jvm { + compilerOptions { jvmTarget = JvmTarget.JVM_17 } + } + + android { + namespace = "io.github.chrisimx.scanbridge" + compileSdk = 36 + minSdk = 23 + + /*compilerOptions.configure { + jvmTarget.set( + org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + ) + }*/ + } + + + iosArm64() + iosSimulatorArm64() + + sourceSets { + commonMain.dependencies { + + } + + commonTest.dependencies { + + } + + androidMain.dependencies { + } + + jvmMain.dependencies { + } + + } + + targets + .withType() + .matching { it.konanTarget.family.isAppleFamily } + .configureEach { + binaries { + framework { + baseName = "ScanBridgeCore" + isStatic = true + } + } + } +} diff --git a/shared/src/iosMain/kotlin/main.kt b/core/src/iosMain/kotlin/main.kt similarity index 100% rename from shared/src/iosMain/kotlin/main.kt rename to core/src/iosMain/kotlin/main.kt diff --git a/desktopApp/build.gradle.kts b/desktopApp/build.gradle.kts index ab29143..3733006 100644 --- a/desktopApp/build.gradle.kts +++ b/desktopApp/build.gradle.kts @@ -6,7 +6,7 @@ plugins { alias(libs.plugins.kotlin.jvm) } dependencies { - implementation(project(":shared")) + implementation(project(":sharedUI")) } compose.desktop { diff --git a/settings-gradle.lockfile b/settings-gradle.lockfile new file mode 100644 index 0000000..709a43f --- /dev/null +++ b/settings-gradle.lockfile @@ -0,0 +1,4 @@ +# This is a Gradle generated file for dependency locking. +# Manual edits can break the build and are not advised. +# This file is expected to be part of source control. +empty=incomingCatalogForLibs0 diff --git a/settings.gradle.kts b/settings.gradle.kts index 0481b86..d0308ec 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -32,7 +32,8 @@ dependencyResolutionManagement { } } -include(":shared") +include(":sharedUI") +include(":core") include(":androidApp") include(":desktopApp") include(":lvl_library") diff --git a/shared/src/commonMain/composeResources/font/IndieFlower-Regular.ttf b/shared/src/commonMain/composeResources/font/IndieFlower-Regular.ttf deleted file mode 100644 index 3774ef55d4dd8d0d272f602542bbbf444ebbbb23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55416 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 - Cyclone - Open github - Run - Stop - Theme - \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/App.kt b/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/App.kt deleted file mode 100644 index e726714..0000000 --- a/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/App.kt +++ /dev/null @@ -1,104 +0,0 @@ -package io.github.chrisimx.scanbridge - -import androidx.compose.animation.core.* -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.* -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.rotate -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import scanbridge.sharedui.generated.resources.* -import io.github.chrisimx.scanbridge.theme.AppTheme -import io.github.chrisimx.scanbridge.theme.LocalThemeIsDark -import kotlinx.coroutines.isActive -import org.jetbrains.compose.resources.Font -import org.jetbrains.compose.resources.stringResource -import org.jetbrains.compose.resources.vectorResource - -@Preview -@Composable -fun App( - onThemeChanged: @Composable (isDark: Boolean) -> Unit = {} -) = AppTheme(onThemeChanged) { - Column( - modifier = Modifier - .fillMaxSize() - .windowInsetsPadding(WindowInsets.safeDrawing) - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - text = stringResource(Res.string.cyclone), - fontFamily = FontFamily(Font(Res.font.IndieFlower_Regular)), - style = MaterialTheme.typography.displayLarge - ) - - var isRotating by remember { mutableStateOf(false) } - - val rotate = remember { Animatable(0f) } - val target = 360f - if (isRotating) { - LaunchedEffect(Unit) { - while (isActive) { - val remaining = (target - rotate.value) / target - rotate.animateTo(target, animationSpec = tween((1_000 * remaining).toInt(), easing = LinearEasing)) - rotate.snapTo(0f) - } - } - } - - Image( - modifier = Modifier - .size(250.dp) - .padding(16.dp) - .run { rotate(rotate.value) }, - imageVector = vectorResource(Res.drawable.ic_cyclone), - colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurface), - contentDescription = null - ) - - ElevatedButton( - modifier = Modifier - .padding(horizontal = 8.dp, vertical = 4.dp) - .widthIn(min = 200.dp), - onClick = { isRotating = !isRotating }, - content = { - Icon(vectorResource(Res.drawable.ic_rotate_right), contentDescription = null) - Spacer(Modifier.size(ButtonDefaults.IconSpacing)) - Text( - stringResource(if (isRotating) Res.string.stop else Res.string.run) - ) - } - ) - - var isDark by LocalThemeIsDark.current - val icon = remember(isDark) { - if (isDark) Res.drawable.ic_light_mode - else Res.drawable.ic_dark_mode - } - - ElevatedButton( - modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp).widthIn(min = 200.dp), - onClick = { isDark = !isDark }, - content = { - Icon(vectorResource(icon), contentDescription = null) - Spacer(Modifier.size(ButtonDefaults.IconSpacing)) - Text(stringResource(Res.string.theme)) - } - ) - - val uriHandler = LocalUriHandler.current - TextButton( - modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp).widthIn(min = 200.dp), - onClick = { uriHandler.openUri("https://github.com/terrakok") }, - ) { - Text(stringResource(Res.string.open_github)) - } - } -} diff --git a/sharedUI/.gitignore b/sharedUI/.gitignore new file mode 100644 index 0000000..92e0b0f --- /dev/null +++ b/sharedUI/.gitignore @@ -0,0 +1,2 @@ +/build +build \ No newline at end of file diff --git a/shared/build.gradle.kts b/sharedUI/build.gradle.kts similarity index 83% rename from shared/build.gradle.kts rename to sharedUI/build.gradle.kts index b7fdc16..45c3725 100644 --- a/shared/build.gradle.kts +++ b/sharedUI/build.gradle.kts @@ -18,6 +18,7 @@ kotlin { namespace = "io.github.chrisimx.scanbridge" compileSdk = 36 minSdk = 23 + androidResources.enable = true /*compilerOptions.configure { jvmTarget.set( @@ -38,7 +39,6 @@ kotlin { api(libs.compose.resources) api(libs.compose.ui.tooling.preview) api(libs.compose.material3) - //implementation(libs.compose.ui.tooling) } commonTest.dependencies { @@ -61,9 +61,19 @@ kotlin { .configureEach { binaries { framework { - baseName = "SharedUI" + baseName = "ScanBridgeSharedUI" isStatic = true } } } -} \ No newline at end of file +} + +dependencies { + androidRuntimeClasspath("org.jetbrains.compose.ui:ui-tooling:1.10.0") +} + +compose.resources { + publicResClass = true + //packageOfResClass = "me.sample.library.resources" + generateResClass = always +} diff --git a/sharedUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt b/sharedUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt new file mode 100644 index 0000000..f28865f --- /dev/null +++ b/sharedUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt @@ -0,0 +1,28 @@ +package io.github.chrisimx.scanbridge.theme + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +@Composable +actual fun platformDarkColorScheme(): ColorScheme? = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val context = LocalContext.current + dynamicDarkColorScheme(context) + } else { + null + } + +@Composable +actual fun platformLightColorScheme(): ColorScheme? = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val context = LocalContext.current + dynamicLightColorScheme(context) + } else { + null + } diff --git a/sharedUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt b/sharedUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt new file mode 100644 index 0000000..4ac11d5 --- /dev/null +++ b/sharedUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt @@ -0,0 +1,8 @@ +package io.github.chrisimx.scanbridge.theme + +import androidx.compose.material3.ColorScheme + +@Composable +actual fun platformDarkColorScheme(): ColorScheme? { + TODO("Not yet implemented") +} diff --git a/shared/src/commonMain/composeResources/drawable/ic_cyclone.xml b/sharedUI/src/commonMain/composeResources/drawable/ic_cyclone.xml similarity index 100% rename from shared/src/commonMain/composeResources/drawable/ic_cyclone.xml rename to sharedUI/src/commonMain/composeResources/drawable/ic_cyclone.xml diff --git a/shared/src/commonMain/composeResources/drawable/ic_dark_mode.xml b/sharedUI/src/commonMain/composeResources/drawable/ic_dark_mode.xml similarity index 100% rename from shared/src/commonMain/composeResources/drawable/ic_dark_mode.xml rename to sharedUI/src/commonMain/composeResources/drawable/ic_dark_mode.xml diff --git a/shared/src/commonMain/composeResources/drawable/ic_light_mode.xml b/sharedUI/src/commonMain/composeResources/drawable/ic_light_mode.xml similarity index 100% rename from shared/src/commonMain/composeResources/drawable/ic_light_mode.xml rename to sharedUI/src/commonMain/composeResources/drawable/ic_light_mode.xml diff --git a/shared/src/commonMain/composeResources/drawable/ic_rotate_right.xml b/sharedUI/src/commonMain/composeResources/drawable/ic_rotate_right.xml similarity index 100% rename from shared/src/commonMain/composeResources/drawable/ic_rotate_right.xml rename to sharedUI/src/commonMain/composeResources/drawable/ic_rotate_right.xml diff --git a/androidApp/src/main/res/font/poppins_black.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_black.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_black.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_black.ttf diff --git a/androidApp/src/main/res/font/poppins_blackitalic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_blackitalic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_blackitalic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_blackitalic.ttf diff --git a/androidApp/src/main/res/font/poppins_bold.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_bold.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_bold.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_bold.ttf diff --git a/androidApp/src/main/res/font/poppins_bolditalic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_bolditalic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_bolditalic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_bolditalic.ttf diff --git a/androidApp/src/main/res/font/poppins_extrabold.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_extrabold.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_extrabold.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_extrabold.ttf diff --git a/androidApp/src/main/res/font/poppins_extrabolditalic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_extrabolditalic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_extrabolditalic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_extrabolditalic.ttf diff --git a/androidApp/src/main/res/font/poppins_extralight.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_extralight.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_extralight.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_extralight.ttf diff --git a/androidApp/src/main/res/font/poppins_extralightitalic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_extralightitalic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_extralightitalic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_extralightitalic.ttf diff --git a/androidApp/src/main/res/font/poppins_italic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_italic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_italic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_italic.ttf diff --git a/androidApp/src/main/res/font/poppins_light.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_light.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_light.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_light.ttf diff --git a/androidApp/src/main/res/font/poppins_lightitalic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_lightitalic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_lightitalic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_lightitalic.ttf diff --git a/androidApp/src/main/res/font/poppins_medium.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_medium.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_medium.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_medium.ttf diff --git a/androidApp/src/main/res/font/poppins_mediumitalic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_mediumitalic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_mediumitalic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_mediumitalic.ttf diff --git a/androidApp/src/main/res/font/poppins_regular.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_regular.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_regular.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_regular.ttf diff --git a/androidApp/src/main/res/font/poppins_semibold.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_semibold.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_semibold.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_semibold.ttf diff --git a/androidApp/src/main/res/font/poppins_semibolditalic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_semibolditalic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_semibolditalic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_semibolditalic.ttf diff --git a/androidApp/src/main/res/font/poppins_thin.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_thin.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_thin.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_thin.ttf diff --git a/androidApp/src/main/res/font/poppins_thinitalic.ttf b/sharedUI/src/commonMain/composeResources/font/poppins_thinitalic.ttf similarity index 100% rename from androidApp/src/main/res/font/poppins_thinitalic.ttf rename to sharedUI/src/commonMain/composeResources/font/poppins_thinitalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/values-de/strings.xml b/sharedUI/src/commonMain/composeResources/values-de/strings.xml new file mode 100644 index 0000000..a56588b --- /dev/null +++ b/sharedUI/src/commonMain/composeResources/values-de/strings.xml @@ -0,0 +1,127 @@ + + + Druckersymbol + Einstellungen + Es wurden keine Scanner gefunden. Bist du mit einem lokalen Netzwerk verbunden? + Warnungssymbol + Fehler + Fehler beim Abrufen der Eigenschaften des Scanners:\n\n%1$s + Okay + Die Eigenschaften des Scanners werden abgerufen + Scannen + Abbrechen + Bricht ab… + Eingescannte Seite + Der Scanauftrag wurde annulliert + Der Scanauftrag wurde aufgrund eines Fehlers abgebrochen + Der Scanauftrag wurde erfolgreich fertiggestellt + Der Scanauftrag ist derzeit noch unerledigt + Es werden derzeit noch Seiten verarbeitet + Der Status des Scanauftrags konnte nicht abrufen werden + Seite löschen + Nach links verschieben + Nach rechts verschieben + Seite %1$s von %2$s + Exportieren + Seite wird abgerufen + Wird exportiert… + Bisher keine Seiten. Klicke den Scanbutton :) + Flachbett + ADF + Verfügbare Scanner + Scannersuche + Einstellungen im eSCLKt-Format kopieren + Scaneinstellungen + Außerhalb des unterstützten Bereichs + Ungültige Nummer + Gültig + Quelle: + Auflösung (DPI): + Duplex + Standard + Breite (in %1$s) + Höhe (in %1$s) + Maximum + Benutzerdefiniert + Ein Scanauftrag läuft bereits + Fehler beim Abrufen einer Seite: %1$s + Kopieren + Fehler + Ungespeicherte Scans + Willst du wirklich die Scanoberfläche schließen? Alle Scans, die du nicht exportiert hast, gehen dabei verloren! + Abbrechen + Verlassen + Appsymbol + Debug + Informationen zu dieser Einstellung + Absturzprotokoll gefunden + Ein Absturzprotokoll wurde gefunden. Dies ist der Fehler der zum Absturz führte. Bitte füge ihn deinem Bugreport an: + OK, löschen + Kamera + Temporäre Dateien gefunden + Temporäre Dateien (Scans und/oder Exporte) wurden im App-Speicher gefunden. Diese Dateien verbleiben im App-Speicher, wenn die App aus der Appübersicht geschlossen oder von Android während einer Scansitzung beendet wurde. Der Hauptgrund für diese Nachfrage ist, dass eine Bestätigung für das Löschen in diesem Fall nicht möglich war.\n\nWas möchtest du mit den folgenden Scan- und Exportdateien machen?:\n%1$s + Löschen + Nichts machen + Nach rechts drehen + Wird gedreht… + Auf einen benutzdefinierten Scanner zugreifen + Verbinden + URL (eSCL-Ressource) + Verbinden mit benutzerdefinierten Scanner + Ungültige URL + Gib bitte eine URL ein + Benutzerdefinierter Scanner + Als PDF exportieren + Als JPEG-Archiv exportieren + Keine weiteren Seiten. %1$s + Fehler beim Herunterladen des empfangenen Bilds als Datei: %1$s + Empfangenes Bild konnte nicht dekodiert werden. %1$s + Scanpreset: + Scanbereich: + Willst du wirklich die derzeitig ausgewählte Seite löschen? Dieser Vorgang ist unwiderruflich. + Debugprotokoll aufzeichnen + Alle Debuglogs werden zu einer in den Einstellungen exportierbaren Datei geschrieben. Dies kann zum Erstellen von Fehlerberichten sehr nützlich sein. + Debugprotokoll löschen + Debugprotokoll exportieren + Diese Einstellung legt fest wie lange ScanBridge maximal auf eine Antwort vom Scanner wartet bevor es den Scanversuch abbricht.\n\nDiese Einstellung ist für langsame Scanner und große Scanbereiche nützlich. + Timeoutlänge für Scannerantwort (in Sekunden) + Erweiterte Einstellungen + + Name + HP Deskjet + Entdeckte Scanner + Gespeicherte Scanner + Max. Seitenzahl für pro PDF + "Da der Arbeitsspeicher von Smartphones begrenzt ist kann es schwierig werden sehr große PDFs zu erzeugen. Um Abstürze zu verhindern, teilt ScanBridge einen PDF-Export auf mehrere PDFs auf, wenn die hier festgelegte Grenze überschritten würde. In diesem Fall werden die PDFs in einem ZIP-Archiv zusammengefasst. Falls gewünscht, können die PDFs dann im Nachhinein zusammengeführt werden. \n\nWarnung: Wenn diese Option zu weit erhöht wird und sehr viele Seiten als PDF exportiert werden sollen, kann es zu Abstürzen kommen." + HTTPS-Zertifikatsüberprüfung umgehen + Diese Einstellung deaktiviert alle Zertifikatsprüfungen bei HTTPS-Verbindungen. Jedes Zertifikat wird folglich akzeptiert, egal ob es ungültig oder selbstsigniert ist. Diese Einstellung sollte nicht in unsicheren Netwerken verwendet werden, denn durch sie wird ein Man-in-the-Middle-Angriff leicht durchführbar.\n\nIn den meisten Fällen werden Scanner in privaten Netzwerken oder über VPN-Verbindungen verwendet, wo Authentizität in der Regel keine große Rolle spielt. In solchen Umgebungen ist es unwahrscheinlich, dass das Deaktivieren der Zertifikatsprüfung ein echtes Sicherheitsrisiko darstellt. Und falls Vertraulichkeit oder Authentizität doch eine Rolle spielen, hilft selbst HTTPS nur begrenzt – denn eSCL bietet keinerlei Client-Authentifizierung. Jeder mit Netzwerkzugriff auf den Scanner kann potenziell auf gescannte Seiten zugreifen. + Speichern der zuletzt verwendeten Scaneinstellungen + Wenn diese Option aktiviert ist, werden die zuletzt verwendeten Scaneinstellungen (z.B. Quelle, Duplex usw.) beim Erstellen einer neuen Scansitzung wiederhergestellt.\n\nWenn sie deaktiviert ist, beginnt jede Sitzung mit den standardmäßigen Scaneinstellungen (höchste Auflösung, größtmöglicher Scanbereich). + Für ScanBridge spenden + Den Quellcode anschauen + In Datei speichern + Bild wird geladen… + Seite zuschneiden + Zuschneiden + Seite wird zugeschnitten… + Zoom-Gesten aktivieren + ScanBridge ist abgestürzt :( + Die Eigenschaften des Scanners sollten bereits abgerufen sein wurden jedoch nicht gefunden. + mm + Zoll + Es tut uns leid. ScanBridge ist abgestürzt. Bitte melde dieses Problem und füge die folgende Fehlermeldung bei (du kannst sie mit der Schaltfläche unten kopieren). + Vorherige Sitzung konnte nicht geladen werden… %1$s + Falls du Hilfe brauchst oder Feedback geben willst, kannst du uns gerne über die E-Mail support@fireamp.eu kontaktieren. Wir werden uns sobald wie möglich bei dir melden! + Danke für deinen Kauf von ScanBridge! + Scan läuft… + Gescannte Seiten werden im Hintergrund abgerufen. + Farbmodus: + Schwarz-Weiß + Farbe ({bitdepth} bit) + Automatische Erkennung + Graustufen ({bitdepth} bit) + Speichern + Benutzerdefinierten Scanner bearbeiten + Willst du den benutzerdefinierten Scanner wirklich löschen? Dieser Vorgang ist unwiderruflich. + Benutzerdefinierten Scanner löschen + \ No newline at end of file diff --git a/sharedUI/src/commonMain/composeResources/values-it/strings.xml b/sharedUI/src/commonMain/composeResources/values-it/strings.xml new file mode 100644 index 0000000..7ebb1aa --- /dev/null +++ b/sharedUI/src/commonMain/composeResources/values-it/strings.xml @@ -0,0 +1,126 @@ + + Icona stampante + Impostazioni + Nessuno scanner disponibile. Sei connesso alla rete locale? + Icona di avviso + Errore + Si è verificato un errore durante il tentativo di recuperare le funzionalità dello scanner:\n\n%1$s + OK + Tentativo di recupero delle funzionalità dello scanner + Scansiona + Annullamento in corso… + Pagina scansionata + L\'attività è stata annullata + L\'attività è stata interrotta a causa di un errore + L\'attività è stata completata correttamente + L\'attività è ancora in sospeso + Le pagine sono ancora in elaborazione + Impossibile recuperare lo stato dell\'attività + Elimina la pagina corrente + Scambia con la pagina precedente + Scambia con la pagina successiva + Pagina %1$s di %2$s + Esporta + Recupero della pagina + Esportazione in corso… + Nessuna pagina è stata ancora scansionata. Fai clic sul pulsante Scansiona :) + Piana/Vetro + Alimentatore + Scanner disponibili + Analisi della rete + Copia le impostazioni di scansione correnti in formato eSCLKt + Impostazioni di scansione + Valore fuori dall\'intervallo consentito + Numero non valido + Valido + Sorgente di input: + Risoluzione utilizzata (dpi): + Duplex + Predefinito + Larghezza (in %1$s) + Altezza (in %1$s) + Dimensione massima + Personalizzato + Attività ancora in esecuzione + Errore durante il recupero della pagina: %1$s + Copia + Errore + Scansioni non salvate + Vuoi davvero chiudere l\'attività di scansione? Tutte le scansioni non esportate andranno perse! + Annulla + Esci + Icona applicazione + Debug + Ulteriori informazioni su questa impostazione + Registro degli arresti anomali trovato + Registro degli arresti anomali individuato. Questa è l\'eccezione che ha causato l\'arresto anomalo. Allega questo messaggio alla tua segnalazione di bug: + OK, eliminalo + Fotocamera + Trovati file temporanei + Sono stati trovati file temporanei (scansioni e/o esportazioni) nell\'archivio dell\'app. Si tratta di file che rimangono nell\'archivio dell\'app se l\'app viene chiusa dall\'anteprima o interrotta da Android durante una sessione di scansione. Il motivo principale di questo avviso è che, chiudendo l\'app in questo modo, non era possibile confermare l\'eliminazione.\n\nCosa vuoi fare con i seguenti file di scansione ed esportazione?:\n%1$s + Elimina + Non fare nulla + Ruota a destra + Rotazione in corso… + Accedi allo scanner personalizzato + Connettiti + URL (risorsa eSCL) + Connettiti a uno scanner personalizzato + URL non valido + Per favore inserisci un URL + Scanner personalizzato + Esporta come PDF + Esporta come archivio di file JPEG + Nessuna pagina aggiuntiva. %1$s + Errore durante la copia dell\'immagine ricevuta nel file: %1$s + Impossibile decodificare l\'immagine ricevuta. %1$s + Modalità di scansione: + Area di scansione: + Eliminare la pagina corrente? Questa azione non può essere annullata. + Log di debug + Tutti i dati di log disponibili verranno scritti in un file esportabile. Utile per inviare segnalazioni di bug. + Cancella registro di debug + Esporta registro di debug + Questo timeout indica per quanto tempo ScanBridge aspetta la risposta dello scanner prima di interrompere la scansione.\n\nÈ particolarmente utile quando si usano scanner lenti o si devono scansionare aree molto grandi, che richiedono più tempo per la scansione. + Timeout di risposta (in secondi) + Impostazioni avanzate + + Nome + HP Deskjet + Scanner rilevati + Scanner salvati + Numero massimo di pagine per file PDF + Poiché uno smartphone ha una memoria limitata, può diventare difficile gestire PDF di grandi dimensioni. Per evitare arresti anomali, ScanBridge limita il numero massimo di pagine memorizzate in un file PDF quando si esportano pagine scansionate in PDF. Se ci sono troppe pagine, vengono creati più PDF e archiviati in un archivio ZIP. Se necessario, i file PDF possono essere uniti successivamente.\n\nAttenzione: un aumento eccessivo di questo valore può causare arresti anomali durante l\'esportazione di un numero elevato di pagine. + Disabilita controlli certificati + Questa opzione disabilita la convalida di tutti i certificati HTTPS. Verrà accettato qualsiasi certificato, inclusi quelli autofirmati, scaduti o non validi. Non utilizzare questa opzione su reti pubbliche o non sicure, poiché rende possibili attacchi man-in-the-middle (MitM). Nella maggior parte dei casi, gli scanner vengono utilizzati su reti private o tramite connessioni VPN, dove le criticità sull\'autenticazione sono minime. In tali ambienti, è improbabile che la disabilitazione dei controlli dei certificati rappresenti un rischio reale per la sicurezza. E nel caso in cui la riservatezza o l\'autenticità siano un problema, anche HTTPS non sarà di grande aiuto, poiché eSCL non dispone di autenticazione client. Chiunque abbia accesso alla rete può potenzialmente recuperare le pagine scansionate. + Ricorda le impostazioni di scansione + Se abilitata, quando si crea una nuova sessione di scansione verranno ripristinate le ultime impostazioni di scansione utilizzate (sorgente di input, duplex, ecc.). Se disabilitata, ogni sessione inizia con le impostazioni di scansione predefinite (massima risoluzione, area di scansione più ampia possibile). + Dona a ScanBridge + Codice sorgente + Annulla + Salva in file + Caricamento dell’immagine… + La sessione precedente non può essere caricata… %1$s + Le proprietà dello scanner dovrebbero essere già state recuperate, ma non sono state trovate. + mm + Ritaglia pagina + Ritaglia + La pagina viene ritagliata… + Attiva i gesti di zoom + ScanBridge si è bloccato :( + Ci dispiace. ScanBridge si è bloccato. Si prega di segnalare questo problema e di allegare il seguente messaggio di errore (puoi copiarlo con il pulsante in basso). + pollice + Se hai bisogno di aiuto o vuoi inviarci un feedback, puoi contattarci liberamente all’indirizzo support@fireamp.eu . Ti risponderemo il prima possibile! + Grazie per aver acquistato ScanBridge! + Scansione in corso… + Le pagine scansionate vengono recuperate in background. + Modalità colore: + Bianco e nero + Colore ({bitdepth} bit) + Rilevamento automatico + Scala di grigi ({bitdepth} bit) + Salva + Modifica scanner personalizzato + Vuoi davvero eliminare lo scanner personalizzato? Questa operazione è irreversibile. + Elimina scanner personalizzato + \ No newline at end of file diff --git a/sharedUI/src/commonMain/composeResources/values/strings.xml b/sharedUI/src/commonMain/composeResources/values/strings.xml new file mode 100644 index 0000000..1d72524 --- /dev/null +++ b/sharedUI/src/commonMain/composeResources/values/strings.xml @@ -0,0 +1,129 @@ + + ScanBridge + Printer icon + Settings + No scanners found. Are you connected to a local network? + Warning icon + Error + An error occurred while trying to retrieve scanner capabilities:\n\n%1$s + Okay + Trying to retrieve ScannerCapabilities + Scan + Cancel + Cancelling… + A scanned page + The job was canceled + The job was aborted because of an error + The job was completed successfully + The job is still pending + The pages are still processed + The job state can\'t be retrieved + Delete current page + Swap with previous + Swap with next + Page %1$s of %2$s + Export + Retrieving page + Exporting… + No pages were scanned yet. Click the scan button :) + Platen + ADF + Available scanners + Discovery + Copy current scan options in eSCLKt format + Scan settings + Not in allowed range + Not a valid number + Valid + Input source: + Used Resolution (dpi): + Duplex + Default + Width (in %1$s) + Height (in %1$s) + Maximum size + Custom + Job still running + Error while retrieving page: %1$s + Copy + Error + Scans unsaved + Do you really want to close the scanning interface? Any scans that you didn\'t export will be lost! + Cancel + Leave + App icon + Debug + Info button for the setting + Crash log file exists + A crash log was found. This is the exception which led to the crash. Please attach this to your bug report: + OK, delete it + Camera + Temporary files found + Temporary files (scans and/or exports) were found in the app storage. These are files which remain in the app storage if the app is closed from the overview or killed by Android while being in a scanning session. The main reason for this dialog is that asking for confirmation of deletion was impossible when the app was closed in this way.\n\nWhat do you want to do with the following scan and export files?:\n%1$s + Delete + Do nothing + Rotate right + Rotating… + Access custom scanner + Just connect + URL (eSCL resource) + Connect to a custom scanner + Invalid URL + Please enter an URL + Custom scanner + Export as PDF + Export as archive of JPEGs + No further pages. %1$s + Error while copying received image to file: %1$s + Couldn\'t decode received image. %1$s + Intent: + Scan Region: + Do you really want to delete the current page? This action can not be undone. + Debug log + This will write all available log data to an exportable file. This is useful for submitting bug repots. + Clear debug log + Export debug log + This timeout determines how long ScanBridge waits at maximum for the scanner to respond to requests until it aborts the scan job.\n\nThis is mostly useful for slow scanners and large scan areas which take longer to scan. + Response Timeout (in seconds) + Advanced Settings + + Name + HP Deskjet + Discovered scanners + Saved scanners + Max. pages per PDF file + As a smartphone has limited memory, it can becomes difficult to handle large PDFs. To prevent crashes, ScanBridge limits the maximum count pages stored in one PDF file when exporting scanned pages as PDF. If there are too much pages, multiple PDFs are created and stored into a ZIP archive. These PDFs can be merged afterwards, if needed.\n\nWarning: Increasing this too far can lead to crashes while exporting if a large number of pages are to be exported. + Disable certificate checks + This option disables all HTTPS certificate validation. Any certificate will be accepted, including self-signed, expired, or otherwise invalid ones. Do not use this option on insecure or public networks, as it makes man-in-the-middle (MitM) attacks possible.\n\nIn most cases, scanners are used on private networks or over VPN connections, where concerns about authenticity are minimal. In such environments, disabling certificate checks is unlikely to pose a real security risk. And in case confidentiality or authenticity is a concern, even HTTPS won\'t help much, as eSCL lacks client authentication altogether. Anyone with access to the network can potentially retrieve scanned pages. + Remember scan settings + When enabled, your last used scan settings (input source, duplex, etc.) will be restored when you create a new scan session.\n\nWhen disabled, each session starts with default scan settings (highest resolution, largest possible scan area). + Support development + View source code + F-Droid + Play Store + Save to File + Loading image… + Crop current page + Crop + Cropping page… + Activate zoom gestures + ScanBridge crashed :( + "We are sorry. ScanBridge has crashed. Please report this issue and attach the following stacktrace (you can copy it with the button at the bottom)" + Loading previous session failed… %1$s + The scanner capabilities should be retrieved at this point, but they weren\'t. + mm + Inches + Scanned pages are received in the background. + If you need help or want to provide feedback, contact us anytime at support@fireamp.eu. We will get back to you as quickly as possible! + Thank you for purchasing ScanBridge! + Scan job running… + Color Mode: + + Color ({bitdepth} bit) + Automatic detection + Grayscale ({bitdepth} bit) + Save + Edit custom scanner + Do you really want to delete this custom scanner? This action cannot be undone. + Delete custom scanner + \ No newline at end of file diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Color.kt b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt similarity index 90% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Color.kt rename to sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt index 021f855..6209286 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Color.kt +++ b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt @@ -19,6 +19,7 @@ package io.github.chrisimx.scanbridge.theme +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color @@ -36,6 +37,6 @@ val Purple = Color(0xFF702CCC) val gradientBrush = Brush.linearGradient( colors = listOf(NiceBlue, Purple), // Colors of the gradient - start = androidx.compose.ui.geometry.Offset.Zero, // Start position - end = androidx.compose.ui.geometry.Offset.Infinite // End position + start = Offset.Zero, // Start position + end = Offset.Infinite // End position ) diff --git a/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt.ig similarity index 100% rename from shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt rename to sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt.ig diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Theme.kt b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt similarity index 75% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Theme.kt rename to sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt index bb7cafc..9b96bae 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/theme/Theme.kt +++ b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt @@ -19,23 +19,20 @@ package io.github.chrisimx.scanbridge.theme -import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.dynamicDarkColorScheme -import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalContext -private val DarkColorScheme = darkColorScheme( +val DarkColorScheme = darkColorScheme( primary = Purple80, secondary = PurpleGrey80, tertiary = Pink80 ) -private val LightColorScheme = lightColorScheme( +val LightColorScheme = lightColorScheme( primary = Purple40, secondary = PurpleGrey40, tertiary = Pink40 @@ -51,6 +48,13 @@ private val LightColorScheme = lightColorScheme( */ ) +@Composable +expect fun platformDarkColorScheme(): ColorScheme? + +@Composable +expect fun platformLightColorScheme(): ColorScheme? + + @Composable fun ScanBridgeTheme( darkTheme: Boolean = isSystemInDarkTheme(), @@ -59,19 +63,13 @@ fun ScanBridgeTheme( content: @Composable () -> Unit ) { val colorScheme = when { - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { - val context = LocalContext.current - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - } - - darkTheme -> DarkColorScheme - - else -> LightColorScheme + darkTheme -> platformDarkColorScheme() ?: DarkColorScheme + else -> platformLightColorScheme() ?: LightColorScheme } MaterialTheme( colorScheme = colorScheme, - typography = Typography, + typography = PoppinsTypography(), content = content ) } diff --git a/shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt.ig similarity index 100% rename from shared/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt rename to sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt.ig diff --git a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt new file mode 100644 index 0000000..cd49f1c --- /dev/null +++ b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt @@ -0,0 +1,199 @@ +package io.github.chrisimx.scanbridge.theme + +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp +import org.jetbrains.compose.resources.Font +import scanbridge.sharedui.generated.resources.Res +import androidx.compose.material3.Typography +import androidx.compose.ui.text.font.FontStyle +import scanbridge.sharedui.generated.resources.* + +@Composable +fun Poppins(): FontFamily = FontFamily( + Font(Res.font.poppins_thin, weight = FontWeight.Thin), + Font(Res.font.poppins_thinitalic, weight = FontWeight.Thin, style = FontStyle.Italic), + + Font(Res.font.poppins_extralight, weight = FontWeight.ExtraLight), + Font(Res.font.poppins_extralightitalic, weight = FontWeight.ExtraLight, style = FontStyle.Italic), + + Font(Res.font.poppins_light, weight = FontWeight.Light), + Font(Res.font.poppins_lightitalic, weight = FontWeight.Light, style = FontStyle.Italic), + + Font(Res.font.poppins_regular, weight = FontWeight.Normal), + Font(Res.font.poppins_italic, weight = FontWeight.Normal, style = FontStyle.Italic), + + Font(Res.font.poppins_medium, weight = FontWeight.Medium), + Font(Res.font.poppins_mediumitalic, weight = FontWeight.Medium, style = FontStyle.Italic), + + Font(Res.font.poppins_semibold, weight = FontWeight.SemiBold), + Font(Res.font.poppins_semibolditalic, weight = FontWeight.SemiBold, style = FontStyle.Italic), + + Font(Res.font.poppins_bold, weight = FontWeight.Bold), + Font(Res.font.poppins_bolditalic, weight = FontWeight.Bold, style = FontStyle.Italic), + + Font(Res.font.poppins_extrabold, weight = FontWeight.ExtraBold), + Font(Res.font.poppins_extrabolditalic, weight = FontWeight.ExtraBold, style = FontStyle.Italic), + + Font(Res.font.poppins_black, weight = FontWeight.Black), + Font(Res.font.poppins_blackitalic, weight = FontWeight.Black, style = FontStyle.Italic) + ) + +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun PoppinsTypography(): Typography { + val poppinsFont = Poppins() + + return Typography( + titleSmall = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 20.sp, + letterSpacing = 0.sp + ), + titleMedium = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + fontSize = 18.sp, + lineHeight = 24.sp, + letterSpacing = 0.sp + ), + titleMediumEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp, + lineHeight = 24.sp, + letterSpacing = 0.sp + ), + titleLarge = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + titleLargeEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + lineHeight = 14.sp, + fontSize = 11.sp, + letterSpacing = 0.sp + ), + labelMedium = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + lineHeight = 14.sp, + fontSize = 14.sp, + letterSpacing = 0.sp + ), + labelLarge = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + letterSpacing = 0.sp + ), + bodySmall = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + letterSpacing = 0.sp + ), + bodySmallEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + letterSpacing = 0.sp + ), + bodyMedium = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + letterSpacing = 0.sp + ), + bodyMediumEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + letterSpacing = 0.sp + ), + bodyLarge = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ), + bodyLargeEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ), + displaySmall = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + letterSpacing = 0.sp + ), + displayMedium = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + letterSpacing = 0.sp + ), + displayLarge = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + letterSpacing = 0.sp + ), + displaySmallEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + letterSpacing = 0.sp + ), + displayMediumEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + letterSpacing = 0.sp + ), + displayLargeEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + letterSpacing = 0.sp + ), + headlineLarge = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + fontSize = 24.sp, + lineHeight = 32.sp, + letterSpacing = 0.sp + ), + headlineMedium = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + fontSize = 20.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + headlineMediumEmphasized = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.ExtraBold, + fontSize = 20.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + headlineSmall = TextStyle( + fontFamily = poppinsFont, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.sp + ) + ) + +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt similarity index 78% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt rename to sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt index 92d16a1..04e10f6 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt +++ b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt @@ -22,24 +22,30 @@ package io.github.chrisimx.scanbridge.uicomponents import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import org.jetbrains.compose.resources.StringResource import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text -import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import io.github.chrisimx.scanbridge.theme.ScanBridgeTheme +import org.jetbrains.compose.resources.stringResource +import scanbridge.sharedui.generated.resources.Res +import scanbridge.sharedui.generated.resources.trying_to_retrieve_scannercapabilities @Composable -fun LoadingScreen(loadingText: Int) { +fun LoadingScreen(loadingText: StringResource) { Column( modifier = Modifier .fillMaxSize() @@ -60,3 +66,13 @@ fun LoadingScreen(loadingText: Int) { ) } } + +@Composable +@Preview +fun LoadingScreenPreview() { + ScanBridgeTheme { + Scaffold { + LoadingScreen(Res.string.trying_to_retrieve_scannercapabilities) + } + } +} From 57aef80c99ee7677981ed84ecbce8553a47753a0 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Fri, 3 Apr 2026 23:00:59 +0200 Subject: [PATCH 04/26] Remove old theme files from skeleton --- .../chrisimx/scanbridge/theme/Color.kt.ig | 80 ------------- .../chrisimx/scanbridge/theme/Theme.kt.ig | 105 ------------------ 2 files changed, 185 deletions(-) delete mode 100644 sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt.ig delete mode 100644 sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt.ig diff --git a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt.ig b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt.ig deleted file mode 100644 index 7c5ad72..0000000 --- a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt.ig +++ /dev/null @@ -1,80 +0,0 @@ -package io.github.chrisimx.scanbridge.theme - -import androidx.compose.ui.graphics.Color - -//generated by https://materialkolor.com -//Color palette was taken here: https://coolors.co/palette/e63946-f1faee-a8dadc-457b9d-1d3557 - -internal val Seed = Color(0xFF1D3557) - -internal val PrimaryLight = Color(0xFF485F84) -internal val OnPrimaryLight = Color(0xFFFFFFFF) -internal val PrimaryContainerLight = Color(0xFFD5E3FF) -internal val OnPrimaryContainerLight = Color(0xFF30476A) -internal val SecondaryLight = Color(0xFF2B6485) -internal val OnSecondaryLight = Color(0xFFFFFFFF) -internal val SecondaryContainerLight = Color(0xFFC7E7FF) -internal val OnSecondaryContainerLight = Color(0xFF064C6B) -internal val TertiaryLight = Color(0xFF356668) -internal val OnTertiaryLight = Color(0xFFFFFFFF) -internal val TertiaryContainerLight = Color(0xFFB9ECEE) -internal val OnTertiaryContainerLight = Color(0xFF1A4E50) -internal val ErrorLight = Color(0xFFBB152C) -internal val OnErrorLight = Color(0xFFFFFFFF) -internal val ErrorContainerLight = Color(0xFFFFDAD8) -internal val OnErrorContainerLight = Color(0xFF410007) -internal val BackgroundLight = Color(0xFFF9F9F9) -internal val OnBackgroundLight = Color(0xFF1A1C1C) -internal val SurfaceLight = Color(0xFFF9F9F9) -internal val OnSurfaceLight = Color(0xFF1A1C1C) -internal val SurfaceVariantLight = Color(0xFFDCE5D9) -internal val OnSurfaceVariantLight = Color(0xFF404941) -internal val OutlineLight = Color(0xFF717970) -internal val OutlineVariantLight = Color(0xFFC0C9BE) -internal val ScrimLight = Color(0xFF000000) -internal val InverseSurfaceLight = Color(0xFF2F3131) -internal val InverseOnSurfaceLight = Color(0xFFF0F1F1) -internal val InversePrimaryLight = Color(0xFFB0C7F1) -internal val SurfaceDimLight = Color(0xFFDADADA) -internal val SurfaceBrightLight = Color(0xFFF9F9F9) -internal val SurfaceContainerLowestLight = Color(0xFFFFFFFF) -internal val SurfaceContainerLowLight = Color(0xFFF3F3F4) -internal val SurfaceContainerLight = Color(0xFFEEEEEE) -internal val SurfaceContainerHighLight = Color(0xFFE8E8E8) -internal val SurfaceContainerHighestLight = Color(0xFFE2E2E2) - -internal val PrimaryDark = Color(0xFFB0C7F1) -internal val OnPrimaryDark = Color(0xFF183153) -internal val PrimaryContainerDark = Color(0xFF30476A) -internal val OnPrimaryContainerDark = Color(0xFFD5E3FF) -internal val SecondaryDark = Color(0xFF98CDF2) -internal val OnSecondaryDark = Color(0xFF00344C) -internal val SecondaryContainerDark = Color(0xFF064C6B) -internal val OnSecondaryContainerDark = Color(0xFFC7E7FF) -internal val TertiaryDark = Color(0xFF9ECFD1) -internal val OnTertiaryDark = Color(0xFF003739) -internal val TertiaryContainerDark = Color(0xFF1A4E50) -internal val OnTertiaryContainerDark = Color(0xFFB9ECEE) -internal val ErrorDark = Color(0xFFFFB3B1) -internal val OnErrorDark = Color(0xFF680011) -internal val ErrorContainerDark = Color(0xFF92001C) -internal val OnErrorContainerDark = Color(0xFFFFDAD8) -internal val BackgroundDark = Color(0xFF121414) -internal val OnBackgroundDark = Color(0xFFE2E2E2) -internal val SurfaceDark = Color(0xFF121414) -internal val OnSurfaceDark = Color(0xFFE2E2E2) -internal val SurfaceVariantDark = Color(0xFF404941) -internal val OnSurfaceVariantDark = Color(0xFFC0C9BE) -internal val OutlineDark = Color(0xFF8A9389) -internal val OutlineVariantDark = Color(0xFF404941) -internal val ScrimDark = Color(0xFF000000) -internal val InverseSurfaceDark = Color(0xFFE2E2E2) -internal val InverseOnSurfaceDark = Color(0xFF2F3131) -internal val InversePrimaryDark = Color(0xFF485F84) -internal val SurfaceDimDark = Color(0xFF121414) -internal val SurfaceBrightDark = Color(0xFF37393A) -internal val SurfaceContainerLowestDark = Color(0xFF0C0F0F) -internal val SurfaceContainerLowDark = Color(0xFF1A1C1C) -internal val SurfaceContainerDark = Color(0xFF1E2020) -internal val SurfaceContainerHighDark = Color(0xFF282A2B) -internal val SurfaceContainerHighestDark = Color(0xFF333535) diff --git a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt.ig b/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt.ig deleted file mode 100644 index 9de99dc..0000000 --- a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt.ig +++ /dev/null @@ -1,105 +0,0 @@ -package io.github.chrisimx.scanbridge.theme - -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme -import androidx.compose.runtime.* - -private val LightColorScheme = lightColorScheme( - primary = PrimaryLight, - onPrimary = OnPrimaryLight, - primaryContainer = PrimaryContainerLight, - onPrimaryContainer = OnPrimaryContainerLight, - secondary = SecondaryLight, - onSecondary = OnSecondaryLight, - secondaryContainer = SecondaryContainerLight, - onSecondaryContainer = OnSecondaryContainerLight, - tertiary = TertiaryLight, - onTertiary = OnTertiaryLight, - tertiaryContainer = TertiaryContainerLight, - onTertiaryContainer = OnTertiaryContainerLight, - error = ErrorLight, - onError = OnErrorLight, - errorContainer = ErrorContainerLight, - onErrorContainer = OnErrorContainerLight, - background = BackgroundLight, - onBackground = OnBackgroundLight, - surface = SurfaceLight, - onSurface = OnSurfaceLight, - surfaceVariant = SurfaceVariantLight, - onSurfaceVariant = OnSurfaceVariantLight, - outline = OutlineLight, - outlineVariant = OutlineVariantLight, - scrim = ScrimLight, - inverseSurface = InverseSurfaceLight, - inverseOnSurface = InverseOnSurfaceLight, - inversePrimary = InversePrimaryLight, - surfaceDim = SurfaceDimLight, - surfaceBright = SurfaceBrightLight, - surfaceContainerLowest = SurfaceContainerLowestLight, - surfaceContainerLow = SurfaceContainerLowLight, - surfaceContainer = SurfaceContainerLight, - surfaceContainerHigh = SurfaceContainerHighLight, - surfaceContainerHighest = SurfaceContainerHighestLight, -) - -private val DarkColorScheme = darkColorScheme( - primary = PrimaryDark, - onPrimary = OnPrimaryDark, - primaryContainer = PrimaryContainerDark, - onPrimaryContainer = OnPrimaryContainerDark, - secondary = SecondaryDark, - onSecondary = OnSecondaryDark, - secondaryContainer = SecondaryContainerDark, - onSecondaryContainer = OnSecondaryContainerDark, - tertiary = TertiaryDark, - onTertiary = OnTertiaryDark, - tertiaryContainer = TertiaryContainerDark, - onTertiaryContainer = OnTertiaryContainerDark, - error = ErrorDark, - onError = OnErrorDark, - errorContainer = ErrorContainerDark, - onErrorContainer = OnErrorContainerDark, - background = BackgroundDark, - onBackground = OnBackgroundDark, - surface = SurfaceDark, - onSurface = OnSurfaceDark, - surfaceVariant = SurfaceVariantDark, - onSurfaceVariant = OnSurfaceVariantDark, - outline = OutlineDark, - outlineVariant = OutlineVariantDark, - scrim = ScrimDark, - inverseSurface = InverseSurfaceDark, - inverseOnSurface = InverseOnSurfaceDark, - inversePrimary = InversePrimaryDark, - surfaceDim = SurfaceDimDark, - surfaceBright = SurfaceBrightDark, - surfaceContainerLowest = SurfaceContainerLowestDark, - surfaceContainerLow = SurfaceContainerLowDark, - surfaceContainer = SurfaceContainerDark, - surfaceContainerHigh = SurfaceContainerHighDark, - surfaceContainerHighest = SurfaceContainerHighestDark, -) - -internal val LocalThemeIsDark = compositionLocalOf { mutableStateOf(true) } - -@Composable -internal fun AppTheme( - onThemeChanged: @Composable (isDark: Boolean) -> Unit, - content: @Composable () -> Unit -) { - val systemIsDark = isSystemInDarkTheme() - val isDarkState = remember(systemIsDark) { mutableStateOf(systemIsDark) } - CompositionLocalProvider( - LocalThemeIsDark provides isDarkState - ) { - val isDark by isDarkState - onThemeChanged(!isDark) - MaterialTheme( - colorScheme = if (isDark) DarkColorScheme else LightColorScheme, - content = { Surface(content = content) } - ) - } -} From aae6b3ac17db459bf61c8354654905dd96010bf7 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Fri, 3 Apr 2026 23:17:35 +0200 Subject: [PATCH 05/26] Move theme to composeUI module --- androidApp/build.gradle.kts | 2 +- .../io/github/chrisimx/scanbridge/ScanBridgeApp.kt | 2 -- .../io/github/chrisimx/scanbridge/ScanningScreen.kt | 4 ++-- {sharedUI => composeUI}/.gitignore | 0 {sharedUI => composeUI}/build.gradle.kts | 0 .../chrisimx/scanbridge/theme/Theme.android.kt | 0 .../github/chrisimx/scanbridge/theme/Theme.apple.kt | 1 + .../composeResources/drawable/ic_cyclone.xml | 0 .../composeResources/drawable/ic_dark_mode.xml | 0 .../composeResources/drawable/ic_light_mode.xml | 0 .../composeResources/drawable/ic_rotate_right.xml | 0 .../composeResources/font/poppins_black.ttf | Bin .../composeResources/font/poppins_blackitalic.ttf | Bin .../composeResources/font/poppins_bold.ttf | Bin .../composeResources/font/poppins_bolditalic.ttf | Bin .../composeResources/font/poppins_extrabold.ttf | Bin .../font/poppins_extrabolditalic.ttf | Bin .../composeResources/font/poppins_extralight.ttf | Bin .../font/poppins_extralightitalic.ttf | Bin .../composeResources/font/poppins_italic.ttf | Bin .../composeResources/font/poppins_light.ttf | Bin .../composeResources/font/poppins_lightitalic.ttf | Bin .../composeResources/font/poppins_medium.ttf | Bin .../composeResources/font/poppins_mediumitalic.ttf | Bin .../composeResources/font/poppins_regular.ttf | Bin .../composeResources/font/poppins_semibold.ttf | Bin .../font/poppins_semibolditalic.ttf | Bin .../composeResources/font/poppins_thin.ttf | Bin .../composeResources/font/poppins_thinitalic.ttf | Bin .../composeResources/values-de/strings.xml | 0 .../composeResources/values-it/strings.xml | 0 .../commonMain/composeResources/values/strings.xml | 0 .../io/github/chrisimx/scanbridge/theme/Color.kt | 0 .../io/github/chrisimx/scanbridge/theme/Theme.kt | 0 .../github/chrisimx/scanbridge/theme/Typography.kt | 0 .../scanbridge/uicomponents/LoadingScreen.kt | 4 ++-- desktopApp/build.gradle.kts | 2 +- settings.gradle.kts | 2 +- 38 files changed, 8 insertions(+), 9 deletions(-) rename {sharedUI => composeUI}/.gitignore (100%) rename {sharedUI => composeUI}/build.gradle.kts (100%) rename {sharedUI => composeUI}/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt (100%) rename {sharedUI => composeUI}/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt (81%) rename {sharedUI => composeUI}/src/commonMain/composeResources/drawable/ic_cyclone.xml (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/drawable/ic_dark_mode.xml (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/drawable/ic_light_mode.xml (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/drawable/ic_rotate_right.xml (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_black.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_blackitalic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_bold.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_bolditalic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_extrabold.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_extrabolditalic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_extralight.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_extralightitalic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_italic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_light.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_lightitalic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_medium.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_mediumitalic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_regular.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_semibold.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_semibolditalic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_thin.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/font/poppins_thinitalic.ttf (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/values-de/strings.xml (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/values-it/strings.xml (100%) rename {sharedUI => composeUI}/src/commonMain/composeResources/values/strings.xml (100%) rename {sharedUI => composeUI}/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt (100%) rename {sharedUI => composeUI}/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt (100%) rename {sharedUI => composeUI}/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt (100%) rename {sharedUI => composeUI}/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt (95%) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index cfabc5f..2e702d9 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -111,7 +111,7 @@ dependencies { implementation(libs.androidx.navigation.compose) implementation(libs.kotlinx.serialization.json) implementation(project(":core")) - implementation(project(":sharedUI")) + implementation(project(":composeUI")) implementation("androidx.concurrent:concurrent-futures:1.2.0") ksp(libs.androidx.room.compiler) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt index 01c5ee7..adb7c80 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt @@ -23,7 +23,6 @@ import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Favorite import androidx.compose.material3.AlertDialog -// TODO: import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -58,7 +57,6 @@ import kotlinx.coroutines.withContext import kotlinx.serialization.json.Json import timber.log.Timber -// TODO: @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun ScanBridgeApp() { ScanBridgeTheme { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt index e5a4937..d332932 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanningScreen.kt @@ -115,8 +115,8 @@ import me.saket.telephoto.zoomable.rememberZoomableState import me.saket.telephoto.zoomable.zoomable import org.koin.androidx.compose.koinViewModel import org.koin.core.parameter.parametersOf -import scanbridge.sharedui.generated.resources.Res -import scanbridge.sharedui.generated.resources.trying_to_retrieve_scannercapabilities +import scanbridge.composeui.generated.resources.Res +import scanbridge.composeui.generated.resources.trying_to_retrieve_scannercapabilities import timber.log.Timber private const val TAG = "ScanningScreen" diff --git a/sharedUI/.gitignore b/composeUI/.gitignore similarity index 100% rename from sharedUI/.gitignore rename to composeUI/.gitignore diff --git a/sharedUI/build.gradle.kts b/composeUI/build.gradle.kts similarity index 100% rename from sharedUI/build.gradle.kts rename to composeUI/build.gradle.kts diff --git a/sharedUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt b/composeUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt similarity index 100% rename from sharedUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt rename to composeUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt diff --git a/sharedUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt b/composeUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt similarity index 81% rename from sharedUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt rename to composeUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt index 4ac11d5..5276020 100644 --- a/sharedUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt +++ b/composeUI/src/appleMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.apple.kt @@ -1,6 +1,7 @@ package io.github.chrisimx.scanbridge.theme import androidx.compose.material3.ColorScheme +import androidx.compose.runtime.Composable @Composable actual fun platformDarkColorScheme(): ColorScheme? { diff --git a/sharedUI/src/commonMain/composeResources/drawable/ic_cyclone.xml b/composeUI/src/commonMain/composeResources/drawable/ic_cyclone.xml similarity index 100% rename from sharedUI/src/commonMain/composeResources/drawable/ic_cyclone.xml rename to composeUI/src/commonMain/composeResources/drawable/ic_cyclone.xml diff --git a/sharedUI/src/commonMain/composeResources/drawable/ic_dark_mode.xml b/composeUI/src/commonMain/composeResources/drawable/ic_dark_mode.xml similarity index 100% rename from sharedUI/src/commonMain/composeResources/drawable/ic_dark_mode.xml rename to composeUI/src/commonMain/composeResources/drawable/ic_dark_mode.xml diff --git a/sharedUI/src/commonMain/composeResources/drawable/ic_light_mode.xml b/composeUI/src/commonMain/composeResources/drawable/ic_light_mode.xml similarity index 100% rename from sharedUI/src/commonMain/composeResources/drawable/ic_light_mode.xml rename to composeUI/src/commonMain/composeResources/drawable/ic_light_mode.xml diff --git a/sharedUI/src/commonMain/composeResources/drawable/ic_rotate_right.xml b/composeUI/src/commonMain/composeResources/drawable/ic_rotate_right.xml similarity index 100% rename from sharedUI/src/commonMain/composeResources/drawable/ic_rotate_right.xml rename to composeUI/src/commonMain/composeResources/drawable/ic_rotate_right.xml diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_black.ttf b/composeUI/src/commonMain/composeResources/font/poppins_black.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_black.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_black.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_blackitalic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_blackitalic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_blackitalic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_blackitalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_bold.ttf b/composeUI/src/commonMain/composeResources/font/poppins_bold.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_bold.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_bold.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_bolditalic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_bolditalic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_bolditalic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_bolditalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_extrabold.ttf b/composeUI/src/commonMain/composeResources/font/poppins_extrabold.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_extrabold.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_extrabold.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_extrabolditalic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_extrabolditalic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_extrabolditalic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_extrabolditalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_extralight.ttf b/composeUI/src/commonMain/composeResources/font/poppins_extralight.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_extralight.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_extralight.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_extralightitalic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_extralightitalic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_extralightitalic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_extralightitalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_italic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_italic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_italic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_italic.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_light.ttf b/composeUI/src/commonMain/composeResources/font/poppins_light.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_light.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_light.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_lightitalic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_lightitalic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_lightitalic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_lightitalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_medium.ttf b/composeUI/src/commonMain/composeResources/font/poppins_medium.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_medium.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_medium.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_mediumitalic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_mediumitalic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_mediumitalic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_mediumitalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_regular.ttf b/composeUI/src/commonMain/composeResources/font/poppins_regular.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_regular.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_regular.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_semibold.ttf b/composeUI/src/commonMain/composeResources/font/poppins_semibold.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_semibold.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_semibold.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_semibolditalic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_semibolditalic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_semibolditalic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_semibolditalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_thin.ttf b/composeUI/src/commonMain/composeResources/font/poppins_thin.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_thin.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_thin.ttf diff --git a/sharedUI/src/commonMain/composeResources/font/poppins_thinitalic.ttf b/composeUI/src/commonMain/composeResources/font/poppins_thinitalic.ttf similarity index 100% rename from sharedUI/src/commonMain/composeResources/font/poppins_thinitalic.ttf rename to composeUI/src/commonMain/composeResources/font/poppins_thinitalic.ttf diff --git a/sharedUI/src/commonMain/composeResources/values-de/strings.xml b/composeUI/src/commonMain/composeResources/values-de/strings.xml similarity index 100% rename from sharedUI/src/commonMain/composeResources/values-de/strings.xml rename to composeUI/src/commonMain/composeResources/values-de/strings.xml diff --git a/sharedUI/src/commonMain/composeResources/values-it/strings.xml b/composeUI/src/commonMain/composeResources/values-it/strings.xml similarity index 100% rename from sharedUI/src/commonMain/composeResources/values-it/strings.xml rename to composeUI/src/commonMain/composeResources/values-it/strings.xml diff --git a/sharedUI/src/commonMain/composeResources/values/strings.xml b/composeUI/src/commonMain/composeResources/values/strings.xml similarity index 100% rename from sharedUI/src/commonMain/composeResources/values/strings.xml rename to composeUI/src/commonMain/composeResources/values/strings.xml diff --git a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt similarity index 100% rename from sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt rename to composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Color.kt diff --git a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt similarity index 100% rename from sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt rename to composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt diff --git a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt similarity index 100% rename from sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt rename to composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt diff --git a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt similarity index 95% rename from sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt rename to composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt index 04e10f6..55f7449 100644 --- a/sharedUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt +++ b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt @@ -41,8 +41,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.github.chrisimx.scanbridge.theme.ScanBridgeTheme import org.jetbrains.compose.resources.stringResource -import scanbridge.sharedui.generated.resources.Res -import scanbridge.sharedui.generated.resources.trying_to_retrieve_scannercapabilities +import scanbridge.composeui.generated.resources.Res +import scanbridge.composeui.generated.resources.trying_to_retrieve_scannercapabilities @Composable fun LoadingScreen(loadingText: StringResource) { diff --git a/desktopApp/build.gradle.kts b/desktopApp/build.gradle.kts index 3733006..52c5104 100644 --- a/desktopApp/build.gradle.kts +++ b/desktopApp/build.gradle.kts @@ -6,7 +6,7 @@ plugins { alias(libs.plugins.kotlin.jvm) } dependencies { - implementation(project(":sharedUI")) + implementation(project(":composeUI")) } compose.desktop { diff --git a/settings.gradle.kts b/settings.gradle.kts index d0308ec..8129694 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -32,7 +32,7 @@ dependencyResolutionManagement { } } -include(":sharedUI") +include(":composeUI") include(":core") include(":androidApp") include(":desktopApp") From 745faf0633ae2611b9af3766a5cc81df92d978d1 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Mon, 6 Apr 2026 12:28:21 +0200 Subject: [PATCH 06/26] Fix import in Typography.kt --- .../kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt index cd49f1c..6ce5898 100644 --- a/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt +++ b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt @@ -7,10 +7,10 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp import org.jetbrains.compose.resources.Font -import scanbridge.sharedui.generated.resources.Res +import scanbridge.composeui.generated.resources.Res import androidx.compose.material3.Typography import androidx.compose.ui.text.font.FontStyle -import scanbridge.sharedui.generated.resources.* +import scanbridge.composeui.generated.resources.* @Composable fun Poppins(): FontFamily = FontFamily( From 09ca8ff06c992611b7fcbe0b57a69a27c360f473 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Sun, 5 Apr 2026 00:03:30 +0200 Subject: [PATCH 07/26] Migrate last route store to Room and abstract to repository, shown message store: abstract to repository --- androidApp/build.gradle.kts | 6 +- .../3.json | 238 ++++++++++++++++ .../4.json | 256 ++++++++++++++++++ .../chrisimx/scanbridge/CrashHandler.kt | 10 +- .../chrisimx/scanbridge/MainActivity.kt | 4 +- .../chrisimx/scanbridge/ScanBridgeApp.kt | 47 ++-- .../scanbridge/ScanBridgeApplication.kt | 75 +++-- .../chrisimx/scanbridge/db/ScanBridgeDb.kt | 18 +- .../db/daos/ExecutedMigrationsDao.kt | 18 ++ .../scanbridge/db/daos/LastRouteDao.kt | 19 ++ .../db/entities/ExecutedMigrationToRoom.kt | 10 + .../scanbridge/db/entities/LastRoute.kt | 10 + .../scanbridge/migrations/Migration.kt | 16 ++ .../migrations/MigrationExecutor.kt | 5 + .../migrations/MigrationRegistry.kt | 17 ++ .../migrations/RoomBackedMigrationExecutor.kt | 36 +++ .../DatastoreLastRouteRepository.kt | 32 +++ .../DatastoreShownMessagesRepository.kt | 42 +++ .../repositories/RoomLastRouteRepository.kt | 30 ++ .../services/FileDebugLogService.kt | 2 +- composeUI/build.gradle.kts | 8 +- .../chrisimx/scanbridge/theme/Theme.jvm.kt | 10 + core/build.gradle.kts | 11 +- .../scanbridge/KmLogScanBridgeLogger.kt | 49 ++++ .../scanbridge/LastRouteRepository.kt | 6 + .../chrisimx/scanbridge/ScanBridgeLogger.kt | 21 ++ .../scanbridge/ShownMessagesRepository.kt | 12 + gradle/libs.versions.toml | 2 + 28 files changed, 936 insertions(+), 74 deletions(-) create mode 100644 androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json create mode 100644 androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/Migration.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationExecutor.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreLastRouteRepository.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreShownMessagesRepository.kt create mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/RoomLastRouteRepository.kt create mode 100644 composeUI/src/jvmMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.jvm.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/KmLogScanBridgeLogger.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LastRouteRepository.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanBridgeLogger.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ShownMessagesRepository.kt diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 2e702d9..18b0614 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -80,8 +80,8 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } buildFeatures { compose = true @@ -91,7 +91,7 @@ android { kotlin { compilerOptions { - jvmTarget = JvmTarget.JVM_11 + jvmTarget = JvmTarget.JVM_17 optIn.add("kotlin.uuid.ExperimentalUuidApi") } } diff --git a/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json b/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json new file mode 100644 index 0000000..86a6e51 --- /dev/null +++ b/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json @@ -0,0 +1,238 @@ +{ + "formatVersion": 1, + "database": { + "version": 3, + "identityHash": "07cfa3c6a4549c1d0782b1afbe48d17e", + "entities": [ + { + "tableName": "customscanners", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, PRIMARY KEY(`uuid`))", + "fields": [ + { + "fieldPath": "uuid", + "columnName": "uuid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "uuid" + ] + } + }, + { + "tableName": "scannedpages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scanId` TEXT NOT NULL, `ownerSessionId` TEXT NOT NULL, `filePath` TEXT NOT NULL, `originalScanSettings` TEXT NOT NULL, `rotation` TEXT NOT NULL, `orderIndex` INTEGER NOT NULL, PRIMARY KEY(`scanId`), FOREIGN KEY(`ownerSessionId`) REFERENCES `sessions`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "scanId", + "columnName": "scanId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "ownerSessionId", + "columnName": "ownerSessionId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filePath", + "columnName": "filePath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "originalScanSettings", + "columnName": "originalScanSettings", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "rotation", + "columnName": "rotation", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "orderIndex", + "columnName": "orderIndex", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "scanId" + ] + }, + "indices": [ + { + "name": "index_scannedpages_ownerSessionId", + "unique": false, + "columnNames": [ + "ownerSessionId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_scannedpages_ownerSessionId` ON `${TABLE_NAME}` (`ownerSessionId`)" + }, + { + "name": "index_scannedpages_ownerSessionId_orderIndex", + "unique": true, + "columnNames": [ + "ownerSessionId", + "orderIndex" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_scannedpages_ownerSessionId_orderIndex` ON `${TABLE_NAME}` (`ownerSessionId`, `orderIndex`)" + } + ], + "foreignKeys": [ + { + "table": "sessions", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "ownerSessionId" + ], + "referencedColumns": [ + "sessionId" + ] + } + ] + }, + { + "tableName": "sessions", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `currentScanSettings` TEXT, `currentSettingsUIData` TEXT DEFAULT null, `currentPage` INTEGER NOT NULL, PRIMARY KEY(`sessionId`))", + "fields": [ + { + "fieldPath": "sessionId", + "columnName": "sessionId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currentScanSettings", + "columnName": "currentScanSettings", + "affinity": "TEXT" + }, + { + "fieldPath": "currentSettingsUIData", + "columnName": "currentSettingsUIData", + "affinity": "TEXT", + "defaultValue": "null" + }, + { + "fieldPath": "currentPage", + "columnName": "currentPage", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "sessionId" + ] + } + }, + { + "tableName": "tempfiles", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tempFileId` TEXT NOT NULL, `ownerSessionId` TEXT NOT NULL, `path` TEXT NOT NULL, PRIMARY KEY(`tempFileId`), FOREIGN KEY(`ownerSessionId`) REFERENCES `sessions`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "tempFileId", + "columnName": "tempFileId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "ownerSessionId", + "columnName": "ownerSessionId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "path", + "columnName": "path", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "tempFileId" + ] + }, + "indices": [ + { + "name": "index_tempfiles_ownerSessionId", + "unique": false, + "columnNames": [ + "ownerSessionId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_tempfiles_ownerSessionId` ON `${TABLE_NAME}` (`ownerSessionId`)" + } + ], + "foreignKeys": [ + { + "table": "sessions", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "ownerSessionId" + ], + "referencedColumns": [ + "sessionId" + ] + } + ] + }, + { + "tableName": "lastroute", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`route` TEXT NOT NULL, `id` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "route", + "columnName": "route", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '07cfa3c6a4549c1d0782b1afbe48d17e')" + ] + } +} \ No newline at end of file diff --git a/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json b/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json new file mode 100644 index 0000000..50c594c --- /dev/null +++ b/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json @@ -0,0 +1,256 @@ +{ + "formatVersion": 1, + "database": { + "version": 4, + "identityHash": "739608178e7b7634ce893a4594feea9a", + "entities": [ + { + "tableName": "customscanners", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, PRIMARY KEY(`uuid`))", + "fields": [ + { + "fieldPath": "uuid", + "columnName": "uuid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "uuid" + ] + } + }, + { + "tableName": "scannedpages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scanId` TEXT NOT NULL, `ownerSessionId` TEXT NOT NULL, `filePath` TEXT NOT NULL, `originalScanSettings` TEXT NOT NULL, `rotation` TEXT NOT NULL, `orderIndex` INTEGER NOT NULL, PRIMARY KEY(`scanId`), FOREIGN KEY(`ownerSessionId`) REFERENCES `sessions`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "scanId", + "columnName": "scanId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "ownerSessionId", + "columnName": "ownerSessionId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filePath", + "columnName": "filePath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "originalScanSettings", + "columnName": "originalScanSettings", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "rotation", + "columnName": "rotation", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "orderIndex", + "columnName": "orderIndex", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "scanId" + ] + }, + "indices": [ + { + "name": "index_scannedpages_ownerSessionId", + "unique": false, + "columnNames": [ + "ownerSessionId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_scannedpages_ownerSessionId` ON `${TABLE_NAME}` (`ownerSessionId`)" + }, + { + "name": "index_scannedpages_ownerSessionId_orderIndex", + "unique": true, + "columnNames": [ + "ownerSessionId", + "orderIndex" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_scannedpages_ownerSessionId_orderIndex` ON `${TABLE_NAME}` (`ownerSessionId`, `orderIndex`)" + } + ], + "foreignKeys": [ + { + "table": "sessions", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "ownerSessionId" + ], + "referencedColumns": [ + "sessionId" + ] + } + ] + }, + { + "tableName": "sessions", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `currentScanSettings` TEXT, `currentSettingsUIData` TEXT DEFAULT null, `currentPage` INTEGER NOT NULL, PRIMARY KEY(`sessionId`))", + "fields": [ + { + "fieldPath": "sessionId", + "columnName": "sessionId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currentScanSettings", + "columnName": "currentScanSettings", + "affinity": "TEXT" + }, + { + "fieldPath": "currentSettingsUIData", + "columnName": "currentSettingsUIData", + "affinity": "TEXT", + "defaultValue": "null" + }, + { + "fieldPath": "currentPage", + "columnName": "currentPage", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "sessionId" + ] + } + }, + { + "tableName": "tempfiles", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tempFileId` TEXT NOT NULL, `ownerSessionId` TEXT NOT NULL, `path` TEXT NOT NULL, PRIMARY KEY(`tempFileId`), FOREIGN KEY(`ownerSessionId`) REFERENCES `sessions`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "tempFileId", + "columnName": "tempFileId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "ownerSessionId", + "columnName": "ownerSessionId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "path", + "columnName": "path", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "tempFileId" + ] + }, + "indices": [ + { + "name": "index_tempfiles_ownerSessionId", + "unique": false, + "columnNames": [ + "ownerSessionId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_tempfiles_ownerSessionId` ON `${TABLE_NAME}` (`ownerSessionId`)" + } + ], + "foreignKeys": [ + { + "table": "sessions", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "ownerSessionId" + ], + "referencedColumns": [ + "sessionId" + ] + } + ] + }, + { + "tableName": "lastroute", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`route` TEXT NOT NULL, `id` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "route", + "columnName": "route", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "executedmigrationtoroom", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`migrationId` TEXT NOT NULL, PRIMARY KEY(`migrationId`))", + "fields": [ + { + "fieldPath": "migrationId", + "columnName": "migrationId", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "migrationId" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '739608178e7b7634ce893a4594feea9a')" + ] + } +} \ No newline at end of file diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt index 8d0eae9..76f02af 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashHandler.kt @@ -21,15 +21,13 @@ package io.github.chrisimx.scanbridge import android.content.Context import android.content.Intent -import io.github.chrisimx.scanbridge.datastore.lastRouteStore -import io.github.chrisimx.scanbridge.proto.copy import java.io.File import java.time.LocalDateTime import java.time.format.DateTimeFormatter import kotlinx.coroutines.runBlocking import timber.log.Timber -class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler { +class CrashHandler(val context: Context, val lastRouteRepository: LastRouteRepository) : Thread.UncaughtExceptionHandler { private val defaultHandler = Thread.getDefaultUncaughtExceptionHandler() @@ -71,10 +69,6 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler { } suspend fun deleteStoredRoute() { - context.lastRouteStore.updateData { - it.copy { - clearLastRoute() - } - } + lastRouteRepository.setLastRoute(null) } } diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt index decde6d..53ebbae 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/MainActivity.kt @@ -31,6 +31,7 @@ import java.io.File import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.koin.android.ext.android.get import org.koin.android.ext.android.inject import org.koin.android.scope.AndroidScopeComponent import org.koin.androidx.scope.activityScope @@ -41,6 +42,7 @@ class MainActivity : ComponentActivity(), AndroidScopeComponent { private val localeProvider: AndroidLocaleProvider by inject() + private val crashHandler: Thread.UncaughtExceptionHandler by inject() override val scope: Scope by activityScope() @@ -52,7 +54,7 @@ class MainActivity : } override fun onCreate(savedInstanceState: Bundle?) { - Thread.setDefaultUncaughtExceptionHandler(CrashHandler(this.applicationContext)) + Thread.setDefaultUncaughtExceptionHandler(crashHandler) enableEdgeToEdge() super.onCreate(savedInstanceState) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt index adb7c80..c32b116 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApp.kt @@ -42,19 +42,12 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import com.google.protobuf.StringValue -import io.github.chrisimx.scanbridge.datastore.lastRouteStore -import io.github.chrisimx.scanbridge.datastore.shownMessagesStore -import io.github.chrisimx.scanbridge.proto.copy -import io.github.chrisimx.scanbridge.proto.lastRouteOrNull import io.github.chrisimx.scanbridge.theme.ScanBridgeTheme import io.github.chrisimx.scanbridge.uicomponents.CrashFileHandler -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.firstOrNull -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import kotlinx.serialization.json.Json +import org.koin.compose.koinInject +import org.koin.core.parameter.parametersOf import timber.log.Timber @Composable @@ -63,13 +56,23 @@ fun ScanBridgeApp() { val navController = rememberNavController() var startDestination: Any? by remember { mutableStateOf(null) } val context = LocalContext.current + val coroutineScope = rememberCoroutineScope() val currentBackStackEntry by navController.currentBackStackEntryAsState() val typedRoute = currentBackStackEntry?.toTypedRoute() + val lastRouteRepository = koinInject() + val shownMessagesRepository = koinInject { + parametersOf(coroutineScope) + } + + val thanksForPurchaseAlreadyShown by shownMessagesRepository + .getWasShownFlow(UserInformationMessage.THANKS_FOR_PURCHASE) + .collectAsState(true) + LaunchedEffect(Unit) { Timber.d("Loading last route from shared preferences") - val lastRoute = context.lastRouteStore.data.firstOrNull()?.lastRouteOrNull?.value + val lastRoute = lastRouteRepository.getLastRoute() if (lastRoute != null) { try { Timber.d("Last route found: $lastRoute") @@ -92,35 +95,17 @@ fun ScanBridgeApp() { val json = Json.encodeToString(route) Timber.d("Route saved as: $json") - context.lastRouteStore.updateData { - it.copy { - lastRoute = StringValue.of(json) - } - } + lastRouteRepository.setLastRoute(json) } } - val playThankShouldBeShown by remember { - context.shownMessagesStore.data.map { - BuildConfig.FLAVOR == "play" && !it.thankPlayOne - } - }.collectAsState(false) - - val coroutineScope = rememberCoroutineScope() - val markThanksMessageAsRead = { coroutineScope.launch { - withContext(Dispatchers.IO) { - context.shownMessagesStore.updateData { - it.copy { - thankPlayOne = true - } - } - } + shownMessagesRepository.setShown(UserInformationMessage.THANKS_FOR_PURCHASE, true) } } - if (playThankShouldBeShown) { + if (!thanksForPurchaseAlreadyShown) { AlertDialog( { markThanksMessageAsRead() diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt index 0b05a2c..7d96d9a 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt @@ -8,8 +8,16 @@ import io.github.chrisimx.scanbridge.data.ui.CustomScannerViewModel import io.github.chrisimx.scanbridge.data.ui.ScanSettingsComposableStateHolder import io.github.chrisimx.scanbridge.data.ui.ScanningScreenViewModel import io.github.chrisimx.scanbridge.datastore.appSettingsStore +import io.github.chrisimx.scanbridge.datastore.shownMessagesStore import io.github.chrisimx.scanbridge.db.ScanBridgeDb +import io.github.chrisimx.scanbridge.migrations.MigrationExecutor +import io.github.chrisimx.scanbridge.migrations.RoomBackedMigrationExecutor +import io.github.chrisimx.scanbridge.migrations.migrationsModule import io.github.chrisimx.scanbridge.proto.ScanBridgeSettings +import io.github.chrisimx.scanbridge.proto.ShownMessages +import io.github.chrisimx.scanbridge.repositories.DatastoreLastRouteRepository +import io.github.chrisimx.scanbridge.repositories.DatastoreShownMessagesRepository +import io.github.chrisimx.scanbridge.repositories.RoomLastRouteRepository import io.github.chrisimx.scanbridge.services.AndroidLocaleProvider import io.github.chrisimx.scanbridge.services.DebugLogService import io.github.chrisimx.scanbridge.services.FileDebugLogService @@ -17,13 +25,15 @@ import io.github.chrisimx.scanbridge.services.LocaleProvider import io.github.chrisimx.scanbridge.services.ScanJobRepository import io.github.chrisimx.scanbridge.stores.LegacyCustomScannerStore.migrateLegacyCustomScanners import io.github.chrisimx.scanbridge.stores.LegacySessionsStore.migrateLegacySessions -import java.util.concurrent.Executors -import kotlinx.coroutines.flow.firstOrNull -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import org.koin.android.ext.koin.androidContext import org.koin.core.context.startKoin +import org.koin.core.qualifier.named import org.koin.dsl.bind import org.koin.dsl.module +import org.koin.mp.KoinPlatform.getKoin import org.koin.plugin.module.dsl.factory import org.koin.plugin.module.dsl.single import org.koin.plugin.module.dsl.create @@ -32,32 +42,48 @@ import timber.log.Timber fun createAppSettingsDataStore(context: Context) = context.appSettingsStore val appModule = module { - single> { + single>(named()) { + get().shownMessagesStore + } + single>(named()) { create(::createAppSettingsDataStore) } + single() bind Thread.UncaughtExceptionHandler::class single() bind LocaleProvider::class - single() bind DebugLogService::class + single { + FileDebugLogService(get(named()),get()) + } bind DebugLogService::class + factory() bind ScanBridgeLogger::class single() + single() bind MigrationExecutor::class + includes(migrationsModule) single { val context = get() - val writeDebug = runBlocking { context.appSettingsStore.data.firstOrNull()?.writeDebug ?: false } val builder = Room.databaseBuilder( - get(), + context, ScanBridgeDb::class.java, "scanbridge" ) - if (writeDebug) { - builder.setQueryCallback( - { sqlQuery, bindArgs -> - Timber.tag("RoomDebug").d("SQL: $sqlQuery, args: $bindArgs") - }, - Executors.newSingleThreadExecutor() - ) - } - builder.build() - .migrateLegacyCustomScanners(get()) - .migrateLegacySessions(get()) + val logger = logger() + builder.setQueryCallback( + { sqlQuery, bindArgs -> + logger.debug("RoomDebug") { + "SQL: $sqlQuery, args: $bindArgs" + } + }, + { it.run() } + ) + val db = builder.build() + .migrateLegacyCustomScanners(context) + .migrateLegacySessions(context) + + return@single db } + single() + single() bind LastRouteRepository::class + single { (scope: CoroutineScope) -> + DatastoreShownMessagesRepository(get(named()), scope) + } bind ShownMessagesRepository::class factory() viewModel() viewModel() @@ -66,11 +92,22 @@ val appModule = module { class ScanBridgeApplication : Application() { override fun onCreate() { super.onCreate() - startKoin { + val koinApp = startKoin { androidContext(this@ScanBridgeApplication) modules(appModule) } Timber.plant(Timber.DebugTree()) + + runMigrations() + } + + fun runMigrations() { + val coroutineScope = CoroutineScope(Dispatchers.IO) + val migrationExecutor = getKoin().get() + coroutineScope.launch { + migrationExecutor.runMigrations() + } } } + diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt index 0473459..f4f9d54 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt @@ -5,10 +5,14 @@ import androidx.room.Database import androidx.room.RoomDatabase import androidx.room.TypeConverters import io.github.chrisimx.scanbridge.db.daos.CustomScannerDao +import io.github.chrisimx.scanbridge.db.daos.ExecutedMigrationsDao +import io.github.chrisimx.scanbridge.db.daos.LastRouteDao import io.github.chrisimx.scanbridge.db.daos.ScannedPageDao import io.github.chrisimx.scanbridge.db.daos.SessionDao import io.github.chrisimx.scanbridge.db.daos.TempFileDao import io.github.chrisimx.scanbridge.db.entities.CustomScanner +import io.github.chrisimx.scanbridge.db.entities.ExecutedMigrationToRoom +import io.github.chrisimx.scanbridge.db.entities.LastRoute import io.github.chrisimx.scanbridge.db.entities.ScannedPage import io.github.chrisimx.scanbridge.db.entities.Session import io.github.chrisimx.scanbridge.db.entities.TempFile @@ -18,12 +22,20 @@ import io.github.chrisimx.scanbridge.db.typeconverters.UrlTypeConverter import io.github.chrisimx.scanbridge.db.typeconverters.UuidTypeConverter @Database( - entities = [CustomScanner::class, ScannedPage::class, Session::class, TempFile::class], - version = 2, + entities = [CustomScanner::class, ScannedPage::class, Session::class, TempFile::class, LastRoute::class, ExecutedMigrationToRoom::class], + version = 4, autoMigrations = [ AutoMigration( from = 1, to = 2 + ), + AutoMigration( + from = 2, + to = 3 + ), + AutoMigration( + from = 3, + to = 4 ) ] ) @@ -38,4 +50,6 @@ abstract class ScanBridgeDb : RoomDatabase() { abstract fun scannedPageDao(): ScannedPageDao abstract fun sessionDao(): SessionDao abstract fun tmpFileDao(): TempFileDao + abstract fun lastRouteDao(): LastRouteDao + abstract fun executedMigrationsDao(): ExecutedMigrationsDao } diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt new file mode 100644 index 0000000..778ba47 --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt @@ -0,0 +1,18 @@ +package io.github.chrisimx.scanbridge.db.daos + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import io.github.chrisimx.scanbridge.db.entities.ExecutedMigrationToRoom + +@Dao +interface ExecutedMigrationsDao { + @Insert(onConflict = OnConflictStrategy.IGNORE) + fun markAsExecuted(migration: ExecutedMigrationToRoom) + + @Query("SELECT * FROM executedmigrationtoroom WHERE migrationId = :id") + fun getExecutedMigration(id: String): ExecutedMigrationToRoom? + + fun isAlreadyDone(id: String): Boolean = getExecutedMigration(id) != null +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt new file mode 100644 index 0000000..807a0c2 --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt @@ -0,0 +1,19 @@ +package io.github.chrisimx.scanbridge.db.daos + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import io.github.chrisimx.scanbridge.db.entities.LastRoute + +@Dao +interface LastRouteDao { + @Query("SELECT * FROM lastroute WHERE id = 1") + suspend fun getLastRoute(): LastRoute? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun setLastRoute(lastRoute: LastRoute) + + @Query("DELETE FROM lastroute WHERE id = 1") + suspend fun clearLastRoute() +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt new file mode 100644 index 0000000..7f97732 --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt @@ -0,0 +1,10 @@ +package io.github.chrisimx.scanbridge.db.entities + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "executedmigrationtoroom") +data class ExecutedMigrationToRoom( + @PrimaryKey + val migrationId: String, +) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt new file mode 100644 index 0000000..ec5af8f --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt @@ -0,0 +1,10 @@ +package io.github.chrisimx.scanbridge.db.entities + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "lastroute") +data class LastRoute ( + val route: String, + @PrimaryKey val id: Int = 1 +) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/Migration.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/Migration.kt new file mode 100644 index 0000000..6ec515d --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/Migration.kt @@ -0,0 +1,16 @@ +package io.github.chrisimx.scanbridge.migrations + +import io.github.chrisimx.scanbridge.db.ScanBridgeDb + +interface Migration { + /** + * A unique identifier of the migration that will be used to determine if it has already run + */ + val migrationId: String + + /** + * Execute the migration + * @return Whether the migration was successful + */ + suspend fun migrate(db: ScanBridgeDb): Boolean +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationExecutor.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationExecutor.kt new file mode 100644 index 0000000..f0968f4 --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationExecutor.kt @@ -0,0 +1,5 @@ +package io.github.chrisimx.scanbridge.migrations + +interface MigrationExecutor { + suspend fun runMigrations() +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt new file mode 100644 index 0000000..33d831f --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt @@ -0,0 +1,17 @@ +package io.github.chrisimx.scanbridge.migrations + +import io.github.chrisimx.scanbridge.repositories.DatastoreLastRouteRepository +import io.github.chrisimx.scanbridge.repositories.LastRouteRepoAutoMigration +import io.github.chrisimx.scanbridge.repositories.RoomLastRouteRepository +import org.koin.dsl.bind +import org.koin.dsl.module + +val migrationsModule = module { + single { + LastRouteRepoAutoMigration( + get(), + get(), + "LastRouteDataStoreToRoom" + ) + } bind Migration::class +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt new file mode 100644 index 0000000..44508eb --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt @@ -0,0 +1,36 @@ +package io.github.chrisimx.scanbridge.migrations + +import io.github.chrisimx.scanbridge.db.ScanBridgeDb +import io.github.chrisimx.scanbridge.db.entities.ExecutedMigrationToRoom +import io.github.chrisimx.scanbridge.logger +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.koin.core.scope.Scope +import org.koin.mp.KoinPlatform.getKoin + +class RoomBackedMigrationExecutor(val db: ScanBridgeDb) : MigrationExecutor { + val logger by logger() + val executedMigrationsDao = db.executedMigrationsDao() + override suspend fun runMigrations() { + val migrations = getKoin().getAll() + + migrations.forEach { + withContext(Dispatchers.IO) { + val ranAlready = executedMigrationsDao.isAlreadyDone(it.migrationId) + if (!ranAlready) { + val success = it.migrate(db) + if (success) { + executedMigrationsDao.markAsExecuted( + ExecutedMigrationToRoom(it.migrationId) + ) + logger.info { "Migration with id ${it.migrationId} has finished successfully." } + } else { + logger.error { "Migration with id ${it.migrationId} has failed" } + } + } else { + logger.debug { "Migration with id ${it.migrationId} has already run" } + } + } + } + } +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreLastRouteRepository.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreLastRouteRepository.kt new file mode 100644 index 0000000..536242f --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreLastRouteRepository.kt @@ -0,0 +1,32 @@ +package io.github.chrisimx.scanbridge.repositories + +import android.content.Context +import com.google.protobuf.StringValue +import io.github.chrisimx.scanbridge.LastRouteRepository +import io.github.chrisimx.scanbridge.datastore.lastRouteStore +import io.github.chrisimx.scanbridge.proto.copy +import io.github.chrisimx.scanbridge.proto.lastRouteOrNull +import kotlinx.coroutines.flow.firstOrNull + +class DatastoreLastRouteRepository(context: Context): LastRouteRepository { + val lastRouteStore = context.lastRouteStore + override suspend fun getLastRoute(): String? = lastRouteStore.data.firstOrNull()?.lastRouteOrNull?.value + + override suspend fun setLastRoute(route: String?) { + if (route != null) { + lastRouteStore.updateData { + it.copy { + lastRoute = StringValue.of(route) + } + } + } else { + lastRouteStore.updateData { + lastRouteStore.updateData { + it.copy { + clearLastRoute() + } + } + } + } + } +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreShownMessagesRepository.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreShownMessagesRepository.kt new file mode 100644 index 0000000..7a19022 --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreShownMessagesRepository.kt @@ -0,0 +1,42 @@ +package io.github.chrisimx.scanbridge.repositories + +import androidx.datastore.core.DataStore +import io.github.chrisimx.scanbridge.BuildConfig +import io.github.chrisimx.scanbridge.ShownMessagesRepository +import io.github.chrisimx.scanbridge.UserInformationMessage +import io.github.chrisimx.scanbridge.proto.ShownMessages +import io.github.chrisimx.scanbridge.proto.copy +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import org.koin.core.annotation.InjectedParam +import org.koin.core.annotation.Named + +class DatastoreShownMessagesRepository( + val shownMessagesDataStore: DataStore, + @InjectedParam + val coroutineScope: CoroutineScope +) : ShownMessagesRepository { + override fun getWasShownFlow(message: UserInformationMessage): Flow { + return shownMessagesDataStore.data.map { + (BuildConfig.FLAVOR != "play" && message.playOnly) || !when (message) { + UserInformationMessage.THANKS_FOR_PURCHASE -> it.thankPlayOne + } + } + } + + override suspend fun setShown( + message: UserInformationMessage, + shown: Boolean + ) { + shownMessagesDataStore.updateData { + it.copy { + when (message) { + UserInformationMessage.THANKS_FOR_PURCHASE -> { + thankPlayOne = shown + } + } + } + } + } +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/RoomLastRouteRepository.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/RoomLastRouteRepository.kt new file mode 100644 index 0000000..a7a7bd5 --- /dev/null +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/RoomLastRouteRepository.kt @@ -0,0 +1,30 @@ +package io.github.chrisimx.scanbridge.repositories + +import io.github.chrisimx.scanbridge.LastRouteRepository +import io.github.chrisimx.scanbridge.migrations.Migration +import io.github.chrisimx.scanbridge.db.ScanBridgeDb +import io.github.chrisimx.scanbridge.db.entities.LastRoute +import org.koin.core.annotation.InjectedParam + +class RoomLastRouteRepository(db: ScanBridgeDb): LastRouteRepository { + val lastRouteDao = db.lastRouteDao() + override suspend fun getLastRoute(): String? = lastRouteDao.getLastRoute()?.route + + override suspend fun setLastRoute(route: String?) { + if (route != null) { + lastRouteDao.setLastRoute(LastRoute(route)) + } else { + lastRouteDao.clearLastRoute() + } + } +} + +class LastRouteRepoAutoMigration(val a: LastRouteRepository, + val b: LastRouteRepository, + override val migrationId: String) : Migration { + override suspend fun migrate(db: ScanBridgeDb): Boolean { + val toBeMigrated = a.getLastRoute() + b.setLastRoute(toBeMigrated) + return true + } +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt index 780a165..7fdd301 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/FileDebugLogService.kt @@ -17,7 +17,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import timber.log.Timber -class FileDebugLogService(val appSettings: DataStore, val application: Application) : DebugLogService { +class FileDebugLogService(appSettings: DataStore, val application: Application) : DebugLogService { val scope = CoroutineScope(Dispatchers.Main) diff --git a/composeUI/build.gradle.kts b/composeUI/build.gradle.kts index 45c3725..b3a13b0 100644 --- a/composeUI/build.gradle.kts +++ b/composeUI/build.gradle.kts @@ -20,17 +20,13 @@ kotlin { minSdk = 23 androidResources.enable = true - /*compilerOptions.configure { + compilerOptions { jvmTarget.set( org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 ) - }*/ + } } - - iosArm64() - iosSimulatorArm64() - sourceSets { commonMain.dependencies { api(libs.compose.runtime) diff --git a/composeUI/src/jvmMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.jvm.kt b/composeUI/src/jvmMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.jvm.kt new file mode 100644 index 0000000..862a0dd --- /dev/null +++ b/composeUI/src/jvmMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.jvm.kt @@ -0,0 +1,10 @@ +package io.github.chrisimx.scanbridge.theme + +import androidx.compose.material3.ColorScheme +import androidx.compose.runtime.Composable + +@Composable +actual fun platformDarkColorScheme(): ColorScheme? = null + +@Composable +actual fun platformLightColorScheme(): ColorScheme? = null diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 6a9dba5..5aa0f5d 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -5,6 +5,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.android.kmp.library) + alias(libs.plugins.koin) } kotlin { @@ -17,11 +18,12 @@ kotlin { compileSdk = 36 minSdk = 23 - /*compilerOptions.configure { + + compilerOptions { jvmTarget.set( org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 ) - }*/ + } } @@ -30,7 +32,10 @@ kotlin { sourceSets { commonMain.dependencies { - + api("com.diamondedge:logging:2.1.0") + api(libs.koin.core) + api(libs.koin.annotations) + api(libs.kotlinx.coroutines) } commonTest.dependencies { diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/KmLogScanBridgeLogger.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/KmLogScanBridgeLogger.kt new file mode 100644 index 0000000..1541580 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/KmLogScanBridgeLogger.kt @@ -0,0 +1,49 @@ +package io.github.chrisimx.scanbridge + +import com.diamondedge.logging.KmLog +import com.diamondedge.logging.logging +import org.koin.core.annotation.InjectedParam +import org.koin.mp.KoinPlatform.getKoin + +class KmLogScanBridgeLogger( + @InjectedParam + tag: String +) : ScanBridgeLogger { + private val logger: KmLog = logging(tag) + + override fun verbose(tag: String?, msg: () -> String) { + logger.v(tag, msg) + } + + override fun debug(tag: String?, msg: () -> String) { + logger.d(tag, msg) + } + + override fun info(tag: String?, msg: () -> String,) { + logger.i(tag, msg) + } + + override fun warn(t: Throwable?, tag: String?, msg: () -> String) { + logger.w(t, tag, msg) + } + + override fun error(t: Throwable?, tag: String?, msg: () -> String) { + logger.e(t, tag, msg) + } + + override fun wtf(t: Throwable?, tag: String?, msg: () -> String) { + logger.e(t, tag, msg) + } +} + +inline fun org.koin.core.scope.Scope.logger(): ScanBridgeLogger { + val tag = T::class.simpleName ?: "Unknown" + return get { org.koin.core.parameter.parametersOf(tag) } +} + +inline fun logger() = lazy { + val koin = getKoin() + koin.get { + org.koin.core.parameter.parametersOf(T::class.simpleName ?: "Unknown") + } +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LastRouteRepository.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LastRouteRepository.kt new file mode 100644 index 0000000..d7027af --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LastRouteRepository.kt @@ -0,0 +1,6 @@ +package io.github.chrisimx.scanbridge + +interface LastRouteRepository { + suspend fun getLastRoute(): String? + suspend fun setLastRoute(route: String?) +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanBridgeLogger.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanBridgeLogger.kt new file mode 100644 index 0000000..d9193f8 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanBridgeLogger.kt @@ -0,0 +1,21 @@ +package io.github.chrisimx.scanbridge + +interface ScanBridgeLogger { + /** Log a verbose message */ + fun verbose(tag: String? = null, msg: () -> String) + + /** Log a debug message */ + fun debug(tag: String? = null, msg: () -> String) + + /** Log an info message */ + fun info(tag: String? = null, msg: () -> String) + + /** Log a warning message with optional throwable */ + fun warn(t: Throwable? = null, tag: String? = null, msg: () -> String) + + /** Log an error message with optional throwable */ + fun error(t: Throwable? = null, tag: String? = null, msg: () -> String) + + /** Log a critical/fatal message with optional throwable */ + fun wtf(t: Throwable? = null, tag: String? = null, msg: () -> String) +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ShownMessagesRepository.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ShownMessagesRepository.kt new file mode 100644 index 0000000..af6b846 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ShownMessagesRepository.kt @@ -0,0 +1,12 @@ +package io.github.chrisimx.scanbridge + +import kotlinx.coroutines.flow.Flow + +interface ShownMessagesRepository { + fun getWasShownFlow(message: UserInformationMessage): Flow + suspend fun setShown(message: UserInformationMessage, shown: Boolean) +} + +enum class UserInformationMessage(val playOnly: Boolean) { + THANKS_FOR_PURCHASE(true) +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d52b88f..627e2a2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,6 +17,7 @@ junitVersion = "1.3.0" espressoCore = "3.7.0" kotlinReflect = "2.1.20" kotlinxSerializationJson = "1.9.0" +kotlinxCoroutines = "1.10.2" lifecycleRuntimeKtx = "2.9.4" activityCompose = "1.11.0" composeBom = "2026.03.01" @@ -96,6 +97,7 @@ androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit androidx-material3 = { module = "androidx.compose.material3:material3", version.ref= "androidx-material3" } kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlinReflect" } kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +kotlinx-coroutines = { module = " org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines"} screengrab = { module = "tools.fastlane:screengrab", version.ref = "screengrab" } timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } zoomable = { module = "me.saket.telephoto:zoomable", version.ref = "zoomable" } From f05d4a86d7b9c2971df1421faae771bf5a1efb51 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Sun, 5 Apr 2026 00:28:23 +0200 Subject: [PATCH 08/26] Move all deps from androidApp build.gradle.kts to version catalog --- androidApp/build.gradle.kts | 17 ++++++++++------- gradle/libs.versions.toml | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 18b0614..bb365bf 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -1,3 +1,4 @@ +import com.android.utils.TraceUtils.simpleId import java.util.* import org.jetbrains.kotlin.gradle.dsl.JvmTarget @@ -14,8 +15,8 @@ plugins { alias(libs.plugins.koin) alias(libs.plugins.protobuf) alias(libs.plugins.room) - id("com.google.devtools.ksp") version "2.3.6" - id("app.cash.paraphrase") version "0.4.1" + alias(libs.plugins.ksp) + alias(libs.plugins.paraphrase) } val gitHashProvider = providers.exec { @@ -112,7 +113,7 @@ dependencies { implementation(libs.kotlinx.serialization.json) implementation(project(":core")) implementation(project(":composeUI")) - implementation("androidx.concurrent:concurrent-futures:1.2.0") + implementation(libs.androidx.concurrent.futures) ksp(libs.androidx.room.compiler) implementation(libs.androidx.room.runtime) @@ -136,9 +137,9 @@ dependencies { implementation(libs.ktor.okhttp) implementation(libs.ktor.logging) "playImplementation"(project(":lvl_library")) - "playImplementation"("com.squareup.retrofit2:retrofit:3.0.0") - "playImplementation"("com.squareup.retrofit2:converter-gson:2.9.0") - "playImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") + "playImplementation"(libs.retrofit) + "playImplementation"(libs.retrofit.converter.gson) + "playImplementation"(libs.kotlinx.coroutines.android) testImplementation(libs.junit) @@ -155,7 +156,9 @@ dependencies { protobuf { protoc { - artifact = "com.google.protobuf:protoc:4.33.5" + val protoc = libs.protoc.get() + + artifact = "${protoc.module}:${protoc.version}" } generateProtoTasks { all().forEach { task -> diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 627e2a2..e794423 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,9 @@ androidx-activityCompose = "1.12.0" agp = "9.1.0" coilCompose = "3.3.0" +concurrentFutures = "1.2.0" constraintlayoutCompose = "1.1.1" +converterGson = "2.9.0" datastore = "1.2.0" esclkt = "2.0.6" escl-mock-server = "1.0.1" @@ -16,11 +18,13 @@ junit = "4.13.2" junitVersion = "1.3.0" espressoCore = "3.7.0" kotlinReflect = "2.1.20" +kotlinxCoroutinesAndroid = "1.7.3" kotlinxSerializationJson = "1.9.0" kotlinxCoroutines = "1.10.2" lifecycleRuntimeKtx = "2.9.4" activityCompose = "1.11.0" composeBom = "2026.03.01" +retrofit = "3.0.0" room = "2.8.4" timber = "5.0.1" zoomable = "0.18.0" @@ -36,9 +40,13 @@ koin-plugin = "0.3.0" protobuf-plugin = "0.9.6" protobuf-kotlin-lite = "4.33.5" rules = "1.7.0" +paraphrase-plugin = "0.4.1" +ksp = "2.3.6" +protoc = "4.33.5" [libraries] +androidx-concurrent-futures = { module = "androidx.concurrent:concurrent-futures", version.ref = "concurrentFutures" } compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose-multiplatform" } compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "compose-multiplatform" } compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "compose-multiplatform" } @@ -55,6 +63,7 @@ androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } +retrofit-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" } koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" } koin-annotations = { module = "io.insert-koin:koin-annotations", version.ref = "koin" } koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin" } @@ -73,6 +82,7 @@ koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", ver koin-compose-viewmodel-navigation = { module = "io.insert-koin:koin-compose-viewmodel-navigation", version.ref = "koin" } koin-androidx-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koin" } +kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" } ktor-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor"} ktor-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor"} androidx-constraintlayout-compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "constraintlayoutCompose" } @@ -98,11 +108,13 @@ androidx-material3 = { module = "androidx.compose.material3:material3", version. kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlinReflect" } kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } kotlinx-coroutines = { module = " org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines"} +retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } screengrab = { module = "tools.fastlane:screengrab", version.ref = "screengrab" } timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } zoomable = { module = "me.saket.telephoto:zoomable", version.ref = "zoomable" } protobuf-kotlin-lite = { module = "com.google.protobuf:protobuf-kotlin-lite", version.ref = "protobuf-kotlin-lite"} androidx-rules = { group = "androidx.test", name = "rules", version.ref = "rules" } +protoc = { module = "com.google.protobuf:protoc", version.ref = "protoc" } escl-mock-server = { module = "io.github.chrisimx:escl-mock-server", version.ref = "escl-mock-server"} @@ -121,4 +133,6 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi versions = { id = "com.github.ben-manes.versions", version.ref = "versionsPlugin" } koin = { id = "io.insert-koin.compiler.plugin", version.ref = "koin-plugin" } protobuf = { id = "com.google.protobuf", version.ref = "protobuf-plugin" } -room = { id = "androidx.room", version.ref = "room"} \ No newline at end of file +room = { id = "androidx.room", version.ref = "room"} +paraphrase = { id = "app.cash.paraphrase", version.ref = "paraphrase-plugin"} +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } \ No newline at end of file From 653a5366f2a7593cfd3e151a3404005736f04b35 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 12:18:14 +0200 Subject: [PATCH 09/26] Put some Koin factories in create functions --- .../scanbridge/ScanBridgeApplication.kt | 48 ++++++++++--------- .../migrations/MigrationRegistry.kt | 15 ++++-- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt index 7d96d9a..4e31b05 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt @@ -41,9 +41,32 @@ import org.koin.plugin.module.dsl.viewModel import timber.log.Timber fun createAppSettingsDataStore(context: Context) = context.appSettingsStore +fun createShownMessagesDataStore(context: Context) = context.shownMessagesStore + +fun createScanBridgeDb(context: Context): ScanBridgeDb { + val builder = Room.databaseBuilder( + context, + ScanBridgeDb::class.java, + "scanbridge" + ) + //val logger = logger() + builder.setQueryCallback( + { sqlQuery, bindArgs -> + // logger.debug("RoomDebug") { + // "SQL: $sqlQuery, args: $bindArgs" + // } + }, + { it.run() } + ) + val db = builder.build() + .migrateLegacyCustomScanners(context) + .migrateLegacySessions(context) + + return db +} val appModule = module { single>(named()) { - get().shownMessagesStore + create(::createShownMessagesDataStore) } single>(named()) { create(::createAppSettingsDataStore) @@ -58,26 +81,7 @@ val appModule = module { single() bind MigrationExecutor::class includes(migrationsModule) single { - val context = get() - val builder = Room.databaseBuilder( - context, - ScanBridgeDb::class.java, - "scanbridge" - ) - val logger = logger() - builder.setQueryCallback( - { sqlQuery, bindArgs -> - logger.debug("RoomDebug") { - "SQL: $sqlQuery, args: $bindArgs" - } - }, - { it.run() } - ) - val db = builder.build() - .migrateLegacyCustomScanners(context) - .migrateLegacySessions(context) - - return@single db + create(::createScanBridgeDb) } single() single() bind LastRouteRepository::class @@ -92,7 +96,7 @@ val appModule = module { class ScanBridgeApplication : Application() { override fun onCreate() { super.onCreate() - val koinApp = startKoin { + startKoin { androidContext(this@ScanBridgeApplication) modules(appModule) } diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt index 33d831f..b4f71e1 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt @@ -5,13 +5,18 @@ import io.github.chrisimx.scanbridge.repositories.LastRouteRepoAutoMigration import io.github.chrisimx.scanbridge.repositories.RoomLastRouteRepository import org.koin.dsl.bind import org.koin.dsl.module +import org.koin.plugin.module.dsl.create + +fun createLastRouteRepoAutoMigration(datastoreLastRouteRepository: DatastoreLastRouteRepository, roomLastRouteRepository: RoomLastRouteRepository): LastRouteRepoAutoMigration { + return LastRouteRepoAutoMigration( + datastoreLastRouteRepository, + roomLastRouteRepository, + "LastRouteDataStoreToRoom" + ) +} val migrationsModule = module { single { - LastRouteRepoAutoMigration( - get(), - get(), - "LastRouteDataStoreToRoom" - ) + create(::createLastRouteRepoAutoMigration) } bind Migration::class } From 25b07168aae03754204f9b7fac1263902ac43692 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 12:26:27 +0200 Subject: [PATCH 10/26] Upgarde Koin and enable compile time safety --- androidApp/build.gradle.kts | 4 ++++ gradle/libs.versions.toml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index bb365bf..55d223a 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -172,6 +172,10 @@ protobuf { } } +koinCompiler { + compileSafety = true +} + afterEvaluate { tasks.named("clean") { doLast { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e794423..e2e118e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -35,8 +35,8 @@ navigationCompose = "2.9.5" versionsPlugin = "0.53.0" screengrab = "2.1.1" ktor = "3.4.0" -koin = "4.2.0-RC1" -koin-plugin = "0.3.0" +koin = "4.2.0" +koin-plugin = "0.6.2" protobuf-plugin = "0.9.6" protobuf-kotlin-lite = "4.33.5" rules = "1.7.0" From 2bc16448c83ee3754d30697520dcb884b5962524 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Mon, 6 Apr 2026 12:04:59 +0200 Subject: [PATCH 11/26] Add build folder of desktopApp to gitignore --- desktopApp/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 desktopApp/.gitignore diff --git a/desktopApp/.gitignore b/desktopApp/.gitignore new file mode 100644 index 0000000..c795b05 --- /dev/null +++ b/desktopApp/.gitignore @@ -0,0 +1 @@ +build \ No newline at end of file From 32327d98a0f3ceb020463d0014952aed418495a4 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 12:49:12 +0200 Subject: [PATCH 12/26] Move LocaleProvider interface to core --- .../ui/ScanSettingsComposableStateHolder.kt | 6 +++--- .../services/AndroidLocaleProvider.kt | 12 +++++++----- .../scanbridge/services/LocaleProvider.kt | 8 -------- .../chrisimx/scanbridge/LocaleProvider.kt | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 16 deletions(-) delete mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LocaleProvider.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt index 1d122b6..2516d35 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt @@ -39,12 +39,12 @@ import io.github.chrisimx.esclkt.inches import io.github.chrisimx.esclkt.millimeters import io.github.chrisimx.esclkt.scanRegion import io.github.chrisimx.esclkt.threeHundredthsOfInch +import io.github.chrisimx.scanbridge.Locale import io.github.chrisimx.scanbridge.R -import io.github.chrisimx.scanbridge.services.LocaleProvider +import io.github.chrisimx.scanbridge.LocaleProvider import io.github.chrisimx.scanbridge.util.derived import io.github.chrisimx.scanbridge.util.getMaxResolution import io.github.chrisimx.scanbridge.util.toDoubleLocalized -import java.util.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -402,7 +402,7 @@ class ScanSettingsComposableStateHolder( } } - private fun unitByLocale(locale: Locale = Locale.getDefault()): ScanSettingsLengthUnit = + private fun unitByLocale(locale: Locale): ScanSettingsLengthUnit = if (locale.country in setOf("US", "LR", "MM")) { ScanSettingsLengthUnit.INCH } else { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt index db456fe..1014806 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt @@ -1,20 +1,22 @@ package io.github.chrisimx.scanbridge.services import android.annotation.SuppressLint -import java.util.Locale +import io.github.chrisimx.scanbridge.Locale +import io.github.chrisimx.scanbridge.LocaleProvider import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import timber.log.Timber class AndroidLocaleProvider : LocaleProvider { - @SuppressLint("ConstantLocale") - private val _locale = MutableStateFlow(Locale.getDefault()) + @SuppressLint("ConstantLocale") // Constant local is not correct because update is called on Activity recreation + private val _locale = MutableStateFlow(getCurrentLocale()) override val locale: StateFlow = _locale.asStateFlow() + private fun getCurrentLocale(): Locale = Locale(java.util.Locale.getDefault().country) + internal fun update() { - val locale = Locale.getDefault() Timber.d("Locale updated to $locale") - _locale.value = locale + _locale.value = getCurrentLocale() } } diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt deleted file mode 100644 index 8aef6fd..0000000 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/LocaleProvider.kt +++ /dev/null @@ -1,8 +0,0 @@ -package io.github.chrisimx.scanbridge.services - -import java.util.Locale -import kotlinx.coroutines.flow.StateFlow - -interface LocaleProvider { - val locale: StateFlow -} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LocaleProvider.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LocaleProvider.kt new file mode 100644 index 0000000..d7c060e --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LocaleProvider.kt @@ -0,0 +1,17 @@ +package io.github.chrisimx.scanbridge + +import kotlinx.coroutines.flow.StateFlow + +data class Locale( + /** + * The two character country code in uppercase + */ + val country: String +) + +/** + * Provides the currently selected [Locale] as a reactive stream. + */ +interface LocaleProvider { + val locale: StateFlow +} From 6990eae1bc4288d1edf68c5307222656e0a156e9 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 12:53:08 +0200 Subject: [PATCH 13/26] Remove unnecessary import in ScanBridgeApplication.kt --- .../java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt index 4e31b05..8d88dbb 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt @@ -21,7 +21,6 @@ import io.github.chrisimx.scanbridge.repositories.RoomLastRouteRepository import io.github.chrisimx.scanbridge.services.AndroidLocaleProvider import io.github.chrisimx.scanbridge.services.DebugLogService import io.github.chrisimx.scanbridge.services.FileDebugLogService -import io.github.chrisimx.scanbridge.services.LocaleProvider import io.github.chrisimx.scanbridge.services.ScanJobRepository import io.github.chrisimx.scanbridge.stores.LegacyCustomScannerStore.migrateLegacyCustomScanners import io.github.chrisimx.scanbridge.stores.LegacySessionsStore.migrateLegacySessions From e2b68dc7890674622ec13f67ca27cf9481023f85 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 13:57:44 +0200 Subject: [PATCH 14/26] Move PaperFormat model to core --- androidApp/build.gradle.kts | 1 - .../data/ui/ScanSettingsStateData.kt | 4 +- .../scanbridge/ScanSettingsStoreTest.kt | 164 ------------------ core/build.gradle.kts | 5 +- .../chrisimx/scanbridge}/PaperFormat.kt | 2 +- .../src/commonTest/kotlin}/PaperFormatTest.kt | 8 +- 6 files changed, 10 insertions(+), 174 deletions(-) delete mode 100644 androidApp/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt rename {androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model => core/src/commonMain/kotlin/io/github/chrisimx/scanbridge}/PaperFormat.kt (97%) rename {androidApp/src/test/java/org/github/chrisimx/scanbridge => core/src/commonTest/kotlin}/PaperFormatTest.kt (90%) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 55d223a..482fbe8 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -104,7 +104,6 @@ dependencies { implementation(libs.koin.annotations) implementation(libs.koin.compose.viewmodel) implementation(libs.koin.androix.navigation) - implementation(libs.esclkt) implementation(libs.zoomable) implementation(libs.kotlin.reflect) implementation(libs.coil.compose) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt index 62a322e..9d6d16e 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt @@ -20,8 +20,8 @@ package io.github.chrisimx.scanbridge.data.ui import io.github.chrisimx.esclkt.ScannerCapabilities -import io.github.chrisimx.scanbridge.data.model.PaperFormat -import io.github.chrisimx.scanbridge.data.model.loadDefaultFormats +import io.github.chrisimx.scanbridge.PaperFormat +import io.github.chrisimx.scanbridge.loadDefaultFormats import kotlinx.serialization.Serializable @Serializable diff --git a/androidApp/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt b/androidApp/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt deleted file mode 100644 index d2320e3..0000000 --- a/androidApp/src/test/java/org/github/chrisimx/scanbridge/ScanSettingsStoreTest.kt +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2024-2025 Christian Nagel and contributors - * - * This file is part of ScanBridge. - * - * ScanBridge is free software: you can redistribute it and/or modify it under the terms of - * the GNU General Public License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * ScanBridge is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with eSCLKt. - * If not, see . - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -package org.github.chrisimx.scanbridge - -import io.github.chrisimx.esclkt.ColorMode -import io.github.chrisimx.esclkt.EnumOrRaw -import io.github.chrisimx.esclkt.InputSource -import io.github.chrisimx.scanbridge.data.model.StatelessImmutableESCLScanSettingsState -import io.github.chrisimx.scanbridge.data.model.StatelessImmutableScanRegion -import org.junit.Assert.assertEquals -import org.junit.Test - -class ScanSettingsStoreTest { - - @Test - fun testScanSettingsPersistenceBehavior() { - val testSettings = StatelessImmutableESCLScanSettingsState( - version = "2.63", - intent = null, - scanRegions = StatelessImmutableScanRegion("297", "210", "0", "0"), - documentFormatExt = "application/pdf", - contentType = null, - inputSource = InputSource.Feeder, - xResolution = 300u, - yResolution = 300u, - colorMode = EnumOrRaw.Known(ColorMode.RGB24), - colorSpace = null, - mediaType = null, - ccdChannel = null, - binaryRendering = null, - duplex = true, - numberOfPages = null, - brightness = null, - compressionFactor = null, - contrast = null, - gamma = null, - highlight = null, - noiseRemoval = null, - shadow = null, - sharpen = null, - threshold = null, - contextID = null, - blankPageDetection = null, - feedDirection = null, - blankPageDetectionAndRemoval = null - ) - - assertEquals(InputSource.Feeder, testSettings.inputSource) - assertEquals(true, testSettings.duplex) - assertEquals("210", testSettings.scanRegions?.width) - assertEquals("297", testSettings.scanRegions?.height) - assertEquals("application/pdf", testSettings.documentFormatExt) - - // Test conversion to mutable (for editing in UI) - val mutableSettings = testSettings.toMutable() - assertEquals(InputSource.Feeder, mutableSettings.inputSource) - assertEquals(true, mutableSettings.duplex) - - // Test conversion back to stateless (for persistence) - val statelessSettings = mutableSettings.toStateless() - assertEquals(testSettings.inputSource, statelessSettings.inputSource) - assertEquals(testSettings.duplex, statelessSettings.duplex) - assertEquals(testSettings.documentFormatExt, statelessSettings.documentFormatExt) - } - - @Test - fun testScanSettingsStatelessDataStructure() { - val testScanRegion = StatelessImmutableScanRegion( - "297", - "210", - "0", - "0" - ) - - val testSettings = StatelessImmutableESCLScanSettingsState( - version = "2.63", - intent = null, - scanRegions = testScanRegion, - documentFormatExt = "image/jpeg", - contentType = null, - inputSource = InputSource.Feeder, - xResolution = 300u, - yResolution = 300u, - colorMode = EnumOrRaw.Known(ColorMode.RGB24), - colorSpace = null, - mediaType = null, - ccdChannel = null, - binaryRendering = null, - duplex = true, - numberOfPages = null, - brightness = null, - compressionFactor = null, - contrast = null, - gamma = null, - highlight = null, - noiseRemoval = null, - shadow = null, - sharpen = null, - threshold = null, - contextID = null, - blankPageDetection = null, - feedDirection = null, - blankPageDetectionAndRemoval = null - ) - - assertEquals(InputSource.Feeder, testSettings.inputSource) - assertEquals(true, testSettings.duplex) - assertEquals("image/jpeg", testSettings.documentFormatExt) - assertEquals(true, testSettings.scanRegions != null) - - // Test the toMutable conversion to ensure settings can be converted back - val mutableSettings = testSettings.toMutable() - assertEquals(InputSource.Feeder, mutableSettings.inputSource) - assertEquals(true, mutableSettings.duplex) - assertEquals("image/jpeg", mutableSettings.documentFormatExt) - - // Test that we can convert back to stateless - val reconvertedSettings = mutableSettings.toStateless() - assertEquals(testSettings.inputSource, reconvertedSettings.inputSource) - assertEquals(testSettings.duplex, reconvertedSettings.duplex) - assertEquals(testSettings.documentFormatExt, reconvertedSettings.documentFormatExt) - } - - @Test - fun testScanRegionDataStructure() { - val a4Region = StatelessImmutableScanRegion("297", "210", "0", "0") - val mutableA4 = a4Region.toMutable() - - assertEquals("210", mutableA4.width) - assertEquals("297", mutableA4.height) - assertEquals("0", mutableA4.xOffset) - assertEquals("0", mutableA4.yOffset) - - // Test that we can modify mutable settings - mutableA4.width = "148" // A5 width - mutableA4.height = "210" // A5 height - - assertEquals("148", mutableA4.width) - assertEquals("210", mutableA4.height) - - // Test conversion back to stateless - val a5Region = mutableA4.toStateless() - val reconvertedA5 = a5Region.toMutable() - assertEquals("148", reconvertedA5.width) - assertEquals("210", reconvertedA5.height) - } -} diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 5aa0f5d..114dbd3 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.android.kmp.library) alias(libs.plugins.koin) + alias(libs.plugins.kotlin.serialization) } kotlin { @@ -36,10 +37,12 @@ kotlin { api(libs.koin.core) api(libs.koin.annotations) api(libs.kotlinx.coroutines) + api(libs.kotlinx.serialization.json) + api(libs.esclkt) } commonTest.dependencies { - + implementation(kotlin("test")) } androidMain.dependencies { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/PaperFormat.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/PaperFormat.kt similarity index 97% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/PaperFormat.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/PaperFormat.kt index b315c11..411cd7d 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/PaperFormat.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/PaperFormat.kt @@ -1,4 +1,4 @@ -package io.github.chrisimx.scanbridge.data.model +package io.github.chrisimx.scanbridge import io.github.chrisimx.esclkt.LengthUnit import io.github.chrisimx.esclkt.Millimeters diff --git a/androidApp/src/test/java/org/github/chrisimx/scanbridge/PaperFormatTest.kt b/core/src/commonTest/kotlin/PaperFormatTest.kt similarity index 90% rename from androidApp/src/test/java/org/github/chrisimx/scanbridge/PaperFormatTest.kt rename to core/src/commonTest/kotlin/PaperFormatTest.kt index ac6ecd0..24d98ae 100644 --- a/androidApp/src/test/java/org/github/chrisimx/scanbridge/PaperFormatTest.kt +++ b/core/src/commonTest/kotlin/PaperFormatTest.kt @@ -17,11 +17,9 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -package org.github.chrisimx.scanbridge - -import io.github.chrisimx.scanbridge.data.model.loadDefaultFormats -import junit.framework.TestCase.assertEquals -import org.junit.Test +import io.github.chrisimx.scanbridge.loadDefaultFormats +import kotlin.test.Test +import kotlin.test.assertEquals class PaperFormatTest { From f046e265b0684d6a2022beb4d6c4703026106f38 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 14:12:24 +0200 Subject: [PATCH 15/26] Prepare Room db for KMP migration --- androidApp/build.gradle.kts | 2 +- .../scanbridge/ScanBridgeApplication.kt | 18 ++++++------------ gradle/libs.versions.toml | 2 ++ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 482fbe8..470f94e 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -116,7 +116,7 @@ dependencies { ksp(libs.androidx.room.compiler) implementation(libs.androidx.room.runtime) - implementation(libs.androidx.room.ktx) + implementation(libs.androidx.sqlite.bundled) implementation(libs.androidx.datastore) implementation(libs.protobuf.kotlin.lite) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt index 8d88dbb..87e93db 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt @@ -37,26 +37,20 @@ import org.koin.plugin.module.dsl.factory import org.koin.plugin.module.dsl.single import org.koin.plugin.module.dsl.create import org.koin.plugin.module.dsl.viewModel +import androidx.sqlite.driver.bundled.BundledSQLiteDriver import timber.log.Timber fun createAppSettingsDataStore(context: Context) = context.appSettingsStore fun createShownMessagesDataStore(context: Context) = context.shownMessagesStore fun createScanBridgeDb(context: Context): ScanBridgeDb { - val builder = Room.databaseBuilder( + val databaseFile = context.getDatabasePath("scanbridge") + val builder = Room.databaseBuilder( context, - ScanBridgeDb::class.java, - "scanbridge" - ) - //val logger = logger() - builder.setQueryCallback( - { sqlQuery, bindArgs -> - // logger.debug("RoomDebug") { - // "SQL: $sqlQuery, args: $bindArgs" - // } - }, - { it.run() } + databaseFile.absolutePath ) + .setDriver(BundledSQLiteDriver()) + val db = builder.build() .migrateLegacyCustomScanners(context) .migrateLegacySessions(context) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e2e118e..b5f1a5d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,6 +43,7 @@ rules = "1.7.0" paraphrase-plugin = "0.4.1" ksp = "2.3.6" protoc = "4.33.5" +androidx-sqlite = "2.6.2" [libraries] @@ -62,6 +63,7 @@ androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "d androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } +androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "androidx-sqlite" } retrofit-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" } koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" } From b9eed58e2fe702816f6443ff50b735bcf42081c7 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 16:11:38 +0200 Subject: [PATCH 16/26] Use KMP-compatible transaction methods --- .../ScanJobForegroundService.kt | 31 +++++----- .../data/ui/ScanningScreenViewModel.kt | 33 +++++----- .../scanbridge/stores/LegacySessionsStore.kt | 61 +++++++++++-------- 3 files changed, 70 insertions(+), 55 deletions(-) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt index 20567fb..cf574c6 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt @@ -12,7 +12,8 @@ import android.os.IBinder import androidx.compose.ui.graphics.asImageBitmap import androidx.core.app.NotificationCompat import androidx.lifecycle.application -import androidx.room.withTransaction +import androidx.room.immediateTransaction +import androidx.room.useWriterConnection import io.github.chrisimx.esclkt.ESCLHttpCallResult import io.github.chrisimx.esclkt.ESCLRequestClient import io.github.chrisimx.esclkt.JobState @@ -365,20 +366,22 @@ class ScanJobForegroundService : Service() { suspend fun addScan(sessionID: Uuid, path: String, settings: ScanSettings, rotation: ScanRelativeRotation) { Timber.d("Adding scan: $path, $rotation") - db.withTransaction { - val highestIdx = scannedPageDao.getHighestIdxForSession(sessionID) ?: -1 - - Timber.d("Inserting scan with index ${highestIdx + 1}") - scannedPageDao.insertAll( - ScannedPage( - Uuid.generateV4(), - sessionID, - path, - settings, - rotation, - highestIdx + 1 + db.useWriterConnection { + it.immediateTransaction { + val highestIdx = scannedPageDao.getHighestIdxForSession(sessionID) ?: -1 + + Timber.d("Inserting scan with index ${highestIdx + 1}") + scannedPageDao.insertAll( + ScannedPage( + Uuid.generateV4(), + sessionID, + path, + settings, + rotation, + highestIdx + 1 + ) ) - ) + } } } diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt index 3d88cc5..ec85458 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt @@ -29,7 +29,8 @@ import androidx.core.content.FileProvider import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.application import androidx.lifecycle.viewModelScope -import androidx.room.withTransaction +import androidx.room.immediateTransaction +import androidx.room.useWriterConnection import com.itextpdf.io.image.ImageDataFactory import com.itextpdf.kernel.geom.PageSize import com.itextpdf.kernel.pdf.PdfDocument @@ -321,13 +322,15 @@ class ScanningScreenViewModel( Timber.d("Stored session: $storedSession") val updateSettings: suspend (ScanSettings.() -> ScanSettings) -> Unit = { lambda -> - db.withTransaction { - val oldSession = sessionDao.getSessionById(sessionID) ?: return@withTransaction - val newSession = oldSession.copy( - currentScanSettings = oldSession.currentScanSettings?.lambda() - ) - Timber.d("Settings updated ${newSession.currentScanSettings}") - sessionDao.update(newSession) + db.useWriterConnection { + it.immediateTransaction { + val oldSession = sessionDao.getSessionById(sessionID) ?: return@immediateTransaction + val newSession = oldSession.copy( + currentScanSettings = oldSession.currentScanSettings?.lambda() + ) + Timber.d("Settings updated ${newSession.currentScanSettings}") + sessionDao.update(newSession) + } } } @@ -526,14 +529,16 @@ class ScanningScreenViewModel( val filePaths = mutableListOf() val tmpPaths = mutableListOf() - db.withTransaction { - val scannedPages = scannedPageDao.getAllForSession(sessionID) - val tmpFiles = tmpFileDao.getFilesBySessionId(sessionID) + db.useWriterConnection { + it.immediateTransaction { + val scannedPages = scannedPageDao.getAllForSession(sessionID) + val tmpFiles = tmpFileDao.getFilesBySessionId(sessionID) - filePaths += scannedPages.map { it.filePath } - tmpPaths += tmpFiles.map { it.path } + filePaths += scannedPages.map { it.filePath } + tmpPaths += tmpFiles.map { it.path } - sessionDao.deleteById(sessionID) + sessionDao.deleteById(sessionID) + } } withContext(Dispatchers.IO) { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt index 542f497..d989942 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt @@ -1,8 +1,8 @@ package io.github.chrisimx.scanbridge.stores import android.content.Context -import androidx.room.util.copy -import androidx.room.withTransaction +import androidx.room.immediateTransaction +import androidx.room.useWriterConnection import io.github.chrisimx.esclkt.ScannerCapabilities import io.github.chrisimx.scanbridge.data.model.LegacySessionV2 import io.github.chrisimx.scanbridge.data.model.LegacySessionV2.Companion.fromString @@ -18,8 +18,6 @@ import java.nio.file.Files import kotlin.concurrent.atomics.AtomicBoolean import kotlin.concurrent.atomics.ExperimentalAtomicApi import kotlin.io.path.Path -import kotlin.io.path.extension -import kotlin.io.path.nameWithoutExtension import kotlin.uuid.Uuid import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -84,29 +82,10 @@ object LegacySessionsStore { val sessionId = Uuid.parse(legacySession.sessionID) - db.withTransaction { - sessionDao().insertAll( - Session(sessionId, legacySession.scanSettings, null) - ) - - tmpFileDao().insertAllList( - legacySession.tmpFiles.map { - TempFile(ownerSessionId = sessionId, path = it) - } - ) - - scannedPageDao().insertAllList( - legacySession.scannedPages.mapIndexed { index, page -> - ScannedPage( - scanId = Uuid.generateV4(), - ownerSessionId = sessionId, - filePath = page.filePath, - originalScanSettings = page.originalScanSettings, - rotation = page.rotation, - orderIndex = index - ) - } - ) + db.useWriterConnection { + it.immediateTransaction { + db.insertLegacySessionData(sessionId, legacySession) + } } Files.deleteIfExists(sessionDir.resolve("$sessionIdString.session")) @@ -124,4 +103,32 @@ object LegacySessionsStore { return this } + + private suspend fun ScanBridgeDb.insertLegacySessionData( + sessionId: Uuid, + legacySession: LegacySessionV2 + ) { + sessionDao().insertAll( + Session(sessionId, legacySession.scanSettings, null) + ) + + tmpFileDao().insertAllList( + legacySession.tmpFiles.map { + TempFile(ownerSessionId = sessionId, path = it) + } + ) + + scannedPageDao().insertAllList( + legacySession.scannedPages.mapIndexed { index, page -> + ScannedPage( + scanId = Uuid.generateV4(), + ownerSessionId = sessionId, + filePath = page.filePath, + originalScanSettings = page.originalScanSettings, + rotation = page.rotation, + orderIndex = index + ) + } + ) + } } From 3d774fc34991a0551576a1d14248d2eb34b72b46 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 16:34:40 +0200 Subject: [PATCH 17/26] Fully migrate to KMP Room --- androidApp/build.gradle.kts | 9 +++--- .../scanbridge/ScanBridgeApplication.kt | 21 +++++--------- .../chrisimx/scanbridge/ScanSettings.kt | 2 +- .../ScanJobForegroundService.kt | 2 +- .../scanbridge/data/model/LegacySessionV2.kt | 2 +- .../ui/ScanSettingsComposableStateHolder.kt | 2 ++ .../data/ui/ScanSettingsStateData.kt | 21 -------------- .../scanbridge/data/ui/ScanningScreenData.kt | 10 ------- .../data/ui/ScanningScreenViewModel.kt | 3 ++ .../stores/DefaultScanSettingsStore.kt | 4 +-- .../scanbridge/stores/LegacySessionsStore.kt | 2 +- .../uicomponents/ValidatedTextField.kt | 3 +- core/build.gradle.kts | 25 +++++++++++++++- .../1.json | 0 .../2.json | 0 .../3.json | 0 .../4.json | 0 .../AndroidScanBridgeDbBuilderFactory.kt | 13 +++++++++ .../chrisimx/scanbridge}/ScanSettingsJson.kt | 2 +- .../chrisimx/scanbridge/db/ScanBridgeDb.kt | 0 .../db/ScanBridgeDbBuilderFactory.kt | 7 +++++ .../scanbridge/db/ScanBridgeDbFactory.kt | 19 ++++++++++++ .../scanbridge/db/daos/CustomScannerDao.kt | 0 .../db/daos/ExecutedMigrationsDao.kt | 0 .../scanbridge/db/daos/LastRouteDao.kt | 0 .../scanbridge/db/daos/ScannedPageDao.kt | 2 -- .../chrisimx/scanbridge/db/daos/SessionDao.kt | 2 +- .../scanbridge/db/daos/TempFileDao.kt | 0 .../scanbridge/db/entities/CustomScanner.kt | 0 .../db/entities/ExecutedMigrationToRoom.kt | 0 .../scanbridge/db/entities/LastRoute.kt | 0 .../scanbridge/db/entities/ScannedPage.kt | 2 +- .../scanbridge/db/entities/Session.kt | 2 +- .../scanbridge/db/entities/TempFile.kt | 0 .../ScanSettingsTypeConverter.kt | 2 +- .../ScanSettingsUiDataTypeConverter.kt | 4 +-- .../db/typeconverters/UrlTypeConverter.kt | 0 .../db/typeconverters/UuidTypeConverter.kt | 0 .../model/NumberValidationResult.kt | 10 +++++++ .../scanbridge/model/ScanRelativeRotation.kt | 11 +++++++ .../model/ScanSettingsEnterableData.kt | 17 +++++++++++ .../kotlin/IosScanBridgeDbBuilderFactory.kt | 29 +++++++++++++++++++ core/src/iosMain/kotlin/main.kt | 22 -------------- 43 files changed, 163 insertions(+), 87 deletions(-) rename {androidApp => core}/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json (100%) rename {androidApp => core}/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json (100%) rename {androidApp => core}/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json (100%) rename {androidApp => core}/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json (100%) create mode 100644 core/src/androidMain/kotlin/AndroidScanBridgeDbBuilderFactory.kt rename {androidApp/src/main/java/io/github/chrisimx/scanbridge/util => core/src/commonMain/kotlin/io/github/chrisimx/scanbridge}/ScanSettingsJson.kt (95%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt (100%) create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDbBuilderFactory.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDbFactory.kt rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt (96%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt (95%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt (93%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/entities/Session.kt (87%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/entities/TempFile.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt (91%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt (82%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt (100%) rename {androidApp/src/main/java => core/src/commonMain/kotlin}/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt (100%) create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/NumberValidationResult.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanRelativeRotation.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt create mode 100644 core/src/iosMain/kotlin/IosScanBridgeDbBuilderFactory.kt delete mode 100644 core/src/iosMain/kotlin/main.kt diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 470f94e..3782b48 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -38,10 +38,6 @@ android { generateLocaleConfig = true } - room { - schemaDirectory("$projectDir/schemas") - } - defaultConfig { applicationId = "io.github.chrisimx.scanbridge" minSdk = 28 @@ -94,9 +90,14 @@ kotlin { compilerOptions { jvmTarget = JvmTarget.JVM_17 optIn.add("kotlin.uuid.ExperimentalUuidApi") + freeCompilerArgs.add("-Xnon-local-break-continue") } } +room { + schemaDirectory("$projectDir/schemas") +} + dependencies { implementation(libs.koin.core) implementation(libs.koin.android) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt index 87e93db..0afcac5 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt @@ -1,5 +1,6 @@ package io.github.chrisimx.scanbridge +import AndroidScanBridgeDbBuilderFactory import android.app.Application import android.content.Context import androidx.datastore.core.DataStore @@ -38,24 +39,16 @@ import org.koin.plugin.module.dsl.single import org.koin.plugin.module.dsl.create import org.koin.plugin.module.dsl.viewModel import androidx.sqlite.driver.bundled.BundledSQLiteDriver +import io.github.chrisimx.scanbridge.db.DefaultScanBridgeDbFactory +import io.github.chrisimx.scanbridge.db.ScanBridgeDbBuilderFactory +import io.github.chrisimx.scanbridge.db.ScanBridgeDbFactory import timber.log.Timber fun createAppSettingsDataStore(context: Context) = context.appSettingsStore fun createShownMessagesDataStore(context: Context) = context.shownMessagesStore -fun createScanBridgeDb(context: Context): ScanBridgeDb { - val databaseFile = context.getDatabasePath("scanbridge") - val builder = Room.databaseBuilder( - context, - databaseFile.absolutePath - ) - .setDriver(BundledSQLiteDriver()) - - val db = builder.build() - .migrateLegacyCustomScanners(context) - .migrateLegacySessions(context) - - return db +fun createScanBridgeDb(factory: ScanBridgeDbFactory): ScanBridgeDb { + return factory.createInstance() } val appModule = module { single>(named()) { @@ -73,6 +66,8 @@ val appModule = module { single() single() bind MigrationExecutor::class includes(migrationsModule) + single() bind ScanBridgeDbBuilderFactory::class + single() bind ScanBridgeDbFactory::class single { create(::createScanBridgeDb) } diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt index e891892..fefdf13 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanSettings.kt @@ -56,9 +56,9 @@ import androidx.compose.ui.unit.dp import io.github.chrisimx.esclkt.DiscreteResolution import io.github.chrisimx.esclkt.SupportedResolutions import io.github.chrisimx.esclkt.equalsLength -import io.github.chrisimx.scanbridge.data.ui.NumberValidationResult import io.github.chrisimx.scanbridge.data.ui.ScanSettingsComposableStateHolder import io.github.chrisimx.scanbridge.data.ui.ScanSettingsLengthUnit +import io.github.chrisimx.scanbridge.model.NumberValidationResult import io.github.chrisimx.scanbridge.uicomponents.SizeBasedConditionalView import io.github.chrisimx.scanbridge.uicomponents.ValidatedDimensionsTextEdit import io.github.chrisimx.scanbridge.util.localizedString diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt index cf574c6..89f6415 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt @@ -21,10 +21,10 @@ import io.github.chrisimx.esclkt.ScanSettings import io.github.chrisimx.scanbridge.MainActivity import io.github.chrisimx.scanbridge.R import io.github.chrisimx.scanbridge.data.model.ScanJob -import io.github.chrisimx.scanbridge.data.ui.ScanRelativeRotation import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.daos.ScannedPageDao import io.github.chrisimx.scanbridge.db.entities.ScannedPage +import io.github.chrisimx.scanbridge.model.ScanRelativeRotation import io.github.chrisimx.scanbridge.services.ScanJobRepository import io.github.chrisimx.scanbridge.util.extractPdfImages import io.github.chrisimx.scanbridge.util.toJobStateString diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt index e56f1db..e1aa2c0 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/LegacySessionV2.kt @@ -4,7 +4,7 @@ import io.github.chrisimx.esclkt.ScanSettings import io.github.chrisimx.esclkt.ScannerCapabilities import io.github.chrisimx.esclkt.getInputSourceCaps import io.github.chrisimx.esclkt.getInputSourceOptions -import io.github.chrisimx.scanbridge.data.ui.ScanRelativeRotation +import io.github.chrisimx.scanbridge.model.ScanRelativeRotation import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import timber.log.Timber diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt index 2516d35..9d30d85 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt @@ -42,6 +42,8 @@ import io.github.chrisimx.esclkt.threeHundredthsOfInch import io.github.chrisimx.scanbridge.Locale import io.github.chrisimx.scanbridge.R import io.github.chrisimx.scanbridge.LocaleProvider +import io.github.chrisimx.scanbridge.model.NumberValidationResult +import io.github.chrisimx.scanbridge.model.ScanSettingsStateData import io.github.chrisimx.scanbridge.util.derived import io.github.chrisimx.scanbridge.util.getMaxResolution import io.github.chrisimx.scanbridge.util.toDoubleLocalized diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt index 9d6d16e..97c2d87 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt @@ -19,24 +19,3 @@ package io.github.chrisimx.scanbridge.data.ui -import io.github.chrisimx.esclkt.ScannerCapabilities -import io.github.chrisimx.scanbridge.PaperFormat -import io.github.chrisimx.scanbridge.loadDefaultFormats -import kotlinx.serialization.Serializable - -@Serializable -sealed class NumberValidationResult { - data class Success(val value: Double) : NumberValidationResult() - data class OutOfRange(val min: Double, val max: Double) : NumberValidationResult() - data object NotANumber : NumberValidationResult() -} - -@Serializable -data class ScanSettingsStateData( - val capabilities: ScannerCapabilities, - val paperFormats: List = loadDefaultFormats(), - val customMenuEnabled: Boolean = false, - val widthString: String = "", - val heightString: String = "", - val maximumSize: Boolean = true -) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt index 656d2cb..bcd6535 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt @@ -28,18 +28,8 @@ import io.github.chrisimx.esclkt.ScannerCapabilities import java.io.File import kotlin.uuid.Uuid -enum class ScanRelativeRotation { - Rotated, - Original -} - data class ErrorDescription(val pretext: Int?, val icon: Int?, val text: String?) -fun ScanRelativeRotation.toggleRotation() = when (this) { - ScanRelativeRotation.Rotated -> ScanRelativeRotation.Original - ScanRelativeRotation.Original -> ScanRelativeRotation.Rotated -} - data class ScanningScreenData( val esclClient: ESCLRequestClient, val sessionID: Uuid, diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt index ec85458..f83ae4c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt @@ -56,6 +56,9 @@ import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.entities.ScannedPage import io.github.chrisimx.scanbridge.db.entities.Session import io.github.chrisimx.scanbridge.db.entities.TempFile +import io.github.chrisimx.scanbridge.model.ScanRelativeRotation +import io.github.chrisimx.scanbridge.model.ScanSettingsStateData +import io.github.chrisimx.scanbridge.model.toggleRotation import io.github.chrisimx.scanbridge.proto.chunkSizePdfExportOrNull import io.github.chrisimx.scanbridge.services.ScanJobRepository import io.github.chrisimx.scanbridge.stores.DefaultScanSettingsStore diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt index a534ef4..2f23ad2 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt @@ -22,13 +22,13 @@ package io.github.chrisimx.scanbridge.stores import android.content.Context import com.google.protobuf.StringValue import io.github.chrisimx.esclkt.ScanSettings -import io.github.chrisimx.scanbridge.data.ui.ScanSettingsStateData import io.github.chrisimx.scanbridge.datastore.appSettingsStore import io.github.chrisimx.scanbridge.datastore.updateSettings import io.github.chrisimx.scanbridge.proto.lastUsedScanSettingsOrNull import io.github.chrisimx.scanbridge.proto.lastUsedScanSettingsUiStateOrNull import io.github.chrisimx.scanbridge.proto.rememberScanSettingsOrNull -import io.github.chrisimx.scanbridge.util.ScanSettingsJson +import io.github.chrisimx.scanbridge.ScanSettingsJson +import io.github.chrisimx.scanbridge.model.ScanSettingsStateData import kotlinx.coroutines.flow.first import timber.log.Timber diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt index d989942..8650a12 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt @@ -12,7 +12,7 @@ import io.github.chrisimx.scanbridge.db.entities.ScannedPage import io.github.chrisimx.scanbridge.db.entities.Session import io.github.chrisimx.scanbridge.db.entities.TempFile import io.github.chrisimx.scanbridge.proto.copy -import io.github.chrisimx.scanbridge.util.ScanSettingsJson +import io.github.chrisimx.scanbridge.ScanSettingsJson import java.io.File import java.nio.file.Files import kotlin.concurrent.atomics.AtomicBoolean diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt index 88ea65b..89a869c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/ValidatedTextField.kt @@ -28,7 +28,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.KeyboardType import io.github.chrisimx.scanbridge.R -import io.github.chrisimx.scanbridge.data.ui.NumberValidationResult +import io.github.chrisimx.scanbridge.model.NumberValidationResult + fun NumberValidationResult.toHumanString(context: Context): String = when (this) { is NumberValidationResult.OutOfRange -> context.getString(R.string.error_state_not_in_allowed_range) NumberValidationResult.NotANumber -> context.getString(R.string.error_state_not_a_valid_number) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 114dbd3..7b399e7 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -7,6 +7,15 @@ plugins { alias(libs.plugins.android.kmp.library) alias(libs.plugins.koin) alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.ksp) + alias(libs.plugins.room) +} + +kotlin { + compilerOptions { + optIn.add("kotlin.uuid.ExperimentalUuidApi") + freeCompilerArgs.add("-Xnon-local-break-continue") + } } kotlin { @@ -27,7 +36,6 @@ kotlin { } } - iosArm64() iosSimulatorArm64() @@ -39,6 +47,10 @@ kotlin { api(libs.kotlinx.coroutines) api(libs.kotlinx.serialization.json) api(libs.esclkt) + + // Room deps + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.sqlite.bundled) } commonTest.dependencies { @@ -65,3 +77,14 @@ kotlin { } } } + +room { + schemaDirectory("$projectDir/schemas") +} + +dependencies { + add("kspAndroid", libs.androidx.room.compiler) + add("kspJvm", libs.androidx.room.compiler) + add("kspIosSimulatorArm64", libs.androidx.room.compiler) + add("kspIosArm64", libs.androidx.room.compiler) +} diff --git a/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json b/core/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json similarity index 100% rename from androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json rename to core/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/1.json diff --git a/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json b/core/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json similarity index 100% rename from androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json rename to core/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/2.json diff --git a/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json b/core/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json similarity index 100% rename from androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json rename to core/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/3.json diff --git a/androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json b/core/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json similarity index 100% rename from androidApp/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json rename to core/schemas/io.github.chrisimx.scanbridge.db.ScanBridgeDb/4.json diff --git a/core/src/androidMain/kotlin/AndroidScanBridgeDbBuilderFactory.kt b/core/src/androidMain/kotlin/AndroidScanBridgeDbBuilderFactory.kt new file mode 100644 index 0000000..fa28549 --- /dev/null +++ b/core/src/androidMain/kotlin/AndroidScanBridgeDbBuilderFactory.kt @@ -0,0 +1,13 @@ +import android.content.Context +import androidx.room.Room +import androidx.room.RoomDatabase +import io.github.chrisimx.scanbridge.db.ScanBridgeDbBuilderFactory +import io.github.chrisimx.scanbridge.db.ScanBridgeDb + +class AndroidScanBridgeDbBuilderFactory(private val context: Context) : ScanBridgeDbBuilderFactory { + override fun getBuilder(): RoomDatabase.Builder { + val databaseFile = context.getDatabasePath("scanbridge") + val builder = Room.databaseBuilder(context, databaseFile.absolutePath) + return builder + } +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ScanSettingsJson.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanSettingsJson.kt similarity index 95% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ScanSettingsJson.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanSettingsJson.kt index 9b1ff20..7a320ea 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/ScanSettingsJson.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanSettingsJson.kt @@ -1,4 +1,4 @@ -package io.github.chrisimx.scanbridge.util +package io.github.chrisimx.scanbridge import io.github.chrisimx.esclkt.Inches import io.github.chrisimx.esclkt.LengthUnit diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDbBuilderFactory.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDbBuilderFactory.kt new file mode 100644 index 0000000..8f8866f --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDbBuilderFactory.kt @@ -0,0 +1,7 @@ +package io.github.chrisimx.scanbridge.db + +import androidx.room.RoomDatabase + +interface ScanBridgeDbBuilderFactory { + fun getBuilder(): RoomDatabase.Builder +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDbFactory.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDbFactory.kt new file mode 100644 index 0000000..5980bea --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDbFactory.kt @@ -0,0 +1,19 @@ +package io.github.chrisimx.scanbridge.db + +import androidx.sqlite.driver.bundled.BundledSQLiteDriver +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO + +interface ScanBridgeDbFactory { + fun createInstance(): ScanBridgeDb +} + +class DefaultScanBridgeDbFactory(val builderFactory: ScanBridgeDbBuilderFactory) : ScanBridgeDbFactory { + override fun createInstance(): ScanBridgeDb { + val dbBuilder = builderFactory.getBuilder() + return dbBuilder + .setDriver(BundledSQLiteDriver()) + .setQueryCoroutineContext(Dispatchers.IO) + .build() + } +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/CustomScannerDao.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/ExecutedMigrationsDao.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/LastRouteDao.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt similarity index 96% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt index d4ea1a3..c9786d7 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/ScannedPageDao.kt @@ -9,7 +9,6 @@ import androidx.room.Update import io.github.chrisimx.scanbridge.db.entities.ScannedPage import kotlin.uuid.Uuid import kotlinx.coroutines.flow.Flow -import timber.log.Timber @Dao interface ScannedPageDao { @@ -40,7 +39,6 @@ interface ScannedPageDao { val page2 = getByScanId(page2.scanId) if (page1 == null || page2 == null) { - Timber.e("Could not swap pages: $page1, $page2") return } diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt similarity index 95% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt index 590e036..84832ca 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt @@ -5,8 +5,8 @@ import androidx.room.Delete import androidx.room.Insert import androidx.room.Query import androidx.room.Update -import io.github.chrisimx.scanbridge.data.ui.ScanSettingsStateData import io.github.chrisimx.scanbridge.db.entities.Session +import io.github.chrisimx.scanbridge.model.ScanSettingsStateData import kotlin.uuid.Uuid import kotlinx.coroutines.flow.Flow diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/TempFileDao.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/CustomScanner.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt similarity index 93% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt index 2c1da1c..77601bb 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ScannedPage.kt @@ -5,7 +5,7 @@ import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey import io.github.chrisimx.esclkt.ScanSettings -import io.github.chrisimx.scanbridge.data.ui.ScanRelativeRotation +import io.github.chrisimx.scanbridge.model.ScanRelativeRotation import kotlin.uuid.Uuid @Entity( diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/Session.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/Session.kt similarity index 87% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/Session.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/Session.kt index d2161d5..822cd8c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/Session.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/Session.kt @@ -4,7 +4,7 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey import io.github.chrisimx.esclkt.ScanSettings -import io.github.chrisimx.scanbridge.data.ui.ScanSettingsStateData +import io.github.chrisimx.scanbridge.model.ScanSettingsStateData import kotlin.uuid.Uuid @Entity(tableName = "sessions") diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/TempFile.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/TempFile.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/entities/TempFile.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/TempFile.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt similarity index 91% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt index bb0dcc9..761d284 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsTypeConverter.kt @@ -2,7 +2,7 @@ package io.github.chrisimx.scanbridge.db.typeconverters import androidx.room.TypeConverter import io.github.chrisimx.esclkt.ScanSettings -import io.github.chrisimx.scanbridge.util.ScanSettingsJson +import io.github.chrisimx.scanbridge.ScanSettingsJson class ScanSettingsTypeConverter { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt similarity index 82% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt index 293b59a..9128451 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt @@ -1,8 +1,8 @@ package io.github.chrisimx.scanbridge.db.typeconverters import androidx.room.TypeConverter -import io.github.chrisimx.scanbridge.data.ui.ScanSettingsStateData -import io.github.chrisimx.scanbridge.util.ScanSettingsJson +import io.github.chrisimx.scanbridge.ScanSettingsJson +import io.github.chrisimx.scanbridge.model.ScanSettingsStateData class ScanSettingsUiDataTypeConverter { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/UrlTypeConverter.kt diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/UuidTypeConverter.kt diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/NumberValidationResult.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/NumberValidationResult.kt new file mode 100644 index 0000000..d844062 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/NumberValidationResult.kt @@ -0,0 +1,10 @@ +package io.github.chrisimx.scanbridge.model + +import kotlinx.serialization.Serializable + +@Serializable +sealed class NumberValidationResult { + data class Success(val value: Double) : NumberValidationResult() + data class OutOfRange(val min: Double, val max: Double) : NumberValidationResult() + data object NotANumber : NumberValidationResult() +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanRelativeRotation.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanRelativeRotation.kt new file mode 100644 index 0000000..559218e --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanRelativeRotation.kt @@ -0,0 +1,11 @@ +package io.github.chrisimx.scanbridge.model + +enum class ScanRelativeRotation { + Rotated, + Original +} + +fun ScanRelativeRotation.toggleRotation() = when (this) { + ScanRelativeRotation.Rotated -> ScanRelativeRotation.Original + ScanRelativeRotation.Original -> ScanRelativeRotation.Rotated +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt new file mode 100644 index 0000000..70e5fb5 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt @@ -0,0 +1,17 @@ +package io.github.chrisimx.scanbridge.model + +import io.github.chrisimx.esclkt.ScannerCapabilities +import io.github.chrisimx.scanbridge.PaperFormat +import io.github.chrisimx.scanbridge.loadDefaultFormats +import kotlinx.serialization.Serializable + + +@Serializable +data class ScanSettingsStateData( + val capabilities: ScannerCapabilities, + val paperFormats: List = loadDefaultFormats(), + val customMenuEnabled: Boolean = false, + val widthString: String = "", + val heightString: String = "", + val maximumSize: Boolean = true +) diff --git a/core/src/iosMain/kotlin/IosScanBridgeDbBuilderFactory.kt b/core/src/iosMain/kotlin/IosScanBridgeDbBuilderFactory.kt new file mode 100644 index 0000000..3e49642 --- /dev/null +++ b/core/src/iosMain/kotlin/IosScanBridgeDbBuilderFactory.kt @@ -0,0 +1,29 @@ +import androidx.room.Room +import androidx.room.RoomDatabase +import io.github.chrisimx.scanbridge.db.ScanBridgeDb +import io.github.chrisimx.scanbridge.db.ScanBridgeDbBuilderFactory +import kotlinx.cinterop.ExperimentalForeignApi +import platform.Foundation.NSDocumentDirectory +import platform.Foundation.NSFileManager +import platform.Foundation.NSUserDomainMask + +class IosScanBridgeDbBuilderFactory : ScanBridgeDbBuilderFactory { + override fun getBuilder(): RoomDatabase.Builder { + val dbFilePath = documentDirectory() + "/scanbridge.db" + return Room.databaseBuilder( + name = dbFilePath, + ) + } + + @OptIn(ExperimentalForeignApi::class) + private fun documentDirectory(): String { + val documentDirectory = NSFileManager.defaultManager.URLForDirectory( + directory = NSDocumentDirectory, + inDomain = NSUserDomainMask, + appropriateForURL = null, + create = false, + error = null, + ) + return requireNotNull(documentDirectory?.path) + } +} diff --git a/core/src/iosMain/kotlin/main.kt b/core/src/iosMain/kotlin/main.kt deleted file mode 100644 index 2d86d9b..0000000 --- a/core/src/iosMain/kotlin/main.kt +++ /dev/null @@ -1,22 +0,0 @@ -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.window.ComposeUIViewController -import io.github.chrisimx.scanbridge.App -import platform.UIKit.UIApplication -import platform.UIKit.UIStatusBarStyleDarkContent -import platform.UIKit.UIStatusBarStyleLightContent -import platform.UIKit.UIViewController -import platform.UIKit.setStatusBarStyle - -fun MainViewController(): UIViewController = ComposeUIViewController { - App(onThemeChanged = { ThemeChanged(it) }) -} - -@Composable -private fun ThemeChanged(isDark: Boolean) { - LaunchedEffect(isDark) { - UIApplication.sharedApplication.setStatusBarStyle( - if (isDark) UIStatusBarStyleDarkContent else UIStatusBarStyleLightContent - ) - } -} From 42df48e40e7e3bb17dbd36c11b0da3f382bd99df Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 16:40:52 +0200 Subject: [PATCH 18/26] Move ScanJob and DiscoveredScanner to core because they are platform independent --- .../main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt | 1 + .../io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt | 3 +-- .../main/java/io/github/chrisimx/scanbridge/StartupScreen.kt | 1 + .../scanbridge/androidservice/ScanJobForegroundService.kt | 2 +- .../chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt | 3 ++- .../github/chrisimx/scanbridge/services/ScanJobRepository.kt | 2 +- .../io/github/chrisimx/scanbridge/model/DiscoveredScanner.kt | 3 +++ .../kotlin/io/github/chrisimx/scanbridge}/model/ScanJob.kt | 2 +- 8 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/DiscoveredScanner.kt rename {androidApp/src/main/java/io/github/chrisimx/scanbridge/data => core/src/commonMain/kotlin/io/github/chrisimx/scanbridge}/model/ScanJob.kt (83%) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt index 7030942..19995dd 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt @@ -48,6 +48,7 @@ import androidx.navigation.NavController import io.github.chrisimx.scanbridge.data.model.EditedCustomScanner import io.github.chrisimx.scanbridge.data.ui.CustomScannerViewModel import io.github.chrisimx.scanbridge.db.entities.CustomScanner +import io.github.chrisimx.scanbridge.model.DiscoveredScanner import io.github.chrisimx.scanbridge.uicomponents.FoundScannerItem import io.github.chrisimx.scanbridge.uicomponents.FullScreenError import io.github.chrisimx.scanbridge.uicomponents.dialog.CustomScannerDialog diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt index 256e5ef..19ba558 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt @@ -24,6 +24,7 @@ import android.net.nsd.NsdServiceInfo import android.os.Build import android.os.ext.SdkExtensions import androidx.compose.runtime.snapshots.SnapshotStateMap +import io.github.chrisimx.scanbridge.model.DiscoveredScanner import io.ktor.http.URLBuilder import io.ktor.http.URLProtocol import io.ktor.http.Url @@ -35,8 +36,6 @@ import timber.log.Timber private const val TAG = "ScannerDiscovery" -data class DiscoveredScanner(val name: String, val addresses: List) - class ScannerDiscovery( val nsdManager: NsdManager, val isSecure: Boolean, diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt index 0323e20..76685de 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/StartupScreen.kt @@ -50,6 +50,7 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.navigation.NavController import io.github.chrisimx.scanbridge.data.model.EditedCustomScanner +import io.github.chrisimx.scanbridge.model.DiscoveredScanner import timber.log.Timber @OptIn(ExperimentalMaterial3Api::class) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt index 89f6415..2e3b1a2 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt @@ -20,7 +20,7 @@ import io.github.chrisimx.esclkt.JobState import io.github.chrisimx.esclkt.ScanSettings import io.github.chrisimx.scanbridge.MainActivity import io.github.chrisimx.scanbridge.R -import io.github.chrisimx.scanbridge.data.model.ScanJob +import io.github.chrisimx.scanbridge.model.ScanJob import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.daos.ScannedPageDao import io.github.chrisimx.scanbridge.db.entities.ScannedPage diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt index f83ae4c..2077ad5 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt @@ -56,6 +56,7 @@ import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.entities.ScannedPage import io.github.chrisimx.scanbridge.db.entities.Session import io.github.chrisimx.scanbridge.db.entities.TempFile +import io.github.chrisimx.scanbridge.model.ScanJob import io.github.chrisimx.scanbridge.model.ScanRelativeRotation import io.github.chrisimx.scanbridge.model.ScanSettingsStateData import io.github.chrisimx.scanbridge.model.toggleRotation @@ -516,7 +517,7 @@ class ScanningScreenViewModel( return@launch } - val scanJob = io.github.chrisimx.scanbridge.data.model.ScanJob( + val scanJob = ScanJob( Uuid.generateV4(), sessionID, currentSettings, diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt index d9962c2..703127a 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/ScanJobRepository.kt @@ -1,6 +1,6 @@ package io.github.chrisimx.scanbridge.services -import io.github.chrisimx.scanbridge.data.model.ScanJob +import io.github.chrisimx.scanbridge.model.ScanJob import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.BufferOverflow diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/DiscoveredScanner.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/DiscoveredScanner.kt new file mode 100644 index 0000000..4bdbfe8 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/DiscoveredScanner.kt @@ -0,0 +1,3 @@ +package io.github.chrisimx.scanbridge.model + +data class DiscoveredScanner(val name: String, val addresses: List) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/ScanJob.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanJob.kt similarity index 83% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/ScanJob.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanJob.kt index 47f30b4..53afbe8 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/model/ScanJob.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanJob.kt @@ -1,4 +1,4 @@ -package io.github.chrisimx.scanbridge.data.model +package io.github.chrisimx.scanbridge.model import io.github.chrisimx.esclkt.ESCLRequestClient import io.github.chrisimx.esclkt.ScanSettings From 2b594f09694e75bb090ec046b63fd91935a2634d Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Thu, 9 Apr 2026 16:54:14 +0200 Subject: [PATCH 19/26] Refactor ScanJob to be pure domain model --- .../chrisimx/scanbridge/model/HttpClientConfig.kt | 7 +++++++ .../io/github/chrisimx/scanbridge/model/ScanJob.kt | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/HttpClientConfig.kt diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/HttpClientConfig.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/HttpClientConfig.kt new file mode 100644 index 0000000..0064e1b --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/HttpClientConfig.kt @@ -0,0 +1,7 @@ +package io.github.chrisimx.scanbridge.model + +data class HttpClientConfig( + val disableCertValidation: Boolean, + val debugLogging: Boolean, + val timeoutInSeconds: ULong +) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanJob.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanJob.kt index 53afbe8..b4aa256 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanJob.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanJob.kt @@ -1,7 +1,13 @@ package io.github.chrisimx.scanbridge.model -import io.github.chrisimx.esclkt.ESCLRequestClient import io.github.chrisimx.esclkt.ScanSettings +import io.ktor.http.Url import kotlin.uuid.Uuid -data class ScanJob(val jobID: Uuid, val ownerSessionId: Uuid, val scanSettings: ScanSettings, val esclClient: ESCLRequestClient) +data class ScanJob( + val jobID: Uuid, + val ownerSessionId: Uuid, + val scanSettings: ScanSettings, + val scannerBaseUrl: Url, + val httpClientConfig: HttpClientConfig +) From c68dcf49701169b68c577139fde7371d404969fe Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Sat, 11 Apr 2026 12:43:27 +0200 Subject: [PATCH 20/26] Move LoggerFactory, ZipService, HttpClientFactory and other things to core. --- androidApp/build.gradle.kts | 3 +- .../scanbridge/ScanBridgeApplication.kt | 10 ++- .../ScanJobForegroundService.kt | 9 ++- .../ui/ScanSettingsComposableStateHolder.kt | 4 +- .../scanbridge/data/ui/ScanningScreenData.kt | 3 - .../data/ui/ScanningScreenViewModel.kt | 62 ++++++++----------- .../migrations/RoomBackedMigrationExecutor.kt | 10 ++- .../services/AndroidLocaleProvider.kt | 4 +- core/build.gradle.kts | 3 + .../kotlin/AndroidHttpClientFactory.kt | 39 ++++++++++++ .../kotlin}/TrustAllTrustManager.kt | 0 .../chrisimx/scanbridge/LocaleProvider.kt | 17 ----- .../KmLogScanBridgeLogger.kt | 18 +----- .../KmLogScanBridgeLoggerFactory.kt | 17 +++++ .../chrisimx/scanbridge/model/Locale.kt | 8 +++ .../scanbridge/model/ScanBridgeFile.kt | 9 +++ .../scanbridge/ports/HttpClientFactory.kt | 8 +++ .../scanbridge/ports/LocaleProvider.kt | 11 ++++ .../{ => ports}/ScanBridgeLogger.kt | 2 +- .../ports/ScanBridgeLoggerFactory.kt | 10 +++ .../chrisimx/scanbridge/ports/ZipService.kt | 7 +++ gradle/libs.versions.toml | 4 +- 22 files changed, 174 insertions(+), 84 deletions(-) create mode 100644 core/src/androidMain/kotlin/AndroidHttpClientFactory.kt rename {androidApp/src/main/java/io/github/chrisimx/scanbridge/util => core/src/androidMain/kotlin}/TrustAllTrustManager.kt (100%) delete mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LocaleProvider.kt rename core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/{ => infrastructure}/KmLogScanBridgeLogger.kt (60%) create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLoggerFactory.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/Locale.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanBridgeFile.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/HttpClientFactory.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/LocaleProvider.kt rename core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/{ => ports}/ScanBridgeLogger.kt (94%) create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLoggerFactory.kt create mode 100644 core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ZipService.kt diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 3782b48..3aa8367 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -1,4 +1,3 @@ -import com.android.utils.TraceUtils.simpleId import java.util.* import org.jetbrains.kotlin.gradle.dsl.JvmTarget @@ -134,7 +133,7 @@ dependencies { implementation(libs.androidx.material.icons.core) implementation(libs.androidx.constraintlayout.compose) implementation(libs.itext7.core) - implementation(libs.ktor.okhttp) + implementation(libs.ktor.client.okhttp) implementation(libs.ktor.logging) "playImplementation"(project(":lvl_library")) "playImplementation"(libs.retrofit) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt index 0afcac5..10312ce 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt @@ -1,5 +1,6 @@ package io.github.chrisimx.scanbridge +import AndroidHttpClientFactory import AndroidScanBridgeDbBuilderFactory import android.app.Application import android.content.Context @@ -42,6 +43,12 @@ import androidx.sqlite.driver.bundled.BundledSQLiteDriver import io.github.chrisimx.scanbridge.db.DefaultScanBridgeDbFactory import io.github.chrisimx.scanbridge.db.ScanBridgeDbBuilderFactory import io.github.chrisimx.scanbridge.db.ScanBridgeDbFactory +import io.github.chrisimx.scanbridge.infrastructure.KmLogScanBridgeLogger +import io.github.chrisimx.scanbridge.infrastructure.KmLogScanBridgeLoggerFactory +import io.github.chrisimx.scanbridge.ports.HttpClientFactory +import io.github.chrisimx.scanbridge.ports.LocaleProvider +import io.github.chrisimx.scanbridge.ports.ScanBridgeLogger +import io.github.chrisimx.scanbridge.ports.ScanBridgeLoggerFactory import timber.log.Timber fun createAppSettingsDataStore(context: Context) = context.appSettingsStore @@ -62,7 +69,8 @@ val appModule = module { single { FileDebugLogService(get(named()),get()) } bind DebugLogService::class - factory() bind ScanBridgeLogger::class + single() bind HttpClientFactory::class + single() bind ScanBridgeLoggerFactory::class single() single() bind MigrationExecutor::class includes(migrationsModule) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt index 2e3b1a2..dc0858d 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt @@ -25,6 +25,7 @@ import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.daos.ScannedPageDao import io.github.chrisimx.scanbridge.db.entities.ScannedPage import io.github.chrisimx.scanbridge.model.ScanRelativeRotation +import io.github.chrisimx.scanbridge.ports.HttpClientFactory import io.github.chrisimx.scanbridge.services.ScanJobRepository import io.github.chrisimx.scanbridge.util.extractPdfImages import io.github.chrisimx.scanbridge.util.toJobStateString @@ -64,6 +65,9 @@ class ScanJobForegroundService : Service() { } private val scanJobs: ScanJobRepository by inject() + + private val httpClientFactory: HttpClientFactory by inject() + private val db: ScanBridgeDb by inject() private val scannedPageDao: ScannedPageDao = db.scannedPageDao() @@ -166,7 +170,10 @@ class ScanJobForegroundService : Service() { private suspend fun doScan(scanJob: ScanJob) { val currentScanSettings = scanJob.scanSettings - val esclRequestClient = scanJob.esclClient + val esclRequestClient = ESCLRequestClient( + scanJob.scannerBaseUrl, + httpClientFactory.create(scanJob.httpClientConfig) + ) scanJobs.notifyStarted(scanJob) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt index 9d30d85..72ca9d4 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt @@ -39,9 +39,9 @@ import io.github.chrisimx.esclkt.inches import io.github.chrisimx.esclkt.millimeters import io.github.chrisimx.esclkt.scanRegion import io.github.chrisimx.esclkt.threeHundredthsOfInch -import io.github.chrisimx.scanbridge.Locale +import io.github.chrisimx.scanbridge.model.Locale import io.github.chrisimx.scanbridge.R -import io.github.chrisimx.scanbridge.LocaleProvider +import io.github.chrisimx.scanbridge.ports.LocaleProvider import io.github.chrisimx.scanbridge.model.NumberValidationResult import io.github.chrisimx.scanbridge.model.ScanSettingsStateData import io.github.chrisimx.scanbridge.util.derived diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt index bcd6535..9e9367c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt @@ -31,7 +31,6 @@ import kotlin.uuid.Uuid data class ErrorDescription(val pretext: Int?, val icon: Int?, val text: String?) data class ScanningScreenData( - val esclClient: ESCLRequestClient, val sessionID: Uuid, val confirmDialogShown: MutableState = mutableStateOf(false), val confirmPageDeleteDialogShown: MutableState = mutableStateOf(false), @@ -48,7 +47,6 @@ data class ScanningScreenData( val isRotating: MutableState = mutableStateOf(false) ) { fun toImmutable() = ImmutableScanningScreenData( - esclClient, sessionID, confirmDialogShown, confirmPageDeleteDialogShown, @@ -67,7 +65,6 @@ data class ScanningScreenData( } data class ImmutableScanningScreenData( - val esclClient: ESCLRequestClient, val sessionID: Uuid, private val confirmDialogShownState: State, private val confirmPageDeleteDialogShownState: State, diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt index 2077ad5..c08051c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt @@ -56,10 +56,12 @@ import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.entities.ScannedPage import io.github.chrisimx.scanbridge.db.entities.Session import io.github.chrisimx.scanbridge.db.entities.TempFile +import io.github.chrisimx.scanbridge.model.HttpClientConfig import io.github.chrisimx.scanbridge.model.ScanJob import io.github.chrisimx.scanbridge.model.ScanRelativeRotation import io.github.chrisimx.scanbridge.model.ScanSettingsStateData import io.github.chrisimx.scanbridge.model.toggleRotation +import io.github.chrisimx.scanbridge.ports.HttpClientFactory import io.github.chrisimx.scanbridge.proto.chunkSizePdfExportOrNull import io.github.chrisimx.scanbridge.services.ScanJobRepository import io.github.chrisimx.scanbridge.stores.DefaultScanSettingsStore @@ -108,49 +110,22 @@ enum class ScanningScreenEvent { class ScanningScreenViewModel( @InjectedParam - address: Url, + val address: Url, @InjectedParam - timeout: UInt, + val timeout: UInt, @InjectedParam - withDebugInterceptor: Boolean, + val withDebugInterceptor: Boolean, @InjectedParam - certificateValidationDisabled: Boolean, + val certificateValidationDisabled: Boolean, @InjectedParam val sessionID: Uuid, val db: ScanBridgeDb, application: Application, - val scanJobRepo: ScanJobRepository + val scanJobRepo: ScanJobRepository, + val httpClientFactory: HttpClientFactory ) : AndroidViewModel(application) { private val _scanningScreenData = ScanningScreenData( - ESCLRequestClient( - address, - HttpClient(OkHttp) { - install(HttpTimeout) { - requestTimeoutMillis = timeout.toLong() * 1000 - connectTimeoutMillis = timeout.toLong() * 1000 - socketTimeoutMillis = timeout.toLong() * 1000 - } - if (withDebugInterceptor) { - install(Logging) { - logger = object : Logger { - override fun log(message: String) { - Timber.tag("ESCLRequestClient").d(message) - } - } - } - } - if (certificateValidationDisabled) { - engine { - config { - val (socketFactory, trustManager) = getTrustAllTM() - sslSocketFactory(socketFactory, trustManager) - hostnameVerifier { _, _ -> true } - } - } - } - } - ), sessionID ) val scanningScreenData: ImmutableScanningScreenData @@ -521,7 +496,12 @@ class ScanningScreenViewModel( Uuid.generateV4(), sessionID, currentSettings, - _scanningScreenData.esclClient + address, + HttpClientConfig( + certificateValidationDisabled, + withDebugInterceptor, + timeout.toULong() + ) ) scanJobRepo.enqueue(scanJob) ScanJobForegroundService.startService(application) @@ -778,8 +758,20 @@ class ScanningScreenViewModel( } } + fun createHttpClientConfig() = HttpClientConfig( + certificateValidationDisabled, + withDebugInterceptor, + timeout.toULong() + ) + fun retrieveScannerCapabilities() = viewModelScope.launch { - val esclClient = scanningScreenData.esclClient + val httpClient = httpClientFactory.create( + createHttpClientConfig() + ) + val esclClient = ESCLRequestClient( + address, + httpClient + ) val scannerCapabilitiesResult = esclClient.getScannerCapabilities() diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt index 44508eb..2df0914 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt @@ -2,15 +2,19 @@ package io.github.chrisimx.scanbridge.migrations import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.entities.ExecutedMigrationToRoom -import io.github.chrisimx.scanbridge.logger +import io.github.chrisimx.scanbridge.ports.ScanBridgeLoggerFactory import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.koin.core.scope.Scope import org.koin.mp.KoinPlatform.getKoin -class RoomBackedMigrationExecutor(val db: ScanBridgeDb) : MigrationExecutor { - val logger by logger() +class RoomBackedMigrationExecutor( + val db: ScanBridgeDb, + loggerFactory: ScanBridgeLoggerFactory +) : MigrationExecutor { + val logger = loggerFactory.withClass(this::class) val executedMigrationsDao = db.executedMigrationsDao() + override suspend fun runMigrations() { val migrations = getKoin().getAll() diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt index 1014806..7b262da 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/services/AndroidLocaleProvider.kt @@ -1,8 +1,8 @@ package io.github.chrisimx.scanbridge.services import android.annotation.SuppressLint -import io.github.chrisimx.scanbridge.Locale -import io.github.chrisimx.scanbridge.LocaleProvider +import io.github.chrisimx.scanbridge.model.Locale +import io.github.chrisimx.scanbridge.ports.LocaleProvider import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 7b399e7..f53b24e 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -46,6 +46,8 @@ kotlin { api(libs.koin.annotations) api(libs.kotlinx.coroutines) api(libs.kotlinx.serialization.json) + api(libs.ktor.client.core) + api(libs.ktor.logging) api(libs.esclkt) // Room deps @@ -58,6 +60,7 @@ kotlin { } androidMain.dependencies { + api(libs.ktor.client.okhttp) } jvmMain.dependencies { diff --git a/core/src/androidMain/kotlin/AndroidHttpClientFactory.kt b/core/src/androidMain/kotlin/AndroidHttpClientFactory.kt new file mode 100644 index 0000000..dae4a62 --- /dev/null +++ b/core/src/androidMain/kotlin/AndroidHttpClientFactory.kt @@ -0,0 +1,39 @@ +import io.github.chrisimx.scanbridge.model.HttpClientConfig +import io.github.chrisimx.scanbridge.ports.HttpClientFactory +import io.github.chrisimx.scanbridge.ports.ScanBridgeLoggerFactory +import io.ktor.client.HttpClient +import io.ktor.client.engine.okhttp.OkHttp +import io.ktor.client.plugins.HttpTimeout +import io.ktor.client.plugins.logging.Logger +import io.ktor.client.plugins.logging.Logging + +class AndroidHttpClientFactory(loggerFactory: ScanBridgeLoggerFactory): HttpClientFactory { + val httpClientLogger = loggerFactory.withTag("AndroidHttpClient") + + override fun create(config: HttpClientConfig): HttpClient = + HttpClient(OkHttp) { + install(HttpTimeout) { + requestTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 + connectTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 + socketTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 + } + if (config.debugLogging) { + install(Logging) { + logger = object : Logger { + override fun log(message: String) { + httpClientLogger.debug { message } + } + } + } + } + if (config.disableCertValidation) { + engine { + config { + val (socketFactory, trustManager) = getTrustAllTM() + sslSocketFactory(socketFactory, trustManager) + hostnameVerifier { _, _ -> true } + } + } + } + } +} diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/util/TrustAllTrustManager.kt b/core/src/androidMain/kotlin/TrustAllTrustManager.kt similarity index 100% rename from androidApp/src/main/java/io/github/chrisimx/scanbridge/util/TrustAllTrustManager.kt rename to core/src/androidMain/kotlin/TrustAllTrustManager.kt diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LocaleProvider.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LocaleProvider.kt deleted file mode 100644 index d7c060e..0000000 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/LocaleProvider.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.chrisimx.scanbridge - -import kotlinx.coroutines.flow.StateFlow - -data class Locale( - /** - * The two character country code in uppercase - */ - val country: String -) - -/** - * Provides the currently selected [Locale] as a reactive stream. - */ -interface LocaleProvider { - val locale: StateFlow -} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/KmLogScanBridgeLogger.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLogger.kt similarity index 60% rename from core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/KmLogScanBridgeLogger.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLogger.kt index 1541580..41b1de6 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/KmLogScanBridgeLogger.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLogger.kt @@ -1,12 +1,10 @@ -package io.github.chrisimx.scanbridge +package io.github.chrisimx.scanbridge.infrastructure import com.diamondedge.logging.KmLog import com.diamondedge.logging.logging -import org.koin.core.annotation.InjectedParam -import org.koin.mp.KoinPlatform.getKoin +import io.github.chrisimx.scanbridge.ports.ScanBridgeLogger class KmLogScanBridgeLogger( - @InjectedParam tag: String ) : ScanBridgeLogger { private val logger: KmLog = logging(tag) @@ -35,15 +33,3 @@ class KmLogScanBridgeLogger( logger.e(t, tag, msg) } } - -inline fun org.koin.core.scope.Scope.logger(): ScanBridgeLogger { - val tag = T::class.simpleName ?: "Unknown" - return get { org.koin.core.parameter.parametersOf(tag) } -} - -inline fun logger() = lazy { - val koin = getKoin() - koin.get { - org.koin.core.parameter.parametersOf(T::class.simpleName ?: "Unknown") - } -} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLoggerFactory.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLoggerFactory.kt new file mode 100644 index 0000000..0e562d3 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLoggerFactory.kt @@ -0,0 +1,17 @@ +package io.github.chrisimx.scanbridge.infrastructure + +import io.github.chrisimx.scanbridge.infrastructure.KmLogScanBridgeLogger +import io.github.chrisimx.scanbridge.ports.ScanBridgeLogger +import io.github.chrisimx.scanbridge.ports.ScanBridgeLoggerFactory +import kotlin.reflect.KClass + +class KmLogScanBridgeLoggerFactory : ScanBridgeLoggerFactory { + override fun withClass(clazz: KClass): ScanBridgeLogger { + val tag = clazz.simpleName ?: "Unknown" + return KmLogScanBridgeLogger( + tag + ) + } + + override fun withTag(tag: String): ScanBridgeLogger = KmLogScanBridgeLogger(tag) +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/Locale.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/Locale.kt new file mode 100644 index 0000000..1e61000 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/Locale.kt @@ -0,0 +1,8 @@ +package io.github.chrisimx.scanbridge.model + +data class Locale( + /** + * The two character country code in uppercase + */ + val country: String +) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanBridgeFile.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanBridgeFile.kt new file mode 100644 index 0000000..fd80189 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanBridgeFile.kt @@ -0,0 +1,9 @@ +package io.github.chrisimx.scanbridge.model + +import kotlinx.io.files.Path + +data class ScanBridgeFile( + val path: Path +) + + diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/HttpClientFactory.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/HttpClientFactory.kt new file mode 100644 index 0000000..6b74a1b --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/HttpClientFactory.kt @@ -0,0 +1,8 @@ +package io.github.chrisimx.scanbridge.ports + +import io.github.chrisimx.scanbridge.model.HttpClientConfig +import io.ktor.client.HttpClient + +interface HttpClientFactory { + fun create(config: HttpClientConfig): HttpClient +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/LocaleProvider.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/LocaleProvider.kt new file mode 100644 index 0000000..903c7a3 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/LocaleProvider.kt @@ -0,0 +1,11 @@ +package io.github.chrisimx.scanbridge.ports + +import io.github.chrisimx.scanbridge.model.Locale +import kotlinx.coroutines.flow.StateFlow + +/** + * Provides the currently selected [io.github.chrisimx.scanbridge.model.Locale] as a reactive stream. + */ +interface LocaleProvider { + val locale: StateFlow +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanBridgeLogger.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLogger.kt similarity index 94% rename from core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanBridgeLogger.kt rename to core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLogger.kt index d9193f8..7c47afb 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ScanBridgeLogger.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLogger.kt @@ -1,4 +1,4 @@ -package io.github.chrisimx.scanbridge +package io.github.chrisimx.scanbridge.ports interface ScanBridgeLogger { /** Log a verbose message */ diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLoggerFactory.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLoggerFactory.kt new file mode 100644 index 0000000..6cae72a --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLoggerFactory.kt @@ -0,0 +1,10 @@ +package io.github.chrisimx.scanbridge.ports + +import io.github.chrisimx.scanbridge.infrastructure.KmLogScanBridgeLogger +import io.github.chrisimx.scanbridge.ports.ScanBridgeLogger +import kotlin.reflect.KClass + +interface ScanBridgeLoggerFactory { + fun withClass(clazz: KClass): ScanBridgeLogger + fun withTag(tag: String): ScanBridgeLogger +} diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ZipService.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ZipService.kt new file mode 100644 index 0000000..e58c298 --- /dev/null +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ZipService.kt @@ -0,0 +1,7 @@ +package io.github.chrisimx.scanbridge.ports + +import io.github.chrisimx.scanbridge.model.ScanBridgeFile + +interface ZipService { + fun zip(files: List, output: ScanBridgeFile, mapFileName: (ScanBridgeFile) -> String = { it.path.name }) +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b5f1a5d..5a5a28f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -85,7 +85,9 @@ koin-compose-viewmodel-navigation = { module = "io.insert-koin:koin-compose-view koin-androidx-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koin" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" } -ktor-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor"} +ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor"} +ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } +ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" } ktor-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor"} androidx-constraintlayout-compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "constraintlayoutCompose" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } From c7d276c6ac9697a975e987311bc8b80376dbffc6 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Sat, 11 Apr 2026 12:46:10 +0200 Subject: [PATCH 21/26] Rename ScanSettingsStateData to ScanSettingsEnterableData --- .../data/ui/ScanSettingsComposableStateHolder.kt | 6 +++--- .../scanbridge/data/ui/ScanningScreenViewModel.kt | 12 +++--------- .../scanbridge/stores/DefaultScanSettingsStore.kt | 8 ++++---- .../github/chrisimx/scanbridge/db/daos/SessionDao.kt | 4 ++-- .../chrisimx/scanbridge/db/entities/Session.kt | 4 ++-- .../ScanSettingsUiDataTypeConverter.kt | 8 ++++---- .../scanbridge/model/ScanSettingsEnterableData.kt | 2 +- 7 files changed, 19 insertions(+), 25 deletions(-) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt index 72ca9d4..262d62d 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt @@ -43,7 +43,7 @@ import io.github.chrisimx.scanbridge.model.Locale import io.github.chrisimx.scanbridge.R import io.github.chrisimx.scanbridge.ports.LocaleProvider import io.github.chrisimx.scanbridge.model.NumberValidationResult -import io.github.chrisimx.scanbridge.model.ScanSettingsStateData +import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData import io.github.chrisimx.scanbridge.util.derived import io.github.chrisimx.scanbridge.util.getMaxResolution import io.github.chrisimx.scanbridge.util.toDoubleLocalized @@ -74,7 +74,7 @@ class ScanSettingsComposableStateHolder( @InjectedParam val scanSettings: StateFlow, @InjectedParam - private val initialScanSettingsData: ScanSettingsStateData, + private val initialScanSettingsData: ScanSettingsEnterableData, @InjectedParam private val updateSettings: suspend (ScanSettings.() -> ScanSettings) -> Unit, @InjectedParam @@ -84,7 +84,7 @@ class ScanSettingsComposableStateHolder( ) { private val _uiState = MutableStateFlow(initialScanSettingsData) - val uiState: StateFlow = _uiState.asStateFlow() + val uiState: StateFlow = _uiState.asStateFlow() val inputSourceOptions: StateFlow> = _uiState.derived(coroutineScope) { it.capabilities.getInputSourceOptions() diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt index c08051c..fef4039 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt @@ -37,7 +37,6 @@ import com.itextpdf.kernel.pdf.PdfDocument import com.itextpdf.kernel.pdf.PdfWriter import com.itextpdf.layout.Document import com.itextpdf.layout.element.Image -import getTrustAllTM import io.github.chrisimx.esclkt.ESCLRequestClient import io.github.chrisimx.esclkt.InputSource import io.github.chrisimx.esclkt.ScanRegion @@ -59,7 +58,7 @@ import io.github.chrisimx.scanbridge.db.entities.TempFile import io.github.chrisimx.scanbridge.model.HttpClientConfig import io.github.chrisimx.scanbridge.model.ScanJob import io.github.chrisimx.scanbridge.model.ScanRelativeRotation -import io.github.chrisimx.scanbridge.model.ScanSettingsStateData +import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData import io.github.chrisimx.scanbridge.model.toggleRotation import io.github.chrisimx.scanbridge.ports.HttpClientFactory import io.github.chrisimx.scanbridge.proto.chunkSizePdfExportOrNull @@ -72,11 +71,6 @@ import io.github.chrisimx.scanbridge.util.rotateBy90 import io.github.chrisimx.scanbridge.util.saveAsJPEG import io.github.chrisimx.scanbridge.util.snackbarErrorRetrievingPage import io.github.chrisimx.scanbridge.util.zipFiles -import io.ktor.client.HttpClient -import io.ktor.client.engine.okhttp.OkHttp -import io.ktor.client.plugins.HttpTimeout -import io.ktor.client.plugins.logging.Logger -import io.ktor.client.plugins.logging.Logging import io.ktor.http.Url import java.io.File import java.nio.file.Files @@ -289,7 +283,7 @@ class ScanningScreenViewModel( } } - suspend fun saveUpdatedScanSettingsUiData(newData: ScanSettingsStateData?) { + suspend fun saveUpdatedScanSettingsUiData(newData: ScanSettingsEnterableData?) { Timber.d("Settings ui data updated $newData") sessionDao.updateScanSettingsUiData(sessionID, newData) } @@ -313,7 +307,7 @@ class ScanningScreenViewModel( } } - val defaultScanSettingsUIData = ScanSettingsStateData( + val defaultScanSettingsUIData = ScanSettingsEnterableData( caps ) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt index 2f23ad2..a9017b6 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt @@ -28,7 +28,7 @@ import io.github.chrisimx.scanbridge.proto.lastUsedScanSettingsOrNull import io.github.chrisimx.scanbridge.proto.lastUsedScanSettingsUiStateOrNull import io.github.chrisimx.scanbridge.proto.rememberScanSettingsOrNull import io.github.chrisimx.scanbridge.ScanSettingsJson -import io.github.chrisimx.scanbridge.model.ScanSettingsStateData +import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData import kotlinx.coroutines.flow.first import timber.log.Timber @@ -38,7 +38,7 @@ object DefaultScanSettingsStore { return appPreferences.rememberScanSettingsOrNull?.value ?: true } - suspend fun save(context: Context, scanSettings: ScanSettings, uiStateData: ScanSettingsStateData?) { + suspend fun save(context: Context, scanSettings: ScanSettings, uiStateData: ScanSettingsEnterableData?) { if (!isRememberSettingsEnabled(context)) { Timber.d("Scan settings persistence is disabled, skipping save") return @@ -61,7 +61,7 @@ object DefaultScanSettingsStore { } } - suspend fun load(context: Context): Pair { + suspend fun load(context: Context): Pair { if (!isRememberSettingsEnabled(context)) { Timber.d("Scan settings persistence is disabled, returning null") return null to null @@ -80,7 +80,7 @@ object DefaultScanSettingsStore { val json = ScanSettingsJson.json val lastUsedScanSettingsDecoded = json.decodeFromString(lastUsedScanSettings) val lastUsedScanSettingsUIStateDecoded = lastUsedScanSettingsUiState?.let { - json.decodeFromString(it) + json.decodeFromString(it) } Timber.d("Loaded default scan settings $lastUsedScanSettings, $lastUsedScanSettingsUIStateDecoded") return lastUsedScanSettingsDecoded to lastUsedScanSettingsUIStateDecoded diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt index 84832ca..9b64277 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/daos/SessionDao.kt @@ -6,7 +6,7 @@ import androidx.room.Insert import androidx.room.Query import androidx.room.Update import io.github.chrisimx.scanbridge.db.entities.Session -import io.github.chrisimx.scanbridge.model.ScanSettingsStateData +import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData import kotlin.uuid.Uuid import kotlinx.coroutines.flow.Flow @@ -37,7 +37,7 @@ interface SessionDao { suspend fun updateCurrentPage(sessionId: Uuid, pageIdx: Int) @Query("UPDATE sessions SET currentSettingsUIData = :uiData WHERE sessionId = :sessionId") - suspend fun updateScanSettingsUiData(sessionId: Uuid, uiData: ScanSettingsStateData?) + suspend fun updateScanSettingsUiData(sessionId: Uuid, uiData: ScanSettingsEnterableData?) @Delete suspend fun delete(session: Session) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/Session.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/Session.kt index 822cd8c..76d4024 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/Session.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/Session.kt @@ -4,7 +4,7 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey import io.github.chrisimx.esclkt.ScanSettings -import io.github.chrisimx.scanbridge.model.ScanSettingsStateData +import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData import kotlin.uuid.Uuid @Entity(tableName = "sessions") @@ -13,6 +13,6 @@ data class Session( val sessionId: Uuid, val currentScanSettings: ScanSettings?, @ColumnInfo(defaultValue = "null") - val currentSettingsUIData: ScanSettingsStateData?, + val currentSettingsUIData: ScanSettingsEnterableData?, val currentPage: Int = 0 ) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt index 9128451..0046b2f 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/typeconverters/ScanSettingsUiDataTypeConverter.kt @@ -2,19 +2,19 @@ package io.github.chrisimx.scanbridge.db.typeconverters import androidx.room.TypeConverter import io.github.chrisimx.scanbridge.ScanSettingsJson -import io.github.chrisimx.scanbridge.model.ScanSettingsStateData +import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData class ScanSettingsUiDataTypeConverter { @TypeConverter - fun fromScanSettingsString(scanSettings: String): ScanSettingsStateData? = if (scanSettings == "null") { + fun fromScanSettingsString(scanSettings: String): ScanSettingsEnterableData? = if (scanSettings == "null") { null } else { - ScanSettingsJson.json.decodeFromString(scanSettings) + ScanSettingsJson.json.decodeFromString(scanSettings) } @TypeConverter - fun toScanSettingsString(scanSettings: ScanSettingsStateData?): String = if (scanSettings == null) { + fun toScanSettingsString(scanSettings: ScanSettingsEnterableData?): String = if (scanSettings == null) { "null" } else { ScanSettingsJson.json.encodeToString(scanSettings) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt index 70e5fb5..f32e597 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt @@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable @Serializable -data class ScanSettingsStateData( +data class ScanSettingsEnterableData( val capabilities: ScannerCapabilities, val paperFormats: List = loadDefaultFormats(), val customMenuEnabled: Boolean = false, From 6f8a06d2a420f0a2a52888862d66f9ead76ba332 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Wed, 13 May 2026 23:20:39 +0200 Subject: [PATCH 22/26] Remove basic README.MD --- README.MD.other | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 README.MD.other diff --git a/README.MD.other b/README.MD.other deleted file mode 100644 index afde789..0000000 --- a/README.MD.other +++ /dev/null @@ -1,19 +0,0 @@ -# ScanBridge - -### Android -To run the application on android device/emulator: - - open project in Android Studio and run imported android run configuration - -To build the application bundle: - - run `./gradlew :androidApp:assembleDebug` - - find `.apk` file in `androidApp/build/outputs/apk/debug/androidApp-debug.apk` - -### Desktop -Run the desktop application: `./gradlew :desktopApp:run` -Run the desktop **hot reload** application: `./gradlew :desktopApp:hotRun --auto` - -### iOS -To run the application on iPhone device/simulator: - - Open `iosApp/iosApp.xcproject` in Xcode and run standard configuration - - Or use [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) for Android Studio - From 7be8c8052d0ef35b4a8f8f0386d56e3e46f0076a Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Wed, 13 May 2026 23:21:08 +0200 Subject: [PATCH 23/26] Add HTTP requests for testing escl and WSD --- .gitignore | 3 +- http-requests/eSCL.http | 4 + http-requests/wsd.http | 164 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 http-requests/eSCL.http create mode 100644 http-requests/wsd.http diff --git a/.gitignore b/.gitignore index 802c8c9..9125031 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ app/src/androidTest/native-libs /app/debug /app/release /app/play -/fastlane/report.xml \ No newline at end of file +/fastlane/report.xml +/http-requests/http-client.private.env.json diff --git a/http-requests/eSCL.http b/http-requests/eSCL.http new file mode 100644 index 0000000..8818123 --- /dev/null +++ b/http-requests/eSCL.http @@ -0,0 +1,4 @@ +### Retrieve the eSCL scanner capabilities +GET http://{{server}}/eSCL/ScannerCapabilities + +### \ No newline at end of file diff --git a/http-requests/wsd.http b/http-requests/wsd.http new file mode 100644 index 0000000..6ad54eb --- /dev/null +++ b/http-requests/wsd.http @@ -0,0 +1,164 @@ +### Retrieve scanner caps +POST http://{{server}}/WebServices/ScannerService +Content-Type: application/soap+xml +User-Agent: WSDAPI + + + + + urn:uuid:9c8c2edb-3ffc-b823-28e8-b4339548f743 + http://192.168.178.122:80/WebServices/ScannerService + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.microsoft.com/windows/2006/08/wdp/scan/GetScannerElements + + + + + sca:ScannerConfiguration + sca:ScannerDescription + sca:DefaultScanTicket + sca:ScannerStatus + + + + + + +### Get scanner status +POST http://{{server}}/WebServices/ScannerService +Content-Type: application/soap+xml +User-Agent: WSDAPI + + + + + urn:uuid:8af74e6f-1f8b-4d40-c36f-f10eee60221e + http://192.168.178.122:80/WebServices/ScannerService + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.microsoft.com/windows/2006/08/wdp/scan/GetScannerElements + + + + + sca:ScannerStatus + + + + + + +### Create scanjob +POST http://{{server}}/WebServices/ScannerService +Content-Type: application/soap+xml +User-Agent: WSDAPI + + + + + urn:uuid:e6d472bf-e3bd-a7a4-6066-cdea1f91e5fa + http://192.168.178.122:80/WebServices/ScannerService + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.microsoft.com/windows/2006/08/wdp/scan/CreateScanJob + + + + + + sane-airscan request + sane-airscan + sane-airscan + + + exif + 1 + + + 8500 + 11700 + + + Platen + + + RGB24 + + 300 + 300 + + + 0 + 0 + 8500 + 11700 + + + + + + + + + +### Retrieve scanned image +POST http://{{server}}/WebServices/ScannerService +Content-Type: application/soap+xml +User-Agent: WSDAPI + + + + + urn:uuid:dc1ff0f8-e4e2-b1ef-758f-b1e6186a5cc6 + http://192.168.178.122:80/WebServices/ScannerService + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.microsoft.com/windows/2006/08/wdp/scan/RetrieveImage + + + + + IMAGE000.JPG + + 2 + urn:uuid:81b7a2a1-f1ff-4504-84a2-3c2af46faf5d + + + + + +### Retrieve device info +POST http://{{server}}/WebServices/Device +Content-Type: application/soap+xml +User-Agent: WSDAPI + + + + + http://schemas.xmlsoap.org/ws/2004/09/transfer/Get + urn:uuid:414bbe9a-7059-e7c3-a856-a38029a53c1c + urn:uuid:e3248000-80ce-11db-8000-3c2af46faf5d + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + + + \ No newline at end of file From cc2b25b3574763dae8950f3f0354f1993864bc64 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Wed, 13 May 2026 23:21:44 +0200 Subject: [PATCH 24/26] Remove unused iosApp --- iosApp/iosApp.xcodeproj/project.pbxproj | 362 ------------------ .../contents.xcworkspacedata | 7 - .../UserInterfaceState.xcuserstate | Bin 17324 -> 0 bytes .../xcschemes/xcschememanagement.plist | 5 - .../xcschemes/iosApp.xcscheme | 66 ---- .../xcschemes/xcschememanagement.plist | 14 - .../AccentColor.colorset/Contents.json | 11 - .../AppIcon.appiconset/AppIcon-20@2x.png | Bin 1494 -> 0 bytes .../AppIcon.appiconset/AppIcon-20@2x~ipad.png | Bin 1494 -> 0 bytes .../AppIcon.appiconset/AppIcon-20@3x.png | Bin 2137 -> 0 bytes .../AppIcon.appiconset/AppIcon-20~ipad.png | Bin 636 -> 0 bytes .../AppIcon.appiconset/AppIcon-29.png | Bin 1272 -> 0 bytes .../AppIcon.appiconset/AppIcon-29@2x.png | Bin 2830 -> 0 bytes .../AppIcon.appiconset/AppIcon-29@2x~ipad.png | Bin 2830 -> 0 bytes .../AppIcon.appiconset/AppIcon-29@3x.png | Bin 3716 -> 0 bytes .../AppIcon.appiconset/AppIcon-29~ipad.png | Bin 1272 -> 0 bytes .../AppIcon.appiconset/AppIcon-40@2x.png | Bin 3170 -> 0 bytes .../AppIcon.appiconset/AppIcon-40@2x~ipad.png | Bin 3170 -> 0 bytes .../AppIcon.appiconset/AppIcon-40@3x.png | Bin 4420 -> 0 bytes .../AppIcon.appiconset/AppIcon-40~ipad.png | Bin 1494 -> 0 bytes .../AppIcon.appiconset/AppIcon-60@2x~car.png | Bin 4420 -> 0 bytes .../AppIcon.appiconset/AppIcon-60@3x~car.png | Bin 8223 -> 0 bytes .../AppIcon-83.5@2x~ipad.png | Bin 7382 -> 0 bytes .../AppIcon.appiconset/AppIcon@2x.png | Bin 4420 -> 0 bytes .../AppIcon.appiconset/AppIcon@2x~ipad.png | Bin 6476 -> 0 bytes .../AppIcon.appiconset/AppIcon@3x.png | Bin 8223 -> 0 bytes .../AppIcon~ios-marketing.png | Bin 67276 -> 0 bytes .../AppIcon.appiconset/AppIcon~ipad.png | Bin 3193 -> 0 bytes .../AppIcon.appiconset/Contents.json | 130 ------- iosApp/iosApp/Assets.xcassets/Contents.json | 6 - iosApp/iosApp/Info.plist | 8 - .../Preview Assets.xcassets/Contents.json | 6 - iosApp/iosApp/iosApp.swift | 21 - 33 files changed, 636 deletions(-) delete mode 100644 iosApp/iosApp.xcodeproj/project.pbxproj delete mode 100644 iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/iosApp.xcscheme delete mode 100644 iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png delete mode 100644 iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 iosApp/iosApp/Assets.xcassets/Contents.json delete mode 100644 iosApp/iosApp/Info.plist delete mode 100644 iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json delete mode 100644 iosApp/iosApp/iosApp.swift diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj deleted file mode 100644 index 6a90958..0000000 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ /dev/null @@ -1,362 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - A93A953B29CC810C00F8E227 /* iosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93A953A29CC810C00F8E227 /* iosApp.swift */; }; - A93A953F29CC810D00F8E227 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A93A953E29CC810D00F8E227 /* Assets.xcassets */; }; - A93A954229CC810D00F8E227 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A93A954129CC810D00F8E227 /* Preview Assets.xcassets */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - A93A953729CC810C00F8E227 /* ScanBridge.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ScanBridge.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A93A953A29CC810C00F8E227 /* iosApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosApp.swift; sourceTree = ""; }; - A93A953E29CC810D00F8E227 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - A93A954129CC810D00F8E227 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - A93A953429CC810C00F8E227 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - A93A952E29CC810C00F8E227 = { - isa = PBXGroup; - children = ( - A93A953929CC810C00F8E227 /* iosApp */, - A93A953829CC810C00F8E227 /* Products */, - C4127409AE3703430489E7BC /* Frameworks */, - ); - sourceTree = ""; - }; - A93A953829CC810C00F8E227 /* Products */ = { - isa = PBXGroup; - children = ( - A93A953729CC810C00F8E227 /* ScanBridge.app */, - ); - name = Products; - sourceTree = ""; - }; - A93A953929CC810C00F8E227 /* iosApp */ = { - isa = PBXGroup; - children = ( - A93A953A29CC810C00F8E227 /* iosApp.swift */, - A93A953E29CC810D00F8E227 /* Assets.xcassets */, - A93A954029CC810D00F8E227 /* Preview Content */, - ); - path = iosApp; - sourceTree = ""; - }; - A93A954029CC810D00F8E227 /* Preview Content */ = { - isa = PBXGroup; - children = ( - A93A954129CC810D00F8E227 /* Preview Assets.xcassets */, - ); - path = "Preview Content"; - sourceTree = ""; - }; - C4127409AE3703430489E7BC /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - A93A953629CC810C00F8E227 /* iosApp */ = { - isa = PBXNativeTarget; - buildConfigurationList = A93A954529CC810D00F8E227 /* Build configuration list for PBXNativeTarget "iosApp" */; - buildPhases = ( - A9D80A052AAB5CDE006C8738 /* ShellScript */, - A93A953329CC810C00F8E227 /* Sources */, - A93A953429CC810C00F8E227 /* Frameworks */, - A93A953529CC810C00F8E227 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = iosApp; - productName = iosApp; - productReference = A93A953729CC810C00F8E227 /* ScanBridge.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - A93A952F29CC810C00F8E227 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1420; - LastUpgradeCheck = 1420; - TargetAttributes = { - A93A953629CC810C00F8E227 = { - CreatedOnToolsVersion = 14.2; - }; - }; - }; - buildConfigurationList = A93A953229CC810C00F8E227 /* Build configuration list for PBXProject "iosApp" */; - compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = A93A952E29CC810C00F8E227; - productRefGroup = A93A953829CC810C00F8E227 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - A93A953629CC810C00F8E227 /* iosApp */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - A93A953529CC810C00F8E227 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A93A954229CC810D00F8E227 /* Preview Assets.xcassets in Resources */, - A93A953F29CC810D00F8E227 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - A9D80A052AAB5CDE006C8738 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT/..\"\n./gradlew :sharedUI:embedAndSignAppleFrameworkForXcode\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - A93A953329CC810C00F8E227 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A93A953B29CC810C00F8E227 /* iosApp.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - A93A954329CC810D00F8E227 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - A93A954429CC810D00F8E227 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - A93A954629CC810D00F8E227 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; - DEVELOPMENT_TEAM = 3MGF2AU6D9; - ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = iosApp/Info.plist; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.github.chrisimx.scanbridge.iosApp; - PRODUCT_NAME = ScanBridge; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - A93A954729CC810D00F8E227 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; - DEVELOPMENT_TEAM = 3MGF2AU6D9; - ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = iosApp/Info.plist; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.github.chrisimx.scanbridge.iosApp; - PRODUCT_NAME = ScanBridge; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - A93A953229CC810C00F8E227 /* Build configuration list for PBXProject "iosApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A93A954329CC810D00F8E227 /* Debug */, - A93A954429CC810D00F8E227 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - A93A954529CC810D00F8E227 /* Build configuration list for PBXNativeTarget "iosApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A93A954629CC810D00F8E227 /* Debug */, - A93A954729CC810D00F8E227 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = A93A952F29CC810C00F8E227 /* Project object */; -} diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/UserInterfaceState.xcuserstate b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 7a97afe7b8a277f9222e6e0101193536144e4a89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17324 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 X`NZ-`vJFOv{K@YO*sFn$@+toh)m7|K diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index ee3458d..0000000 --- a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/iosApp.xcscheme b/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/iosApp.xcscheme deleted file mode 100644 index 9c8bccd..0000000 --- a/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/iosApp.xcscheme +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist b/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index fa59f97..0000000 --- a/iosApp/iosApp.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - iosApp.xcscheme - - orderHint - 0 - - - - diff --git a/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json b/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb87897..0000000 --- a/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png deleted file mode 100644 index 41a92ea6e762fc71e84241b523441237d133b5d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1494 zcmV;{1u6Q8P)BQ3DW2UV$vVBO^#MfH7=D?RxVR!i(}K~OiFBy zO)QS0Fu=G0DlU;}VF-c985X9dsMBb0so|E=pcr+(-Uv>2^}vzH7+9N`AqURK%?k zpoBkvM_f*(z`RRoe|5qXI8*fa8XG^nli*G16LV@Pt?}nItt|q%?QEfZL1RoOU@)bv zaOn%;Z%c6jK0JL49|X8- zhQrBPC6FJVIU$gSrrTh^qP z+S=jkS#uGhcEe*=S z*c>ujKHqoc5@L^}qnluLnO>njv1A3NsXh99OitY`n#NJfdo~to)i8mZPf_ipCSc>a zofQ!ykX&jCq3P-Z z&*Y7*Hl4Gog&m7o?oXT=#fGjl!7ez}{ z*i_$bmvr3^Aj?$i%e{bXTd7o7z7$2!Yq%Y97ca+XJA3i-pi<1fPS#Xm`Y#E}0C^rK z&0UP=#*P<98w&Gfs@zYLtff-fN+qK;mM;4rcj#;sy*0?rSQ>cbnG!5Z!@P_X(K=&f z#=*)8hpBOR>*;Tvd%wZ8|Fm+TP#OftHzv{~ST=6LfI_{KggW>hp)Mk!UOk9Vw^HP^ z(#3jMMA|x-84Ngu)~iDi(IP86>Ua`lT`Lp6`bOOX&oM{{i;z)Qt7#=!Do2dZlX7o( zMzYRMHW-kn!^XfFc#l>sUKVZ=ae$Um-nIuads-G)ZoZfiCUCqgY%V@2GR5-s zKmpmAC21Z*uJsEMNR}I3w^B+k320eUgN!@w{0J`}ET@v-b&GdMhWqqfk*sX&gSR5K z2bN-OgcyT>_^e_8N% zR?}pPl^3y%MMv=wrCpa9+{HS*7;!P)Hwd3i3zY_&OM=f!#3KdBYnro4C9By5TH9K? wIv*`SBZ4hQA9{+10F8}+((^+pRvN*70blgm&(&cR*Z=?k07*qoM6N<$g55CA)c^nh diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png deleted file mode 100644 index 41a92ea6e762fc71e84241b523441237d133b5d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1494 zcmV;{1u6Q8P)BQ3DW2UV$vVBO^#MfH7=D?RxVR!i(}K~OiFBy zO)QS0Fu=G0DlU;}VF-c985X9dsMBb0so|E=pcr+(-Uv>2^}vzH7+9N`AqURK%?k zpoBkvM_f*(z`RRoe|5qXI8*fa8XG^nli*G16LV@Pt?}nItt|q%?QEfZL1RoOU@)bv zaOn%;Z%c6jK0JL49|X8- zhQrBPC6FJVIU$gSrrTh^qP z+S=jkS#uGhcEe*=S z*c>ujKHqoc5@L^}qnluLnO>njv1A3NsXh99OitY`n#NJfdo~to)i8mZPf_ipCSc>a zofQ!ykX&jCq3P-Z z&*Y7*Hl4Gog&m7o?oXT=#fGjl!7ez}{ z*i_$bmvr3^Aj?$i%e{bXTd7o7z7$2!Yq%Y97ca+XJA3i-pi<1fPS#Xm`Y#E}0C^rK z&0UP=#*P<98w&Gfs@zYLtff-fN+qK;mM;4rcj#;sy*0?rSQ>cbnG!5Z!@P_X(K=&f z#=*)8hpBOR>*;Tvd%wZ8|Fm+TP#OftHzv{~ST=6LfI_{KggW>hp)Mk!UOk9Vw^HP^ z(#3jMMA|x-84Ngu)~iDi(IP86>Ua`lT`Lp6`bOOX&oM{{i;z)Qt7#=!Do2dZlX7o( zMzYRMHW-kn!^XfFc#l>sUKVZ=ae$Um-nIuads-G)ZoZfiCUCqgY%V@2GR5-s zKmpmAC21Z*uJsEMNR}I3w^B+k320eUgN!@w{0J`}ET@v-b&GdMhWqqfk*sX&gSR5K z2bN-OgcyT>_^e_8N% zR?}pPl^3y%MMv=wrCpa9+{HS*7;!P)Hwd3i3zY_&OM=f!#3KdBYnro4C9By5TH9K? wIv*`SBZ4hQA9{+10F8}+((^+pRvN*70blgm&(&cR*Z=?k07*qoM6N<$g55CA)c^nh diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png deleted file mode 100644 index ff64c69da90c62babcac97ed45364926fb78fa5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2137 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png deleted file mode 100644 index 9068381fdbc416aa43d63ec7ec5523e41fdea683..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2830 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png deleted file mode 100644 index 455225204e3548b8203e41067cab015642edfaff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3716 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 IM6N<$f}5S!cmMzZ diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png deleted file mode 100644 index ddd8c8f1eb962090ba571912d98f5f21cd4429bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3170 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 IM6N<$f}5S!cmMzZ diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png deleted file mode 100644 index 761f82134f04bcf3010fdec4b7b7a7e69c3b0b11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4420 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png deleted file mode 100644 index 41a92ea6e762fc71e84241b523441237d133b5d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1494 zcmV;{1u6Q8P)BQ3DW2UV$vVBO^#MfH7=D?RxVR!i(}K~OiFBy zO)QS0Fu=G0DlU;}VF-c985X9dsMBb0so|E=pcr+(-Uv>2^}vzH7+9N`AqURK%?k zpoBkvM_f*(z`RRoe|5qXI8*fa8XG^nli*G16LV@Pt?}nItt|q%?QEfZL1RoOU@)bv zaOn%;Z%c6jK0JL49|X8- zhQrBPC6FJVIU$gSrrTh^qP z+S=jkS#uGhcEe*=S z*c>ujKHqoc5@L^}qnluLnO>njv1A3NsXh99OitY`n#NJfdo~to)i8mZPf_ipCSc>a zofQ!ykX&jCq3P-Z z&*Y7*Hl4Gog&m7o?oXT=#fGjl!7ez}{ z*i_$bmvr3^Aj?$i%e{bXTd7o7z7$2!Yq%Y97ca+XJA3i-pi<1fPS#Xm`Y#E}0C^rK z&0UP=#*P<98w&Gfs@zYLtff-fN+qK;mM;4rcj#;sy*0?rSQ>cbnG!5Z!@P_X(K=&f z#=*)8hpBOR>*;Tvd%wZ8|Fm+TP#OftHzv{~ST=6LfI_{KggW>hp)Mk!UOk9Vw^HP^ z(#3jMMA|x-84Ngu)~iDi(IP86>Ua`lT`Lp6`bOOX&oM{{i;z)Qt7#=!Do2dZlX7o( zMzYRMHW-kn!^XfFc#l>sUKVZ=ae$Um-nIuads-G)ZoZfiCUCqgY%V@2GR5-s zKmpmAC21Z*uJsEMNR}I3w^B+k320eUgN!@w{0J`}ET@v-b&GdMhWqqfk*sX&gSR5K z2bN-OgcyT>_^e_8N% zR?}pPl^3y%MMv=wrCpa9+{HS*7;!P)Hwd3i3zY_&OM=f!#3KdBYnro4C9By5TH9K? wIv*`SBZ4hQA9{+10F8}+((^+pRvN*70blgm&(&cR*Z=?k07*qoM6N<$g55CA)c^nh diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png deleted file mode 100644 index 761f82134f04bcf3010fdec4b7b7a7e69c3b0b11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4420 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png deleted file mode 100644 index 276a950e65922b414281102ff5c13fd6eff9bee2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8223 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png deleted file mode 100644 index 9e23219b3306ceef03000feab0ec2af24a384527..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7382 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png deleted file mode 100644 index 761f82134f04bcf3010fdec4b7b7a7e69c3b0b11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4420 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png deleted file mode 100644 index 59ac0abccbdf99480c75b05f7c73368147714b85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6476 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png deleted file mode 100644 index ef951ed2c218c78916f6ca8b1efbb62217dcf885..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67276 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 diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png deleted file mode 100644 index 1923af1a67ad838c5e7b2e149a691e50dba32689..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3193 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 - - - - CADisableMinimumFrameDurationOnPhone - - - diff --git a/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json b/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json deleted file mode 100644 index 73c0059..0000000 --- a/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/iosApp/iosApp/iosApp.swift b/iosApp/iosApp/iosApp.swift deleted file mode 100644 index 0e4b303..0000000 --- a/iosApp/iosApp/iosApp.swift +++ /dev/null @@ -1,21 +0,0 @@ -import SwiftUI -import SharedUI - -@main -struct ComposeApp: App { - var body: some Scene { - WindowGroup { - ContentView().ignoresSafeArea(.all) - } - } -} - -struct ContentView: UIViewControllerRepresentable { - func makeUIViewController(context: Context) -> UIViewController { - return MainKt.MainViewController() - } - - func updateUIViewController(_ uiViewController: UIViewController, context: Context) { - // Updates will be handled by Compose - } -} From 2c0f8e41564ad35af9ac7d6712c34dfa18accb1f Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Wed, 13 May 2026 23:45:24 +0200 Subject: [PATCH 25/26] Try to fix CI --- .github/workflows/android.yml | 4 ++-- .github/workflows/create-release.yml | 6 +++--- androidApp/fastlane/Fastfile | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 7f4f9dc..7d48b92 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -31,7 +31,7 @@ jobs: uses: actions/upload-artifact@v4.5.0 with: name: unsigned-release-apk - path: app/build/outputs/apk/fdroid/release/app-fdroid-release-unsigned.apk + path: androidApp/build/outputs/apk/fdroid/release/androidApp-fdroid-release-unsigned.apk if-no-files-found: error - uses: noriban/sign-android-release@v5 name: Sign app APK @@ -39,7 +39,7 @@ jobs: # ID used to access action output id: sign_app with: - releaseDirectory: app/build/outputs/apk/fdroid/release + releaseDirectory: androidApp/build/outputs/apk/fdroid/release signingKeyBase64: ${{ secrets.CI_KEYSTORE_BASE64 }} alias: ${{ secrets.CI_ALIAS }} keyStorePassword: ${{ secrets.CI_KEY_STORE_PASSWORD }} diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index dcf11f9..cee607e 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -85,18 +85,18 @@ jobs: # ID used to access action output id: sign_app with: - releaseDirectory: app/build/outputs/apk/fdroid/release + releaseDirectory: androidApp/build/outputs/apk/fdroid/release signingKeyBase64: ${{ secrets.RELEASE_KEY_STORE_BASE64 }} alias: ${{ secrets.RELEASE_ALIAS }} keyStorePassword: ${{ secrets.RELEASE_KEY_STORE_PASSWORD }} keyPassword: ${{ secrets.RELEASE_KEY_PASSWORD }} - name: Rename signed APK - run: mv ${{steps.sign_app.outputs.signedReleaseFile}} app/build/outputs/apk/fdroid/release/ScanBridge${{ needs.prepare.outputs.artifact_version_suffix }}.apk + run: mv ${{steps.sign_app.outputs.signedReleaseFile}} androidApp/build/outputs/apk/fdroid/release/ScanBridge${{ needs.prepare.outputs.artifact_version_suffix }}.apk - name: Upload signed APK uses: actions/upload-artifact@v4.5.0 with: name: signed-release-apk - path: app/build/outputs/apk/fdroid/release/ScanBridge${{ needs.prepare.outputs.artifact_version_suffix }}.apk + path: androidApp/build/outputs/apk/fdroid/release/ScanBridge${{ needs.prepare.outputs.artifact_version_suffix }}.apk if-no-files-found: error publish-result: diff --git a/androidApp/fastlane/Fastfile b/androidApp/fastlane/Fastfile index 9d68fe3..eb1f6e5 100644 --- a/androidApp/fastlane/Fastfile +++ b/androidApp/fastlane/Fastfile @@ -100,8 +100,8 @@ platform :android do sh("adb shell wm user-rotation lock #{rotation}") screengrab( - tests_apk_path: "app/build/outputs/apk/androidTest/play/debug/app-play-debug-androidTest.apk", - app_apk_path: "app/build/outputs/apk/play/debug/app-play-debug.apk", + tests_apk_path: "androidApp/build/outputs/apk/androidTest/play/debug/androidApp-play-debug-androidTest.apk", + app_apk_path: "androidApp/build/outputs/apk/play/debug/androidApp-play-debug.apk", output_directory: $playMetadata, device_type: device_type, tests_package_name: "io.github.chrisimx.scanbridge.play.test", @@ -111,8 +111,8 @@ platform :android do ) screengrab( - tests_apk_path: "app/build/outputs/apk/androidTest/fdroid/debug/app-fdroid-debug-androidTest.apk", - app_apk_path: "app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk", + tests_apk_path: "androidApp/build/outputs/apk/androidTest/fdroid/debug/androidApp-fdroid-debug-androidTest.apk", + app_apk_path: "androidApp/build/outputs/apk/fdroid/debug/androidApp-fdroid-debug.apk", output_directory: "fastlane/metadata/android", device_type: device_type, tests_package_name: "io.github.chrisimx.scanbridge.test", From 9607e08cdea16f25ea27a1e5d0bfdd679624d5d9 Mon Sep 17 00:00:00 2001 From: Christian Nagel Date: Wed, 13 May 2026 23:50:04 +0200 Subject: [PATCH 26/26] Fix format --- .../chrisimx/scanbridge/CrashActivity.kt | 2 - .../github/chrisimx/scanbridge/CropScreen.kt | 2 - .../scanbridge/ScanBridgeApplication.kt | 29 +++++------- .../chrisimx/scanbridge/ScannerBrowser.kt | 6 +-- .../scanbridge/ScannerDiscoveryBackend.kt | 4 +- .../ScanJobForegroundService.kt | 2 +- .../ui/ScanSettingsComposableStateHolder.kt | 15 +++---- .../data/ui/ScanSettingsStateData.kt | 21 --------- .../scanbridge/data/ui/ScanningScreenData.kt | 1 - .../data/ui/ScanningScreenViewModel.kt | 8 ++-- .../migrations/MigrationRegistry.kt | 15 ++++--- .../migrations/RoomBackedMigrationExecutor.kt | 6 +-- .../DatastoreLastRouteRepository.kt | 2 +- .../DatastoreShownMessagesRepository.kt | 14 ++---- .../repositories/RoomLastRouteRepository.kt | 9 ++-- .../stores/DefaultScanSettingsStore.kt | 4 +- .../scanbridge/stores/LegacySessionsStore.kt | 7 +-- .../scanbridge/uicomponents/TitledCard.kt | 1 - composeUI/build.gradle.kts | 5 +-- .../scanbridge/theme/Theme.android.kt | 28 +++++------- .../github/chrisimx/scanbridge/theme/Theme.kt | 3 +- .../chrisimx/scanbridge/theme/Typography.kt | 45 +++++++++---------- .../scanbridge/uicomponents/LoadingScreen.kt | 4 +- core/build.gradle.kts | 4 +- .../kotlin/AndroidHttpClientFactory.kt | 41 +++++++++-------- .../AndroidScanBridgeDbBuilderFactory.kt | 2 +- .../chrisimx/scanbridge/db/ScanBridgeDb.kt | 4 +- .../db/entities/ExecutedMigrationToRoom.kt | 2 +- .../scanbridge/db/entities/LastRoute.kt | 5 +-- .../infrastructure/KmLogScanBridgeLogger.kt | 6 +-- .../scanbridge/model/HttpClientConfig.kt | 6 +-- .../scanbridge/model/ScanBridgeFile.kt | 6 +-- .../model/ScanSettingsEnterableData.kt | 1 - .../ports/ScanBridgeLoggerFactory.kt | 1 - .../kotlin/IosScanBridgeDbBuilderFactory.kt | 4 +- .../src/main/kotlin/{main.kt => Main.kt} | 5 +-- 36 files changed, 122 insertions(+), 198 deletions(-) delete mode 100644 androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt rename desktopApp/src/main/kotlin/{main.kt => Main.kt} (91%) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt index 5d196fb..01a1638 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CrashActivity.kt @@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -// TODO: import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -28,7 +27,6 @@ import io.github.chrisimx.scanbridge.theme.ScanBridgeTheme import timber.log.Timber class CrashActivity : ComponentActivity() { - // TODO: @OptIn(ExperimentalMaterial3ExpressiveApi::class) override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt index fbdd7f1..601e70f 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/CropScreen.kt @@ -6,7 +6,6 @@ import androidx.compose.animation.core.snap import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -// TODO: import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExtendedFloatingActionButton import androidx.compose.material3.FabPosition import androidx.compose.material3.Icon @@ -43,7 +42,6 @@ import kotlin.uuid.Uuid import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.saket.telephoto.ExperimentalTelephotoApi import me.saket.telephoto.zoomable.EnabledZoomGestures import me.saket.telephoto.zoomable.ZoomSpec import me.saket.telephoto.zoomable.rememberZoomableState diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt index 10312ce..bd8e67d 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScanBridgeApplication.kt @@ -5,16 +5,22 @@ import AndroidScanBridgeDbBuilderFactory import android.app.Application import android.content.Context import androidx.datastore.core.DataStore -import androidx.room.Room import io.github.chrisimx.scanbridge.data.ui.CustomScannerViewModel import io.github.chrisimx.scanbridge.data.ui.ScanSettingsComposableStateHolder import io.github.chrisimx.scanbridge.data.ui.ScanningScreenViewModel import io.github.chrisimx.scanbridge.datastore.appSettingsStore import io.github.chrisimx.scanbridge.datastore.shownMessagesStore +import io.github.chrisimx.scanbridge.db.DefaultScanBridgeDbFactory import io.github.chrisimx.scanbridge.db.ScanBridgeDb +import io.github.chrisimx.scanbridge.db.ScanBridgeDbBuilderFactory +import io.github.chrisimx.scanbridge.db.ScanBridgeDbFactory +import io.github.chrisimx.scanbridge.infrastructure.KmLogScanBridgeLoggerFactory import io.github.chrisimx.scanbridge.migrations.MigrationExecutor import io.github.chrisimx.scanbridge.migrations.RoomBackedMigrationExecutor import io.github.chrisimx.scanbridge.migrations.migrationsModule +import io.github.chrisimx.scanbridge.ports.HttpClientFactory +import io.github.chrisimx.scanbridge.ports.LocaleProvider +import io.github.chrisimx.scanbridge.ports.ScanBridgeLoggerFactory import io.github.chrisimx.scanbridge.proto.ScanBridgeSettings import io.github.chrisimx.scanbridge.proto.ShownMessages import io.github.chrisimx.scanbridge.repositories.DatastoreLastRouteRepository @@ -24,8 +30,6 @@ import io.github.chrisimx.scanbridge.services.AndroidLocaleProvider import io.github.chrisimx.scanbridge.services.DebugLogService import io.github.chrisimx.scanbridge.services.FileDebugLogService import io.github.chrisimx.scanbridge.services.ScanJobRepository -import io.github.chrisimx.scanbridge.stores.LegacyCustomScannerStore.migrateLegacyCustomScanners -import io.github.chrisimx.scanbridge.stores.LegacySessionsStore.migrateLegacySessions import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -35,28 +39,16 @@ import org.koin.core.qualifier.named import org.koin.dsl.bind import org.koin.dsl.module import org.koin.mp.KoinPlatform.getKoin +import org.koin.plugin.module.dsl.create import org.koin.plugin.module.dsl.factory import org.koin.plugin.module.dsl.single -import org.koin.plugin.module.dsl.create import org.koin.plugin.module.dsl.viewModel -import androidx.sqlite.driver.bundled.BundledSQLiteDriver -import io.github.chrisimx.scanbridge.db.DefaultScanBridgeDbFactory -import io.github.chrisimx.scanbridge.db.ScanBridgeDbBuilderFactory -import io.github.chrisimx.scanbridge.db.ScanBridgeDbFactory -import io.github.chrisimx.scanbridge.infrastructure.KmLogScanBridgeLogger -import io.github.chrisimx.scanbridge.infrastructure.KmLogScanBridgeLoggerFactory -import io.github.chrisimx.scanbridge.ports.HttpClientFactory -import io.github.chrisimx.scanbridge.ports.LocaleProvider -import io.github.chrisimx.scanbridge.ports.ScanBridgeLogger -import io.github.chrisimx.scanbridge.ports.ScanBridgeLoggerFactory import timber.log.Timber fun createAppSettingsDataStore(context: Context) = context.appSettingsStore fun createShownMessagesDataStore(context: Context) = context.shownMessagesStore -fun createScanBridgeDb(factory: ScanBridgeDbFactory): ScanBridgeDb { - return factory.createInstance() -} +fun createScanBridgeDb(factory: ScanBridgeDbFactory): ScanBridgeDb = factory.createInstance() val appModule = module { single>(named()) { create(::createShownMessagesDataStore) @@ -67,7 +59,7 @@ val appModule = module { single() bind Thread.UncaughtExceptionHandler::class single() bind LocaleProvider::class single { - FileDebugLogService(get(named()),get()) + FileDebugLogService(get(named()), get()) } bind DebugLogService::class single() bind HttpClientFactory::class single() bind ScanBridgeLoggerFactory::class @@ -110,4 +102,3 @@ class ScanBridgeApplication : Application() { } } } - diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt index 19995dd..cfb26d0 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt @@ -64,14 +64,14 @@ fun startScannerDiscovery( context: Context, scannerMap: SnapshotStateMap, scannerMapSecure: SnapshotStateMap -): Optional>> { +): Optional>> { val service = getSystemService(context, NsdManager::class.java) if (service == null) { Timber.e("Couldn't get NsdManager service") return Optional.empty() } - val listener = ScannerDiscovery(service, isSecure = false, scannerMap) - val listenerSecure = ScannerDiscovery(service, isSecure = true, scannerMapSecure) + val listener = ScannerDiscoveryBackend(service, isSecure = false, scannerMap) + val listenerSecure = ScannerDiscoveryBackend(service, isSecure = true, scannerMapSecure) service.discoverServices("_uscan._tcp", NsdManager.PROTOCOL_DNS_SD, listener) service.discoverServices("_uscans._tcp", NsdManager.PROTOCOL_DNS_SD, listenerSecure) Timber.i("Discovery started") diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt index 19ba558..48b22c3 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/ScannerDiscoveryBackend.kt @@ -36,7 +36,7 @@ import timber.log.Timber private const val TAG = "ScannerDiscovery" -class ScannerDiscovery( +class ScannerDiscoveryBackend( val nsdManager: NsdManager, val isSecure: Boolean, val statefulScannerMap: SnapshotStateMap @@ -155,7 +155,7 @@ class ScannerDiscovery( } } -private fun ScannerDiscovery.tryParseScannerUrl(address: InetAddress, serviceInfo: NsdServiceInfo, rs: String): Url? { +private fun ScannerDiscoveryBackend.tryParseScannerUrl(address: InetAddress, serviceInfo: NsdServiceInfo, rs: String): Url? { if (address.isLinkLocalAddress) { Timber.tag(TAG).d("Ignoring link local address: ${address.hostAddress}") return null diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt index dc0858d..4f95b5c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/androidservice/ScanJobForegroundService.kt @@ -20,10 +20,10 @@ import io.github.chrisimx.esclkt.JobState import io.github.chrisimx.esclkt.ScanSettings import io.github.chrisimx.scanbridge.MainActivity import io.github.chrisimx.scanbridge.R -import io.github.chrisimx.scanbridge.model.ScanJob import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.daos.ScannedPageDao import io.github.chrisimx.scanbridge.db.entities.ScannedPage +import io.github.chrisimx.scanbridge.model.ScanJob import io.github.chrisimx.scanbridge.model.ScanRelativeRotation import io.github.chrisimx.scanbridge.ports.HttpClientFactory import io.github.chrisimx.scanbridge.services.ScanJobRepository diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt index 262d62d..259258c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsComposableStateHolder.kt @@ -39,11 +39,11 @@ import io.github.chrisimx.esclkt.inches import io.github.chrisimx.esclkt.millimeters import io.github.chrisimx.esclkt.scanRegion import io.github.chrisimx.esclkt.threeHundredthsOfInch -import io.github.chrisimx.scanbridge.model.Locale import io.github.chrisimx.scanbridge.R -import io.github.chrisimx.scanbridge.ports.LocaleProvider +import io.github.chrisimx.scanbridge.model.Locale import io.github.chrisimx.scanbridge.model.NumberValidationResult import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData +import io.github.chrisimx.scanbridge.ports.LocaleProvider import io.github.chrisimx.scanbridge.util.derived import io.github.chrisimx.scanbridge.util.getMaxResolution import io.github.chrisimx.scanbridge.util.toDoubleLocalized @@ -404,12 +404,11 @@ class ScanSettingsComposableStateHolder( } } - private fun unitByLocale(locale: Locale): ScanSettingsLengthUnit = - if (locale.country in setOf("US", "LR", "MM")) { - ScanSettingsLengthUnit.INCH - } else { - ScanSettingsLengthUnit.MILLIMETER - } + private fun unitByLocale(locale: Locale): ScanSettingsLengthUnit = if (locale.country in setOf("US", "LR", "MM")) { + ScanSettingsLengthUnit.INCH + } else { + ScanSettingsLengthUnit.MILLIMETER + } fun selectMaxRegion() { _uiState.update { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt deleted file mode 100644 index 97c2d87..0000000 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanSettingsStateData.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2024-2025 Christian Nagel and contributors - * - * This file is part of ScanBridge. - * - * ScanBridge is free software: you can redistribute it and/or modify it under the terms of - * the GNU General Public License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * ScanBridge is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with eSCLKt. - * If not, see . - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -package io.github.chrisimx.scanbridge.data.ui - diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt index 9e9367c..6b0c532 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenData.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.MutableState import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import io.github.chrisimx.esclkt.ESCLRequestClient import io.github.chrisimx.esclkt.ScannerCapabilities import java.io.File import kotlin.uuid.Uuid diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt index fef4039..1d27c13 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/data/ui/ScanningScreenViewModel.kt @@ -753,10 +753,10 @@ class ScanningScreenViewModel( } fun createHttpClientConfig() = HttpClientConfig( - certificateValidationDisabled, - withDebugInterceptor, - timeout.toULong() - ) + certificateValidationDisabled, + withDebugInterceptor, + timeout.toULong() + ) fun retrieveScannerCapabilities() = viewModelScope.launch { val httpClient = httpClientFactory.create( diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt index b4f71e1..a4e1839 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/MigrationRegistry.kt @@ -7,13 +7,14 @@ import org.koin.dsl.bind import org.koin.dsl.module import org.koin.plugin.module.dsl.create -fun createLastRouteRepoAutoMigration(datastoreLastRouteRepository: DatastoreLastRouteRepository, roomLastRouteRepository: RoomLastRouteRepository): LastRouteRepoAutoMigration { - return LastRouteRepoAutoMigration( - datastoreLastRouteRepository, - roomLastRouteRepository, - "LastRouteDataStoreToRoom" - ) -} +fun createLastRouteRepoAutoMigration( + datastoreLastRouteRepository: DatastoreLastRouteRepository, + roomLastRouteRepository: RoomLastRouteRepository +): LastRouteRepoAutoMigration = LastRouteRepoAutoMigration( + datastoreLastRouteRepository, + roomLastRouteRepository, + "LastRouteDataStoreToRoom" +) val migrationsModule = module { single { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt index 2df0914..c694211 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/migrations/RoomBackedMigrationExecutor.kt @@ -5,13 +5,9 @@ import io.github.chrisimx.scanbridge.db.entities.ExecutedMigrationToRoom import io.github.chrisimx.scanbridge.ports.ScanBridgeLoggerFactory import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.koin.core.scope.Scope import org.koin.mp.KoinPlatform.getKoin -class RoomBackedMigrationExecutor( - val db: ScanBridgeDb, - loggerFactory: ScanBridgeLoggerFactory -) : MigrationExecutor { +class RoomBackedMigrationExecutor(val db: ScanBridgeDb, loggerFactory: ScanBridgeLoggerFactory) : MigrationExecutor { val logger = loggerFactory.withClass(this::class) val executedMigrationsDao = db.executedMigrationsDao() diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreLastRouteRepository.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreLastRouteRepository.kt index 536242f..2a6d61c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreLastRouteRepository.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreLastRouteRepository.kt @@ -8,7 +8,7 @@ import io.github.chrisimx.scanbridge.proto.copy import io.github.chrisimx.scanbridge.proto.lastRouteOrNull import kotlinx.coroutines.flow.firstOrNull -class DatastoreLastRouteRepository(context: Context): LastRouteRepository { +class DatastoreLastRouteRepository(context: Context) : LastRouteRepository { val lastRouteStore = context.lastRouteStore override suspend fun getLastRoute(): String? = lastRouteStore.data.firstOrNull()?.lastRouteOrNull?.value diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreShownMessagesRepository.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreShownMessagesRepository.kt index 7a19022..afc939d 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreShownMessagesRepository.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/DatastoreShownMessagesRepository.kt @@ -10,25 +10,19 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import org.koin.core.annotation.InjectedParam -import org.koin.core.annotation.Named class DatastoreShownMessagesRepository( val shownMessagesDataStore: DataStore, @InjectedParam val coroutineScope: CoroutineScope ) : ShownMessagesRepository { - override fun getWasShownFlow(message: UserInformationMessage): Flow { - return shownMessagesDataStore.data.map { - (BuildConfig.FLAVOR != "play" && message.playOnly) || !when (message) { - UserInformationMessage.THANKS_FOR_PURCHASE -> it.thankPlayOne - } + override fun getWasShownFlow(message: UserInformationMessage): Flow = shownMessagesDataStore.data.map { + (BuildConfig.FLAVOR != "play" && message.playOnly) || !when (message) { + UserInformationMessage.THANKS_FOR_PURCHASE -> it.thankPlayOne } } - override suspend fun setShown( - message: UserInformationMessage, - shown: Boolean - ) { + override suspend fun setShown(message: UserInformationMessage, shown: Boolean) { shownMessagesDataStore.updateData { it.copy { when (message) { diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/RoomLastRouteRepository.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/RoomLastRouteRepository.kt index a7a7bd5..413cc57 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/RoomLastRouteRepository.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/repositories/RoomLastRouteRepository.kt @@ -1,12 +1,11 @@ package io.github.chrisimx.scanbridge.repositories import io.github.chrisimx.scanbridge.LastRouteRepository -import io.github.chrisimx.scanbridge.migrations.Migration import io.github.chrisimx.scanbridge.db.ScanBridgeDb import io.github.chrisimx.scanbridge.db.entities.LastRoute -import org.koin.core.annotation.InjectedParam +import io.github.chrisimx.scanbridge.migrations.Migration -class RoomLastRouteRepository(db: ScanBridgeDb): LastRouteRepository { +class RoomLastRouteRepository(db: ScanBridgeDb) : LastRouteRepository { val lastRouteDao = db.lastRouteDao() override suspend fun getLastRoute(): String? = lastRouteDao.getLastRoute()?.route @@ -19,9 +18,7 @@ class RoomLastRouteRepository(db: ScanBridgeDb): LastRouteRepository { } } -class LastRouteRepoAutoMigration(val a: LastRouteRepository, - val b: LastRouteRepository, - override val migrationId: String) : Migration { +class LastRouteRepoAutoMigration(val a: LastRouteRepository, val b: LastRouteRepository, override val migrationId: String) : Migration { override suspend fun migrate(db: ScanBridgeDb): Boolean { val toBeMigrated = a.getLastRoute() b.setLastRoute(toBeMigrated) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt index a9017b6..606ce6b 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/DefaultScanSettingsStore.kt @@ -22,13 +22,13 @@ package io.github.chrisimx.scanbridge.stores import android.content.Context import com.google.protobuf.StringValue import io.github.chrisimx.esclkt.ScanSettings +import io.github.chrisimx.scanbridge.ScanSettingsJson import io.github.chrisimx.scanbridge.datastore.appSettingsStore import io.github.chrisimx.scanbridge.datastore.updateSettings +import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData import io.github.chrisimx.scanbridge.proto.lastUsedScanSettingsOrNull import io.github.chrisimx.scanbridge.proto.lastUsedScanSettingsUiStateOrNull import io.github.chrisimx.scanbridge.proto.rememberScanSettingsOrNull -import io.github.chrisimx.scanbridge.ScanSettingsJson -import io.github.chrisimx.scanbridge.model.ScanSettingsEnterableData import kotlinx.coroutines.flow.first import timber.log.Timber diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt index 8650a12..027d52c 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/stores/LegacySessionsStore.kt @@ -4,6 +4,7 @@ import android.content.Context import androidx.room.immediateTransaction import androidx.room.useWriterConnection import io.github.chrisimx.esclkt.ScannerCapabilities +import io.github.chrisimx.scanbridge.ScanSettingsJson import io.github.chrisimx.scanbridge.data.model.LegacySessionV2 import io.github.chrisimx.scanbridge.data.model.LegacySessionV2.Companion.fromString import io.github.chrisimx.scanbridge.datastore.appSettingsStore @@ -12,7 +13,6 @@ import io.github.chrisimx.scanbridge.db.entities.ScannedPage import io.github.chrisimx.scanbridge.db.entities.Session import io.github.chrisimx.scanbridge.db.entities.TempFile import io.github.chrisimx.scanbridge.proto.copy -import io.github.chrisimx.scanbridge.ScanSettingsJson import java.io.File import java.nio.file.Files import kotlin.concurrent.atomics.AtomicBoolean @@ -104,10 +104,7 @@ object LegacySessionsStore { return this } - private suspend fun ScanBridgeDb.insertLegacySessionData( - sessionId: Uuid, - legacySession: LegacySessionV2 - ) { + private suspend fun ScanBridgeDb.insertLegacySessionData(sessionId: Uuid, legacySession: LegacySessionV2) { sessionDao().insertAll( Session(sessionId, legacySession.scanSettings, null) ) diff --git a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt index 866b9a1..8bfd0e2 100644 --- a/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt +++ b/androidApp/src/main/java/io/github/chrisimx/scanbridge/uicomponents/TitledCard.kt @@ -33,7 +33,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.github.chrisimx.scanbridge.theme.Poppins -import io.github.chrisimx.scanbridge.theme.PoppinsTypography import io.github.chrisimx.scanbridge.theme.Teal1 @Composable diff --git a/composeUI/build.gradle.kts b/composeUI/build.gradle.kts index b3a13b0..a7dc95b 100644 --- a/composeUI/build.gradle.kts +++ b/composeUI/build.gradle.kts @@ -1,5 +1,5 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { @@ -48,7 +48,6 @@ kotlin { jvmMain.dependencies { implementation(compose.desktop.currentOs) } - } targets @@ -70,6 +69,6 @@ dependencies { compose.resources { publicResClass = true - //packageOfResClass = "me.sample.library.resources" + // packageOfResClass = "me.sample.library.resources" generateResClass = always } diff --git a/composeUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt b/composeUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt index f28865f..0c3ef62 100644 --- a/composeUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt +++ b/composeUI/src/androidMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.android.kt @@ -1,28 +1,24 @@ package io.github.chrisimx.scanbridge.theme import android.os.Build -import androidx.annotation.RequiresApi import androidx.compose.material3.ColorScheme -import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext @Composable -actual fun platformDarkColorScheme(): ColorScheme? = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - val context = LocalContext.current - dynamicDarkColorScheme(context) - } else { - null - } +actual fun platformDarkColorScheme(): ColorScheme? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val context = LocalContext.current + dynamicDarkColorScheme(context) +} else { + null +} @Composable -actual fun platformLightColorScheme(): ColorScheme? = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - val context = LocalContext.current - dynamicLightColorScheme(context) - } else { - null - } +actual fun platformLightColorScheme(): ColorScheme? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val context = LocalContext.current + dynamicLightColorScheme(context) +} else { + null +} diff --git a/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt index 9b96bae..aa346b1 100644 --- a/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt +++ b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Theme.kt @@ -54,7 +54,6 @@ expect fun platformDarkColorScheme(): ColorScheme? @Composable expect fun platformLightColorScheme(): ColorScheme? - @Composable fun ScanBridgeTheme( darkTheme: Boolean = isSystemInDarkTheme(), @@ -64,7 +63,7 @@ fun ScanBridgeTheme( ) { val colorScheme = when { darkTheme -> platformDarkColorScheme() ?: DarkColorScheme - else -> platformLightColorScheme() ?: LightColorScheme + else -> platformLightColorScheme() ?: LightColorScheme } MaterialTheme( diff --git a/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt index 6ce5898..ecff228 100644 --- a/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt +++ b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/theme/Typography.kt @@ -1,46 +1,46 @@ package io.github.chrisimx.scanbridge.theme import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.Typography import androidx.compose.runtime.Composable import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp import org.jetbrains.compose.resources.Font -import scanbridge.composeui.generated.resources.Res -import androidx.compose.material3.Typography -import androidx.compose.ui.text.font.FontStyle import scanbridge.composeui.generated.resources.* +import scanbridge.composeui.generated.resources.Res @Composable fun Poppins(): FontFamily = FontFamily( - Font(Res.font.poppins_thin, weight = FontWeight.Thin), - Font(Res.font.poppins_thinitalic, weight = FontWeight.Thin, style = FontStyle.Italic), + Font(Res.font.poppins_thin, weight = FontWeight.Thin), + Font(Res.font.poppins_thinitalic, weight = FontWeight.Thin, style = FontStyle.Italic), - Font(Res.font.poppins_extralight, weight = FontWeight.ExtraLight), - Font(Res.font.poppins_extralightitalic, weight = FontWeight.ExtraLight, style = FontStyle.Italic), + Font(Res.font.poppins_extralight, weight = FontWeight.ExtraLight), + Font(Res.font.poppins_extralightitalic, weight = FontWeight.ExtraLight, style = FontStyle.Italic), - Font(Res.font.poppins_light, weight = FontWeight.Light), - Font(Res.font.poppins_lightitalic, weight = FontWeight.Light, style = FontStyle.Italic), + Font(Res.font.poppins_light, weight = FontWeight.Light), + Font(Res.font.poppins_lightitalic, weight = FontWeight.Light, style = FontStyle.Italic), - Font(Res.font.poppins_regular, weight = FontWeight.Normal), - Font(Res.font.poppins_italic, weight = FontWeight.Normal, style = FontStyle.Italic), + Font(Res.font.poppins_regular, weight = FontWeight.Normal), + Font(Res.font.poppins_italic, weight = FontWeight.Normal, style = FontStyle.Italic), - Font(Res.font.poppins_medium, weight = FontWeight.Medium), - Font(Res.font.poppins_mediumitalic, weight = FontWeight.Medium, style = FontStyle.Italic), + Font(Res.font.poppins_medium, weight = FontWeight.Medium), + Font(Res.font.poppins_mediumitalic, weight = FontWeight.Medium, style = FontStyle.Italic), - Font(Res.font.poppins_semibold, weight = FontWeight.SemiBold), - Font(Res.font.poppins_semibolditalic, weight = FontWeight.SemiBold, style = FontStyle.Italic), + Font(Res.font.poppins_semibold, weight = FontWeight.SemiBold), + Font(Res.font.poppins_semibolditalic, weight = FontWeight.SemiBold, style = FontStyle.Italic), - Font(Res.font.poppins_bold, weight = FontWeight.Bold), - Font(Res.font.poppins_bolditalic, weight = FontWeight.Bold, style = FontStyle.Italic), + Font(Res.font.poppins_bold, weight = FontWeight.Bold), + Font(Res.font.poppins_bolditalic, weight = FontWeight.Bold, style = FontStyle.Italic), - Font(Res.font.poppins_extrabold, weight = FontWeight.ExtraBold), - Font(Res.font.poppins_extrabolditalic, weight = FontWeight.ExtraBold, style = FontStyle.Italic), + Font(Res.font.poppins_extrabold, weight = FontWeight.ExtraBold), + Font(Res.font.poppins_extrabolditalic, weight = FontWeight.ExtraBold, style = FontStyle.Italic), - Font(Res.font.poppins_black, weight = FontWeight.Black), - Font(Res.font.poppins_blackitalic, weight = FontWeight.Black, style = FontStyle.Italic) - ) + Font(Res.font.poppins_black, weight = FontWeight.Black), + Font(Res.font.poppins_blackitalic, weight = FontWeight.Black, style = FontStyle.Italic) +) @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -195,5 +195,4 @@ fun PoppinsTypography(): Typography { letterSpacing = 0.sp ) ) - } diff --git a/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt index 55f7449..f0c4119 100644 --- a/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt +++ b/composeUI/src/commonMain/kotlin/io/github/chrisimx/scanbridge/uicomponents/LoadingScreen.kt @@ -22,8 +22,6 @@ package io.github.chrisimx.scanbridge.uicomponents import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.runtime.Composable -import org.jetbrains.compose.resources.StringResource import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -32,6 +30,7 @@ import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight @@ -40,6 +39,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.github.chrisimx.scanbridge.theme.ScanBridgeTheme +import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.stringResource import scanbridge.composeui.generated.resources.Res import scanbridge.composeui.generated.resources.trying_to_retrieve_scannercapabilities diff --git a/core/build.gradle.kts b/core/build.gradle.kts index f53b24e..329bec1 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,5 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { @@ -28,7 +28,6 @@ kotlin { compileSdk = 36 minSdk = 23 - compilerOptions { jvmTarget.set( org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 @@ -65,7 +64,6 @@ kotlin { jvmMain.dependencies { } - } targets diff --git a/core/src/androidMain/kotlin/AndroidHttpClientFactory.kt b/core/src/androidMain/kotlin/AndroidHttpClientFactory.kt index dae4a62..dca1f40 100644 --- a/core/src/androidMain/kotlin/AndroidHttpClientFactory.kt +++ b/core/src/androidMain/kotlin/AndroidHttpClientFactory.kt @@ -7,33 +7,32 @@ import io.ktor.client.plugins.HttpTimeout import io.ktor.client.plugins.logging.Logger import io.ktor.client.plugins.logging.Logging -class AndroidHttpClientFactory(loggerFactory: ScanBridgeLoggerFactory): HttpClientFactory { +class AndroidHttpClientFactory(loggerFactory: ScanBridgeLoggerFactory) : HttpClientFactory { val httpClientLogger = loggerFactory.withTag("AndroidHttpClient") - override fun create(config: HttpClientConfig): HttpClient = - HttpClient(OkHttp) { - install(HttpTimeout) { - requestTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 - connectTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 - socketTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 - } - if (config.debugLogging) { - install(Logging) { - logger = object : Logger { - override fun log(message: String) { - httpClientLogger.debug { message } - } + override fun create(config: HttpClientConfig): HttpClient = HttpClient(OkHttp) { + install(HttpTimeout) { + requestTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 + connectTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 + socketTimeoutMillis = config.timeoutInSeconds.toLong() * 1000 + } + if (config.debugLogging) { + install(Logging) { + logger = object : Logger { + override fun log(message: String) { + httpClientLogger.debug { message } } } } - if (config.disableCertValidation) { - engine { - config { - val (socketFactory, trustManager) = getTrustAllTM() - sslSocketFactory(socketFactory, trustManager) - hostnameVerifier { _, _ -> true } - } + } + if (config.disableCertValidation) { + engine { + config { + val (socketFactory, trustManager) = getTrustAllTM() + sslSocketFactory(socketFactory, trustManager) + hostnameVerifier { _, _ -> true } } } } + } } diff --git a/core/src/androidMain/kotlin/AndroidScanBridgeDbBuilderFactory.kt b/core/src/androidMain/kotlin/AndroidScanBridgeDbBuilderFactory.kt index fa28549..8f522fe 100644 --- a/core/src/androidMain/kotlin/AndroidScanBridgeDbBuilderFactory.kt +++ b/core/src/androidMain/kotlin/AndroidScanBridgeDbBuilderFactory.kt @@ -1,8 +1,8 @@ import android.content.Context import androidx.room.Room import androidx.room.RoomDatabase -import io.github.chrisimx.scanbridge.db.ScanBridgeDbBuilderFactory import io.github.chrisimx.scanbridge.db.ScanBridgeDb +import io.github.chrisimx.scanbridge.db.ScanBridgeDbBuilderFactory class AndroidScanBridgeDbBuilderFactory(private val context: Context) : ScanBridgeDbBuilderFactory { override fun getBuilder(): RoomDatabase.Builder { diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt index f4f9d54..376e8f4 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/ScanBridgeDb.kt @@ -22,7 +22,9 @@ import io.github.chrisimx.scanbridge.db.typeconverters.UrlTypeConverter import io.github.chrisimx.scanbridge.db.typeconverters.UuidTypeConverter @Database( - entities = [CustomScanner::class, ScannedPage::class, Session::class, TempFile::class, LastRoute::class, ExecutedMigrationToRoom::class], + entities = [ + CustomScanner::class, ScannedPage::class, Session::class, TempFile::class, LastRoute::class, ExecutedMigrationToRoom::class + ], version = 4, autoMigrations = [ AutoMigration( diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt index 7f97732..88d2168 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/ExecutedMigrationToRoom.kt @@ -6,5 +6,5 @@ import androidx.room.PrimaryKey @Entity(tableName = "executedmigrationtoroom") data class ExecutedMigrationToRoom( @PrimaryKey - val migrationId: String, + val migrationId: String ) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt index ec5af8f..7a233d2 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/db/entities/LastRoute.kt @@ -4,7 +4,4 @@ import androidx.room.Entity import androidx.room.PrimaryKey @Entity(tableName = "lastroute") -data class LastRoute ( - val route: String, - @PrimaryKey val id: Int = 1 -) +data class LastRoute(val route: String, @PrimaryKey val id: Int = 1) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLogger.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLogger.kt index 41b1de6..5a4d04b 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLogger.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/infrastructure/KmLogScanBridgeLogger.kt @@ -4,9 +4,7 @@ import com.diamondedge.logging.KmLog import com.diamondedge.logging.logging import io.github.chrisimx.scanbridge.ports.ScanBridgeLogger -class KmLogScanBridgeLogger( - tag: String -) : ScanBridgeLogger { +class KmLogScanBridgeLogger(tag: String) : ScanBridgeLogger { private val logger: KmLog = logging(tag) override fun verbose(tag: String?, msg: () -> String) { @@ -17,7 +15,7 @@ class KmLogScanBridgeLogger( logger.d(tag, msg) } - override fun info(tag: String?, msg: () -> String,) { + override fun info(tag: String?, msg: () -> String) { logger.i(tag, msg) } diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/HttpClientConfig.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/HttpClientConfig.kt index 0064e1b..16484b2 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/HttpClientConfig.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/HttpClientConfig.kt @@ -1,7 +1,3 @@ package io.github.chrisimx.scanbridge.model -data class HttpClientConfig( - val disableCertValidation: Boolean, - val debugLogging: Boolean, - val timeoutInSeconds: ULong -) +data class HttpClientConfig(val disableCertValidation: Boolean, val debugLogging: Boolean, val timeoutInSeconds: ULong) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanBridgeFile.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanBridgeFile.kt index fd80189..4fe327c 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanBridgeFile.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanBridgeFile.kt @@ -2,8 +2,4 @@ package io.github.chrisimx.scanbridge.model import kotlinx.io.files.Path -data class ScanBridgeFile( - val path: Path -) - - +data class ScanBridgeFile(val path: Path) diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt index f32e597..7180690 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/model/ScanSettingsEnterableData.kt @@ -5,7 +5,6 @@ import io.github.chrisimx.scanbridge.PaperFormat import io.github.chrisimx.scanbridge.loadDefaultFormats import kotlinx.serialization.Serializable - @Serializable data class ScanSettingsEnterableData( val capabilities: ScannerCapabilities, diff --git a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLoggerFactory.kt b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLoggerFactory.kt index 6cae72a..05f8800 100644 --- a/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLoggerFactory.kt +++ b/core/src/commonMain/kotlin/io/github/chrisimx/scanbridge/ports/ScanBridgeLoggerFactory.kt @@ -1,6 +1,5 @@ package io.github.chrisimx.scanbridge.ports -import io.github.chrisimx.scanbridge.infrastructure.KmLogScanBridgeLogger import io.github.chrisimx.scanbridge.ports.ScanBridgeLogger import kotlin.reflect.KClass diff --git a/core/src/iosMain/kotlin/IosScanBridgeDbBuilderFactory.kt b/core/src/iosMain/kotlin/IosScanBridgeDbBuilderFactory.kt index 3e49642..561cafe 100644 --- a/core/src/iosMain/kotlin/IosScanBridgeDbBuilderFactory.kt +++ b/core/src/iosMain/kotlin/IosScanBridgeDbBuilderFactory.kt @@ -11,7 +11,7 @@ class IosScanBridgeDbBuilderFactory : ScanBridgeDbBuilderFactory { override fun getBuilder(): RoomDatabase.Builder { val dbFilePath = documentDirectory() + "/scanbridge.db" return Room.databaseBuilder( - name = dbFilePath, + name = dbFilePath ) } @@ -22,7 +22,7 @@ class IosScanBridgeDbBuilderFactory : ScanBridgeDbBuilderFactory { inDomain = NSUserDomainMask, appropriateForURL = null, create = false, - error = null, + error = null ) return requireNotNull(documentDirectory?.path) } diff --git a/desktopApp/src/main/kotlin/main.kt b/desktopApp/src/main/kotlin/Main.kt similarity index 91% rename from desktopApp/src/main/kotlin/main.kt rename to desktopApp/src/main/kotlin/Main.kt index 65386b0..be25196 100644 --- a/desktopApp/src/main/kotlin/main.kt +++ b/desktopApp/src/main/kotlin/Main.kt @@ -2,17 +2,16 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window import androidx.compose.ui.window.application import androidx.compose.ui.window.rememberWindowState -import java.awt.Dimension import io.github.chrisimx.scanbridge.App +import java.awt.Dimension fun main() = application { Window( title = "ScanBridge", state = rememberWindowState(width = 800.dp, height = 600.dp), - onCloseRequest = ::exitApplication, + onCloseRequest = ::exitApplication ) { window.minimumSize = Dimension(350, 600) App() } } -