Kotlin Multiplatform sync/data stack for Quran mobile apps.
This repository contains shared modules used by Android and iOS apps for:
- Authentication (OIDC)
- Local persistence (SQLDelight)
- Sync engine orchestration
- A unified app-level service API (
SyncService)
- Architecture
- Modules
- Requirements
- Quick Start
- Usage
- Run the Demos
- Build, Test, and Release Commands
- Related Repositories
auth + persistence + syncengine are composed in sync-pipelines, exposed through a DI graph (AppGraph / SharedDependencyGraph), and exported to iOS through umbrella.
flowchart LR
UI[Android/iOS UI] --> S[SyncService]
S --> A[Auth Module]
S --> P[Persistence Module]
S --> E[SyncEngine Module]
U[Umbrella XCFramework] --> UI
| Module | Purpose |
|---|---|
:auth |
OIDC login/logout, auth state, token handling |
:persistence |
SQLDelight DB, repositories for bookmarks/collections/notes/recent pages |
:syncengine |
Core sync engine and scheduling |
:sync-pipelines |
DI graph and SyncService orchestration API |
:umbrella |
iOS XCFramework export (Shared.xcframework) |
:demo:android |
Android sample app (Compose) |
:demo:common |
Shared demo helpers/models |
:mutations-definitions |
Shared mutation/domain definitions |
- JDK 17
- Android Studio (for Android demo)
- Xcode (for iOS demo)
- Cocoa toolchain for iOS simulator/device builds
Optional but recommended:
local.propertieswith OAuth credentials:
OAUTH_CLIENT_ID=your_client_id
OAUTH_CLIENT_SECRET=your_client_secret- Clone and enter the repo:
git clone https://github.com/quran/mobile-sync.git
cd mobile-sync- Ensure Gradle can resolve dependencies:
./gradlew help- Run tests:
./gradlew allTests --stacktrace --continueimport com.quran.shared.auth.di.AuthFlowFactoryProvider
import com.quran.shared.persistence.DriverFactory
import com.quran.shared.pipeline.di.SharedDependencyGraph
import com.quran.shared.syncengine.SynchronizationEnvironment
import org.publicvalue.multiplatform.oidc.appsupport.AndroidCodeAuthFlowFactory
val authFactory = AndroidCodeAuthFlowFactory(useWebView = false)
authFactory.registerActivity(activity)
AuthFlowFactoryProvider.initialize(authFactory)
val graph = SharedDependencyGraph.init(
driverFactory = DriverFactory(context = applicationContext),
environment = SynchronizationEnvironment(
endPointURL = "https://apis-prelive.quran.foundation/auth"
)
)
val authService = graph.authService
val syncService = graph.syncServiceimport Shared
final class AppContainer {
static let shared = AppContainer()
static var graph: AppGraph { shared.graph }
let graph: AppGraph
private init() {
Shared.AuthFlowFactoryProvider.shared.doInitialize()
let driverFactory = DriverFactory()
let environment = SynchronizationEnvironment(
endPointURL: "https://apis-prelive.quran.foundation/auth"
)
graph = SharedDependencyGraph.shared.doInit(
driverFactory: driverFactory,
environment: environment
)
}
}Core API examples:
- Observe:
authState,bookmarks,collectionsWithBookmarks,notes - Mutations:
addBookmark,deleteBookmark,addCollection,deleteCollection,addNote,deleteNote - Trigger sync:
triggerSync()
Lifecycle note:
SyncServiceis app-scoped. Initialize once viaSharedDependencyGraph.init(...).- Do not clear app-scoped services from UI/view-model teardown.
auth uses BuildKonfig flavor to expose build type values.
Default (gradle.properties):
buildkonfig.flavor=debugOverride for release-like builds:
./gradlew :auth:build -Pbuildkonfig.flavor=release- Open project in Android Studio.
- Run
demo/androidapp module.
CLI build example:
./gradlew :demo:android:assembleDebug- Open:
demo/apple/QuranSyncDemo/QuranSyncDemo.xcodeproj - Select
QuranSyncDemoscheme. - Run on an iOS Simulator.
The Xcode project includes a Run Script phase that calls:
./gradlew :umbrella:embedAndSignAppleFrameworkForXcodeCLI build example:
xcodebuild -project demo/apple/QuranSyncDemo/QuranSyncDemo.xcodeproj \
-scheme QuranSyncDemo \
-configuration Debug \
-destination 'generic/platform=iOS Simulator' \
build CODE_SIGNING_ALLOWED=NOBuild all:
./gradlew buildRun all tests:
./gradlew allTests --stacktrace --continueBuild iOS XCFramework:
./gradlew :umbrella:assembleSharedXCFrameworkBuild Android demo compile target:
./gradlew :demo:android:compileDebugKotlinBuild iOS KMP target:
./gradlew :sync-pipelines:compileKotlinIosSimulatorArm64