feat: convert Zayit to Kotlin Multiplatform (JVM + Android + iOS)#506
Open
kdroidFilter wants to merge 3 commits into
Open
feat: convert Zayit to Kotlin Multiplatform (JVM + Android + iOS)#506kdroidFilter wants to merge 3 commits into
kdroidFilter wants to merge 3 commits into
Conversation
kdroidFilter
force-pushed
the
feat/kmp-multiplatform
branch
from
June 22, 2026 15:55
671f905 to
a54c828
Compare
Group search results by book into one deduplicated card per book: the top hit shown prominently, locations in a leading reference column, matched terms in gold, and the remaining hits in a fixed-height, scrollable list. Reuse the book pane's ContentAwareScrollbarShell so the expanded list and the main results list both get a themed, stable scrollbar thumb (sized from the facet book count, so it no longer shrinks as more pages load). - ViewModel: expose bookFacetCountsFlow and loadAllHitsForBook(bookId) - TabsContent: wire book counts and the per-book hit loader into the shell - strings: add search_more_in_book / search_collapse Signed-off-by: Elie Gambache <elyahou.hadass@gmail.com>
…iOS) The whole project is now KMP. JVM desktop is unchanged; Android and iOS build with stub UIs, and everything platform-agnostic moved into commonMain. leaf libraries (icons, texteffects, navigation, pagination, htmlparser, logger) - add Android + iOS targets - logger: Sentry + timestamp behind expect/actual (JVM=Sentry, mobile=stub), kotlin.concurrent.Volatile, drop @JvmField - navigation: java.util.UUID -> kotlin.uuid.Uuid; nowEpochMillis via kotlin.time.Clock - htmlparser: jsoup -> ksoup 0.2.6 (parser runs on all platforms) SeforimApp - add Android (KMP library) + iOS targets; iOS framework + MainViewController entry - relocate JVM-only deps (Nucleus, network, releasefetcher, ktor-cio) commonMain -> jvmMain - move ~75 files of platform-agnostic code (onboarding/settings/search use-cases, state, AppSettings, core utils, theme enums) into commonMain - AccentColor split: enum in commonMain, Jewel/Nucleus color resolution in jvmMain - search engine via common SearchEngine interface (JVM=Lucene, mobile=StubSearchEngine) - stub App() for Android/iOS; Jewel/Nucleus/Lucene/AWT desktop UI stays in jvmMain androidApp - new thin com.android.application module (AGP 9 forbids it in the KMP module) that hosts the launchable APK and depends on :SeforimApp build - AGP 9.1.1 built-in Kotlin (no kotlin-android plugin), compileSdk 36, android.library plugin available to subprojects, SeforimLibrary submodule bump Signed-off-by: Elie Gambache <elyahou.hadass@gmail.com>
Signed-off-by: Elie Gambache <elyahou.hadass@gmail.com>
kdroidFilter
force-pushed
the
feat/kmp-multiplatform
branch
from
June 22, 2026 16:13
98351c1 to
1308e0b
Compare
kdroidFilter
marked this pull request as ready for review
June 22, 2026 16:50
There was a problem hiding this comment.
Pull request overview
This PR migrates Zayit to Kotlin Multiplatform (JVM + Android + iOS), moving platform-agnostic logic into commonMain, keeping JVM-only dependencies in jvmMain, and adding thin Android/iOS entrypoints so mobile targets compile with placeholder UI.
Changes:
- Introduces KMP targets (Android library + iOS frameworks) across the app and several leaf modules, and adds a new
:androidApplauncher module. - Moves/introduces shared domain + UI-support code into
commonMain(onboarding/settings/search/state/utils), while keeping desktop/JVM-only integrations injvmMain. - Enhances desktop search results UI with grouped-per-book result cards and adds exact per-book facet counts + “expand all hits in book” behavior.
Reviewed changes
Copilot reviewed 43 out of 114 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| texteffects/build.gradle.kts | Adds Android + iOS targets and Android namespace/sdk config for texteffects. |
| settings.gradle.kts | Registers new :androidApp module in the build. |
| SeforimApp/src/jvmTest/.../ResultsIndexingUseCaseTest.kt | Updates assertion to match new index identity strategy. |
| SeforimApp/src/jvmTest/.../CopyWithSourceE2ETest.kt | Adapts catalog loading to suspend API via runBlocking. |
| SeforimApp/src/jvmTest/.../CatalogAccessTest.kt | Adapts catalog loading to suspend API via runBlocking. |
| SeforimApp/src/jvmMain/.../DatabaseUtils.kt | Wraps suspend catalog load in runBlocking inside JVM cache loader. |
| SeforimApp/src/jvmMain/.../DisplaySettingsScreen.kt | Updates theme-related import usage for JVM UI. |
| SeforimApp/src/jvmMain/.../SearchResultViewModel.kt | Adds per-book facet counts flow and a method to load all hits for a book. |
| SeforimApp/src/jvmMain/.../SearchResultScreen.kt | Reworks results UI into grouped per-book cards with expansion + custom scrollbar behavior. |
| SeforimApp/src/jvmMain/.../DownloadViewModel.kt | Makes @Volatile annotation explicit for KMP compilation. |
| SeforimApp/src/jvmMain/.../HomeView.kt | Updates theme import usage for JVM UI. |
| SeforimApp/src/jvmMain/.../HomeCelestialWidgets.kt | Updates theme color resolution import usage for JVM UI. |
| SeforimApp/src/jvmMain/.../core/presentation/theme/AccentColorColors.kt | Adds JVM-specific color resolution extensions for common AccentColor. |
| SeforimApp/src/jvmMain/.../core/presentation/theme/AccentColor.kt | Removes JVM-only AccentColor enum (moved to common). |
| SeforimApp/src/jvmMain/.../core/presentation/tabs/TabsContent.kt | Plumbs new book facet counts and book-hit loader into search tab UI. |
| SeforimApp/src/iosMain/.../MainViewController.kt | Adds iOS entrypoint returning a ComposeUIViewController hosting App(). |
| SeforimApp/src/commonMain/.../framework/di/AppScope.kt | Adds app-wide DI scope marker for Metro. |
| SeforimApp/src/commonMain/.../framework/di/AppMetroViewModelFactory.kt | Adds Metro ViewModel factory wiring for common ViewModels. |
| SeforimApp/src/commonMain/.../features/zmanim/data/Cities.kt | Adds shared country/city coordinate dataset for region/zmanim features. |
| SeforimApp/src/commonMain/.../features/settings/SettingsWindowViewModel.kt | Adds shared settings-window visibility ViewModel. |
| SeforimApp/src/commonMain/.../features/settings/SettingsWindowState.kt | Adds settings window state model. |
| SeforimApp/src/commonMain/.../features/settings/SettingsWindowEvents.kt | Adds settings window events model. |
| SeforimApp/src/commonMain/.../features/settings/navigation/SettingsDestination.kt | Adds serializable settings destinations for navigation. |
| SeforimApp/src/commonMain/.../features/settings/general/GeneralSettingsViewModel.kt | Adds shared General Settings ViewModel backed by AppSettings. |
| SeforimApp/src/commonMain/.../features/settings/general/GeneralSettingsState.kt | Adds shared General Settings state model. |
| SeforimApp/src/commonMain/.../features/settings/general/GeneralSettingsEvents.kt | Adds events model for General Settings. |
| SeforimApp/src/commonMain/.../features/settings/fonts/FontsSettingsViewModel.kt | Adds shared Fonts Settings ViewModel backed by AppSettings. |
| SeforimApp/src/commonMain/.../features/settings/fonts/FontsSettingsState.kt | Adds shared Fonts Settings state model. |
| SeforimApp/src/commonMain/.../features/settings/fonts/FontsSettingsEvents.kt | Adds events model for Fonts Settings. |
| SeforimApp/src/commonMain/.../features/settings/display/DisplaySettingsViewModel.kt | Adds shared Display Settings ViewModel backed by AppSettings. |
| SeforimApp/src/commonMain/.../features/settings/display/DisplaySettingsState.kt | Adds shared Display Settings state model. |
| SeforimApp/src/commonMain/.../features/settings/display/DisplaySettingsEvents.kt | Adds events model for Display Settings. |
| SeforimApp/src/commonMain/.../features/settings/dbupdate/DbDeltaUpdateState.kt | Adds shared UI state surface for DB delta update panel. |
| SeforimApp/src/commonMain/.../features/settings/dbupdate/DbDeltaUpdateEvents.kt | Adds events model for DB delta update panel. |
| SeforimApp/src/commonMain/.../features/settings/data/DataSettingsState.kt | Adds shared Data settings state model (import/export/reset flags). |
| SeforimApp/src/commonMain/.../features/search/SearchFilter.kt | Adds shared search mode enum for Home search. |
| SeforimApp/src/commonMain/.../features/search/domain/ResultsIndexingUseCase.kt | Updates caching/identity and parallel filtering to be KMP-friendly. |
| SeforimApp/src/commonMain/.../features/search/domain/GetBreadcrumbPiecesUseCase.kt | Adds shared use case for breadcrumb resolution with internal caching. |
| SeforimApp/src/commonMain/.../features/search/domain/CategoryNavigationUseCase.kt | Adds shared category navigation use case with caching. |
| SeforimApp/src/commonMain/.../features/onboarding/userprofile/UserProfileViewModel.kt | Adds shared onboarding user-profile ViewModel/state/events. |
| SeforimApp/src/commonMain/.../features/onboarding/userprofile/UserProfileUseCase.kt | Adds shared user-profile helper use case. |
| SeforimApp/src/commonMain/.../features/onboarding/userprofile/UserProfileState.kt | Adds shared user-profile state. |
| SeforimApp/src/commonMain/.../features/onboarding/userprofile/UserProfileEvents.kt | Adds shared user-profile events. |
| SeforimApp/src/commonMain/.../features/onboarding/userprofile/Community.kt | Adds shared community enum. |
| SeforimApp/src/commonMain/.../features/onboarding/typeofinstall/TypeOfInstallationViewModel.kt | Adds shared onboarding step ViewModel for install type. |
| SeforimApp/src/commonMain/.../features/onboarding/typeofinstall/TypeOfInstallationState.kt | Adds shared onboarding state model for install type. |
| SeforimApp/src/commonMain/.../features/onboarding/typeofinstall/TypeOfInstallationEvents.kt | Adds events model for install type selection. |
| SeforimApp/src/commonMain/.../features/onboarding/region/RegionConfigViewModel.kt | Adds shared region config ViewModel reading/writing AppSettings. |
| SeforimApp/src/commonMain/.../features/onboarding/region/RegionConfigUseCase.kt | Adds shared region config use case backed by worldPlaces. |
| SeforimApp/src/commonMain/.../features/onboarding/region/RegionConfigState.kt | Adds shared region config state + preview data. |
| SeforimApp/src/commonMain/.../features/onboarding/region/RegionConfigEvents.kt | Adds events model for region selection. |
| SeforimApp/src/commonMain/.../features/onboarding/navigation/ProgressBarState.kt | Adds shared progress controller singleton for onboarding UI. |
| SeforimApp/src/commonMain/.../features/onboarding/navigation/OnBoardingDestination.kt | Adds serializable onboarding destinations. |
| SeforimApp/src/commonMain/.../features/onboarding/extract/ExtractState.kt | Adds shared state model for extraction step. |
| SeforimApp/src/commonMain/.../features/onboarding/extract/ExtractEvents.kt | Adds events model for extraction step. |
| SeforimApp/src/commonMain/.../features/onboarding/download/DownloadState.kt | Adds shared download state + error categorization. |
| SeforimApp/src/commonMain/.../features/onboarding/download/DownloadEvents.kt | Adds events model for download flow. |
| SeforimApp/src/commonMain/.../features/onboarding/diskspace/AvailableDiskSpaceState.kt | Adds shared state for disk space checks. |
| SeforimApp/src/commonMain/.../features/onboarding/diskspace/AvailableDiskSpaceEvents.kt | Adds events model for disk space screen. |
| SeforimApp/src/commonMain/.../features/onboarding/data/OnboardingProcessRepository.kt | Adds shared transient onboarding process repository (e.g., pending .zst path). |
| SeforimApp/src/commonMain/.../features/database/update/navigation/DatabaseUpdateProgressBarState.kt | Adds shared progress controller for DB update flow. |
| SeforimApp/src/commonMain/.../features/database/update/navigation/DatabaseUpdateDestination.kt | Adds serializable destinations for DB update flow. |
| SeforimApp/src/commonMain/.../features/bookcontent/ui/panels/.../SelectionBarLogic.kt | Extracts selection-bar decision logic into shared helper functions. |
| SeforimApp/src/commonMain/.../features/bookcontent/ui/panels/.../ScrollbarMetrics.kt | Adds shared scrollbar measurement helpers and binary search utilities. |
| SeforimApp/src/commonMain/.../features/bookcontent/ui/panels/.../HomeCelestialWidgetsViewModel.kt | Adds shared ViewModel for home zmanim widgets using region settings. |
| SeforimApp/src/commonMain/.../features/bookcontent/ui/panels/.../BookContentZoomInteraction.kt | Adds composition local for zoom interaction state. |
| SeforimApp/src/commonMain/.../features/bookcontent/ui/components/SelectionWorkarounds.kt | Adds shared safe selection container workaround for Compose crash. |
| SeforimApp/src/commonMain/.../features/bookcontent/state/StateKeys.kt | Centralizes persisted state keys for book content. |
| SeforimApp/src/commonMain/.../features/bookcontent/state/SplitDefaults.kt | Centralizes split-pane default constants. |
| SeforimApp/src/commonMain/.../features/bookcontent/state/LineConnectionsSnapshot.kt | Adds shared snapshot model for line connection data. |
| SeforimApp/src/commonMain/.../features/bookcontent/state/CommentatorGroup.kt | Adds shared models for commentaries grouping UI. |
| SeforimApp/src/commonMain/.../features/bookcontent/state/BookOpenSource.kt | Adds shared enum to tag origins of “open book” actions. |
| SeforimApp/src/commonMain/.../features/bookcontent/BookContentEvent.kt | Moves/introduces a shared sealed event model for book content interactions. |
| SeforimApp/src/commonMain/.../core/settings/AppSettings.kt | Makes @Volatile explicit for KMP compatibility. |
| SeforimApp/src/commonMain/.../core/selection/SelectionContext.kt | Introduces shared selection context interface + default implementation. |
| SeforimApp/src/commonMain/.../core/presentation/utils/WindowViewModelOwner.kt | Adds a window-scoped ViewModelStoreOwner for Compose windows. |
| SeforimApp/src/commonMain/.../core/presentation/utils/TouchMode.kt | Adds shared touch-mode detection composition local + modifier. |
| SeforimApp/src/commonMain/.../core/presentation/utils/FormatUtils.kt | Replaces String.format with a multiplatform-friendly formatting helper. |
| SeforimApp/src/commonMain/.../core/presentation/theme/ThemeStyle.kt | Adds shared theme-style enum. |
| SeforimApp/src/commonMain/.../core/presentation/theme/IntUiThemes.kt | Adds shared light/dark/system enum. |
| SeforimApp/src/commonMain/.../core/presentation/theme/AccentColor.kt | Moves the persisted AccentColor enum to commonMain. |
| SeforimApp/src/commonMain/.../core/presentation/text/HebrewSearch.kt | Adds shared Hebrew-aware diacritic stripping + matching utilities. |
| SeforimApp/src/commonMain/.../core/presentation/navigation/NoAnimatedComposable.kt | Adds shared navigation builder helper using disabled transitions on JVM. |
| SeforimApp/src/commonMain/.../core/presentation/components/ProgressBarController.kt | Adds shared reactive progress controller base class. |
| SeforimApp/src/commonMain/.../core/presentation/components/HardDriveUpload.kt | Adds shared vector asset definition for installer/update UI. |
| SeforimApp/src/commonMain/.../core/MainAppState.kt | Adds shared app-level state holder (theme/onboarding) backed by AppSettings. |
| SeforimApp/src/commonMain/.../core/coroutines/CoroutineUtils.kt | Adds coroutine-safe runSuspendCatching helper. |
| SeforimApp/src/commonMain/.../core/catalog/CatalogAccess.kt | Makes @Volatile explicit for KMP compatibility. |
| SeforimApp/src/commonMain/.../core/annotations/HighlightSelectionResolver.kt | Adds shared highlight range resolution for (multi-line) selections. |
| SeforimApp/src/commonMain/kotlin/.../App.kt | Adds shared (stub) mobile app entry composable. |
| SeforimApp/src/commonMain/composeResources/values/strings.xml | Adds new Hebrew strings for “more in book” and “collapse” in search. |
| SeforimApp/src/androidMain/.../Theme.android.kt | Removes Android-only SystemAppearance implementation (moved/obsolete in KMP refactor). |
| SeforimApp/build.gradle.kts | Converts SeforimApp to an Android library KMP module, adds iOS frameworks, relocates JVM-only deps. |
| pagination/src/commonMain/.../LinesPagingSource.kt | Replaces Java reflection usage with KMP-safe ::class. |
| pagination/build.gradle.kts | Adds Android + iOS targets and Android namespace/sdk config for pagination. |
| navigation/src/commonMain/.../TabsViewModel.kt | Replaces java.util.UUID with kotlin.uuid.Uuid and uses shared epoch time helper. |
| navigation/src/commonMain/.../PlatformTime.kt | Adds multiplatform epoch-millis helper using Clock. |
| navigation/build.gradle.kts | Adds Android + iOS targets and includes kotlinx-datetime for time support. |
| logger/src/jvmMain/.../Logger.jvm.kt | Adds JVM crash reporting implementation via Sentry for the new expect/actual logger API. |
| logger/src/iosMain/.../Logger.ios.kt | Adds iOS timestamp implementation and stubs crash reporting. |
| logger/src/commonMain/.../Logger.kt | Refactors logger into expect/actual timestamp + crash reporting; removes JVM-only code from common. |
| logger/src/androidMain/.../Logger.android.kt | Adds Android crash-report stubs for expect/actual logger API. |
| logger/src/androidJvmMain/.../Logger.jvmAndroid.kt | Adds shared JVM/Android timestamp formatting implementation. |
| logger/build.gradle.kts | Makes logger multiplatform (Android + iOS) and defines an androidJvmMain shared source set. |
| icons/build.gradle.kts | Adds Android + iOS targets and Android namespace/sdk config for icons. |
| htmlparser/src/commonMain/.../HtmlParser.kt | Switches HTML parsing from jsoup to ksoup for iOS compatibility. |
| htmlparser/build.gradle.kts | Adds Android + iOS targets and swaps dependency from jsoup to ksoup. |
| gradle/libs.versions.toml | Adds ksoup dependency version and module coordinates. |
| build.gradle.kts | Adds android-library plugin alias for subprojects. |
| androidApp/src/main/AndroidManifest.xml | Adds new Android launcher manifest pointing at shared AppActivity. |
| androidApp/build.gradle.kts | Adds thin Android application module that depends on :SeforimApp. |
Comments suppressed due to low confidence (2)
SeforimApp/src/commonMain/kotlin/io/github/kdroidfilter/seforimapp/features/search/domain/ResultsIndexingUseCase.kt:66
ensureIndexcan return a stalecachedIndex:cachedResultsis updated to the newresultslist before the new index is assigned, so a concurrent caller can observecachedResults === resultswhilecachedIndexstill points at the previous index and return it from this fast-path.
androidApp/src/main/AndroidManifest.xml:7- The Android
android:labelis hardcoded. For localization (and consistency with the project guideline of not hardcoding user-visible text), it should reference an Android string resource (e.g.@string/app_name) defined inandroidApp/src/main/res/values/strings.xml.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Converts the whole project to Kotlin Multiplatform. The JVM desktop app is
unchanged; Android and iOS now build, with stub UIs, and everything that is
platform-agnostic has moved into
commonMain. JVM-only code (Jewel, Nucleus,Lucene, AWT, JDBC, jsoup) stays in
jvmMain.Build matrix (all verified)
SeforimApp.frameworklinks (MainViewControllerentry):androidApp:assembleDebugproduces an APK (~15 MB)Highlights
icons,texteffects,navigation,pagination,htmlparser,logger) → multiplatform.htmlparserswaps jsoup for ksoup so the parserruns on iOS;
loggerputs Sentry behind expect/actual;navigationuseskotlin.uuid.Uuid+kotlin.time.Clock.platform-agnostic code (onboarding / settings / search use-cases, state,
AppSettings, core utils, theme enums) moved tocommonMain. JVM-only depsrelocated to
jvmMain.AccentColorsplit into a common enum + a jvm colorresolver. Search behind a common
SearchEngineinterface (JVM = Lucene,mobile =
StubSearchEngine).androidApp— new thincom.android.applicationmodule hosting the APK(AGP 9 forbids the application plugin inside the KMP module), depending on
:SeforimApp.kotlin-androidplugin),compileSdk 36,AGP/Kotlin aligned across the composite build.
Not in scope
The Android/iOS UI is a placeholder
App()and the mobile search engine is ano-op stub. Implementing the real mobile UI + a mobile search backend (and
abstracting the desktop split-panes out of bookcontent state to move even more
into common) are follow-ups. Opened as draft for that reason.