mirror of
https://github.com/igorescodro/alkaa.git
synced 2025-05-17 19:16:02 +08:00
🚧 WIP
This commit is contained in:
18
.github/workflows/build.yml
vendored
18
.github/workflows/build.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew clean build test -x shared:testDebugUnitTest -x shared:testReleaseUnitTest --parallel
|
||||
run: ./gradlew clean build test -x shared:testDebugUnitTest -x shared:testReleaseUnitTest -x shared:desktopTest --parallel
|
||||
env:
|
||||
ALKAA_KEY_ALIAS: ${{ secrets.ALKAA_KEY_ALIAS }}
|
||||
ALKAA_KEY_PASSWORD: ${{ secrets.ALKAA_KEY_PASSWORD }}
|
||||
@ -49,3 +49,19 @@ jobs:
|
||||
|
||||
- name: Build with Xcode
|
||||
run: xcodebuild -workspace ios-app/alkaa.xcodeproj/project.xcworkspace -configuration Debug -scheme alkaa -sdk iphonesimulator
|
||||
|
||||
build-desktop:
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '19'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew desktop-app:createDistributable
|
||||
|
33
.github/workflows/instrumented_tests.yml
vendored
33
.github/workflows/instrumented_tests.yml
vendored
@ -90,6 +90,37 @@ jobs:
|
||||
with:
|
||||
name: test-results
|
||||
path: |
|
||||
/Users/runner/work/alkaa/alkaa/app/build/reports/androidTests/
|
||||
/Users/runner/work/alkaa/alkaa/app/build/reports/tests/
|
||||
./logcat.txt
|
||||
retention-days: 7
|
||||
|
||||
desktop-test:
|
||||
name: "Desktop"
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 80
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
|
||||
- name: Run instrumented tests
|
||||
run: ./gradlew :shared:desktopTest
|
||||
|
||||
- name: Save Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: test-results
|
||||
path: |
|
||||
/Users/runner/work/alkaa/alkaa/app/build/reports/tests/
|
||||
./logcat.txt
|
||||
retention-days: 7
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.escodro.datastore
|
||||
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
|
||||
internal class DesktopDataStore {
|
||||
|
||||
fun getDataStore(): DataStore<Preferences> = getDataStore(
|
||||
producePath = { dataStoreFileName },
|
||||
)
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.escodro.datastore.di
|
||||
|
||||
import com.escodro.datastore.DesktopDataStore
|
||||
import org.koin.dsl.module
|
||||
|
||||
/**
|
||||
* Provides the platform-specific dependencies.
|
||||
*/
|
||||
internal actual val platformDataStoreModule = module {
|
||||
single { DesktopDataStore().getDataStore() }
|
||||
}
|
@ -11,6 +11,8 @@ kotlin {
|
||||
setFrameworkBaseName("local")
|
||||
|
||||
sourceSets {
|
||||
val desktopMain by getting
|
||||
|
||||
commonMain.dependencies {
|
||||
implementation(projects.libraries.coroutines)
|
||||
implementation(projects.data.repository)
|
||||
@ -37,6 +39,11 @@ kotlin {
|
||||
implementation(kotlin("test"))
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
}
|
||||
|
||||
desktopMain.dependencies {
|
||||
implementation(libs.sqldelight.jvm)
|
||||
implementation(libs.multiplatform.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,4 @@ internal class AndroidDriverFactory(
|
||||
|
||||
override fun createDriver(databaseName: String): SqlDriver =
|
||||
AndroidSqliteDriver(AlkaaDatabase.Schema, context, databaseName)
|
||||
|
||||
override fun shouldPrepopulateDatabase(databaseName: String): Boolean =
|
||||
!context.getDatabasePath(databaseName).exists()
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ internal class DatabaseProvider(
|
||||
}
|
||||
|
||||
private fun prepopulateDatabase(database: AlkaaDatabase) {
|
||||
if (driverFactory.shouldPrepopulateDatabase(DATABASE_NAME)) {
|
||||
if (isDatabaseEmpty(database)) {
|
||||
appCoroutineScope.launch {
|
||||
for (category in getPrepopulateData()) {
|
||||
database.categoryQueries.insert(
|
||||
@ -59,6 +59,17 @@ internal class DatabaseProvider(
|
||||
}
|
||||
}
|
||||
|
||||
private fun isDatabaseEmpty(database: AlkaaDatabase): Boolean = with(database) {
|
||||
categoryQueries
|
||||
.selectAll()
|
||||
.executeAsList()
|
||||
.isEmpty() &&
|
||||
taskQueries
|
||||
.selectAllTasksWithDueDate()
|
||||
.executeAsList()
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
private suspend fun getPrepopulateData(): List<Category> =
|
||||
listOf(
|
||||
Category(
|
||||
|
@ -15,13 +15,4 @@ internal interface DriverFactory {
|
||||
* @return the [SqlDriver] to be used in the database
|
||||
*/
|
||||
fun createDriver(databaseName: String): SqlDriver
|
||||
|
||||
/**
|
||||
* Checks if the database is opening for the first time and should be prepopulated.
|
||||
*
|
||||
* @param databaseName the database name
|
||||
*
|
||||
* @return true if the database should be prepopulated, false otherwise
|
||||
*/
|
||||
fun shouldPrepopulateDatabase(databaseName: String): Boolean
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.escodro.local.di
|
||||
|
||||
import com.escodro.local.provider.DesktopDriverFactory
|
||||
import com.escodro.local.provider.DriverFactory
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
/**
|
||||
* Provides the platform-specific dependencies.
|
||||
*/
|
||||
internal actual val platformLocalModule = module {
|
||||
singleOf(::DesktopDriverFactory) bind DriverFactory::class
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.escodro.local.provider
|
||||
|
||||
import app.cash.sqldelight.db.SqlDriver
|
||||
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
|
||||
import com.escodro.local.AlkaaDatabase
|
||||
import me.sujanpoudel.utils.paths.appCacheDirectory
|
||||
|
||||
internal class DesktopDriverFactory : DriverFactory {
|
||||
|
||||
override fun createDriver(databaseName: String): SqlDriver {
|
||||
val appCacheDirectory = appCacheDirectory(appId = PACKAGE_NAME, createDir = true)
|
||||
val jdbcUrl = "jdbc:sqlite:$appCacheDirectory$databaseName"
|
||||
return JdbcSqliteDriver(jdbcUrl).apply {
|
||||
AlkaaDatabase.Schema.create(this)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val PACKAGE_NAME = "com.escodro.alkaa"
|
||||
}
|
||||
}
|
@ -3,51 +3,11 @@ package com.escodro.local.provider
|
||||
import app.cash.sqldelight.db.SqlDriver
|
||||
import app.cash.sqldelight.driver.native.NativeSqliteDriver
|
||||
import com.escodro.local.AlkaaDatabase
|
||||
import kotlinx.cinterop.CPointer
|
||||
import kotlinx.cinterop.DoubleVarOf
|
||||
import kotlinx.cinterop.ExperimentalForeignApi
|
||||
import kotlinx.cinterop.get
|
||||
import platform.CoreGraphics.CGColorGetComponents
|
||||
import platform.CoreGraphics.CGFloat
|
||||
import platform.Foundation.NSFileManager
|
||||
import platform.Foundation.NSLibraryDirectory
|
||||
import platform.Foundation.NSURL
|
||||
import platform.Foundation.NSUserDomainMask
|
||||
import platform.UIKit.UIColor
|
||||
|
||||
internal class IosDriverFactory : DriverFactory {
|
||||
override fun createDriver(databaseName: String): SqlDriver =
|
||||
NativeSqliteDriver(AlkaaDatabase.Schema, databaseName)
|
||||
|
||||
override fun shouldPrepopulateDatabase(databaseName: String): Boolean =
|
||||
!databaseExists(databaseName)
|
||||
|
||||
private fun databaseExists(databaseName: String): Boolean {
|
||||
val fileManager = NSFileManager.defaultManager
|
||||
val documentDirectory = NSFileManager
|
||||
.defaultManager
|
||||
.URLsForDirectory(
|
||||
NSLibraryDirectory,
|
||||
NSUserDomainMask,
|
||||
).last() as NSURL
|
||||
|
||||
val file = documentDirectory
|
||||
.URLByAppendingPathComponent("$DATABASE_PATH$databaseName")
|
||||
?.path
|
||||
|
||||
return fileManager.fileExistsAtPath(file ?: "")
|
||||
}
|
||||
|
||||
@Suppress("ktlint:standard:chain-method-continuation")
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
private fun UIColor.toHex(): String {
|
||||
val components: CPointer<DoubleVarOf<CGFloat>>? = CGColorGetComponents(CGColor)
|
||||
val r = components?.get(0)?.times(255)?.toInt()?.toString(16)?.padStart(2, '0') ?: "00"
|
||||
val g = components?.get(1)?.times(255)?.toInt()?.toString(16)?.padStart(2, '0') ?: "00"
|
||||
val b = components?.get(2)?.times(255)?.toInt()?.toString(16)?.padStart(2, '0') ?: "00"
|
||||
return "#$r$g$b"
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val DATABASE_PATH = "Application Support/databases/"
|
||||
}
|
||||
|
1
desktop-app/.gitignore
vendored
Normal file
1
desktop-app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
61
desktop-app/build.gradle.kts
Normal file
61
desktop-app/build.gradle.kts
Normal file
@ -0,0 +1,61 @@
|
||||
import extension.setFrameworkBaseName
|
||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||
|
||||
plugins {
|
||||
id("com.escodro.multiplatform")
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.compose.compiler)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
setFrameworkBaseName("desktop-app")
|
||||
|
||||
sourceSets {
|
||||
val desktopMain by getting
|
||||
|
||||
commonMain.dependencies {
|
||||
implementation(projects.shared)
|
||||
implementation(projects.resources)
|
||||
implementation(projects.libraries.appstate)
|
||||
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.components.resources)
|
||||
implementation(libs.kotlinx.coroutines.swing)
|
||||
}
|
||||
|
||||
desktopMain.dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compose.desktop {
|
||||
application {
|
||||
mainClass = "com.escodro.desktopapp.MainKt"
|
||||
|
||||
nativeDistributions {
|
||||
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
||||
packageName = "com.escodro.alkaa"
|
||||
packageVersion = libs.versions.version.name.get()
|
||||
modules("java.sql")
|
||||
|
||||
macOS {
|
||||
iconFile.set(project.file("src/desktopMain/resources/ic_launcher.icns"))
|
||||
}
|
||||
windows {
|
||||
iconFile.set(project.file("src/desktopMain/resources/ic_launcher.ico"))
|
||||
}
|
||||
linux {
|
||||
iconFile.set(project.file("src/desktopMain/resources/ic_launcher.png"))
|
||||
}
|
||||
}
|
||||
|
||||
jvmArgs(
|
||||
"-DpackageVersion=${libs.versions.version.name.get()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "desktop"
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
@file:Suppress("ktlint:standard:filename")
|
||||
|
||||
package com.escodro.desktopapp
|
||||
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import com.escodro.resources.Res
|
||||
import com.escodro.resources.content_app_name
|
||||
import com.escodro.shared.AlkaaMultiplatformApp
|
||||
import com.escodro.shared.di.initKoin
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
fun main() = application {
|
||||
initKoin()
|
||||
|
||||
Window(
|
||||
onCloseRequest = ::exitApplication,
|
||||
title = stringResource(Res.string.content_app_name),
|
||||
) {
|
||||
AlkaaMultiplatformApp()
|
||||
}
|
||||
}
|
BIN
desktop-app/src/desktopMain/resources/ic_launcher.icns
Normal file
BIN
desktop-app/src/desktopMain/resources/ic_launcher.icns
Normal file
Binary file not shown.
BIN
desktop-app/src/desktopMain/resources/ic_launcher.ico
Normal file
BIN
desktop-app/src/desktopMain/resources/ic_launcher.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 164 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,17 @@
|
||||
package com.escodro.alarm.di
|
||||
|
||||
import com.escodro.alarm.notification.DesktopNotificationScheduler
|
||||
import com.escodro.alarm.notification.DesktopTaskNotification
|
||||
import com.escodro.alarm.notification.NotificationScheduler
|
||||
import com.escodro.alarm.notification.TaskNotification
|
||||
import com.escodro.alarm.permission.DesktopAlarmPermission
|
||||
import com.escodro.alarmapi.AlarmPermission
|
||||
import org.koin.core.module.dsl.factoryOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
actual val platformAlarmModule = module {
|
||||
factoryOf(::DesktopNotificationScheduler) bind NotificationScheduler::class
|
||||
factoryOf(::DesktopTaskNotification) bind TaskNotification::class
|
||||
factoryOf(::DesktopAlarmPermission) bind AlarmPermission::class
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.escodro.alarm.notification
|
||||
|
||||
import com.escodro.alarm.model.Task
|
||||
|
||||
internal class DesktopNotificationScheduler : NotificationScheduler {
|
||||
|
||||
override fun scheduleTaskNotification(task: Task, timeInMillis: Long) {
|
||||
// TODO: Implement scheduleTaskNotification
|
||||
}
|
||||
|
||||
override fun cancelTaskNotification(task: Task) {
|
||||
// TODO: Implement cancelTaskNotification
|
||||
}
|
||||
|
||||
override fun updateTaskNotification(task: Task) {
|
||||
// TODO: Implement updateTaskNotification
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.escodro.alarm.notification
|
||||
|
||||
import com.escodro.alarm.model.Task
|
||||
|
||||
internal class DesktopTaskNotification : TaskNotification {
|
||||
|
||||
override fun show(task: Task) {
|
||||
// TODO: Implement show
|
||||
}
|
||||
|
||||
override fun showRepeating(task: Task) {
|
||||
// TODO: Implement showRepeating
|
||||
}
|
||||
|
||||
override fun dismiss(taskId: Long) {
|
||||
// TODO: Implement dismiss
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.escodro.alarm.permission
|
||||
|
||||
import com.escodro.alarmapi.AlarmPermission
|
||||
|
||||
internal class DesktopAlarmPermission : AlarmPermission {
|
||||
|
||||
override fun hasExactAlarmPermission(): Boolean {
|
||||
// TODO: Implement hasExactAlarmPermission
|
||||
return true
|
||||
}
|
||||
|
||||
override fun openExactAlarmPermissionScreen() {
|
||||
// TODO: Implement openExactAlarmPermissionScreen
|
||||
}
|
||||
|
||||
override fun openAppSettings() {
|
||||
// TODO: Implement openAppSettings
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ kotlin {
|
||||
setFrameworkBaseName("preference")
|
||||
|
||||
sourceSets {
|
||||
val desktopMain by getting
|
||||
|
||||
commonMain.dependencies {
|
||||
implementation(projects.domain)
|
||||
implementation(projects.libraries.coroutines)
|
||||
@ -36,6 +38,10 @@ kotlin {
|
||||
iosMain.dependencies {
|
||||
implementation(projects.features.tracker)
|
||||
}
|
||||
|
||||
desktopMain.dependencies{
|
||||
implementation(projects.features.tracker)
|
||||
}
|
||||
}
|
||||
}
|
||||
android {
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.escodro.preference.di
|
||||
|
||||
import com.escodro.preference.provider.AppInfoProvider
|
||||
import com.escodro.preference.provider.DesktopAppInfoProvider
|
||||
import com.escodro.preference.provider.DesktopTrackerProvider
|
||||
import com.escodro.preference.provider.TrackerProvider
|
||||
import org.koin.core.module.dsl.factoryOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
/**
|
||||
* Provides the platform-specific dependencies.
|
||||
*/
|
||||
internal actual val platformPreferenceModule = module {
|
||||
factoryOf(::DesktopAppInfoProvider) bind AppInfoProvider::class
|
||||
factoryOf(::DesktopTrackerProvider) bind TrackerProvider::class
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.escodro.preference.provider
|
||||
|
||||
internal class DesktopAppInfoProvider : AppInfoProvider {
|
||||
|
||||
override fun getAppVersion(): String {
|
||||
val version = System.getProperty("packageVersion") ?: "0.0.0"
|
||||
return "$version-alpha"
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.escodro.preference.provider
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.escodro.tracker.presentation.TrackerScreen
|
||||
|
||||
internal class DesktopTrackerProvider : TrackerProvider {
|
||||
|
||||
@Composable
|
||||
override fun Content(onUpPress: () -> Unit) {
|
||||
TrackerScreen(onUpPress = onUpPress)
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.escodro.task.di
|
||||
|
||||
import com.escodro.task.provider.DesktopRelativeDateTimeProvider
|
||||
import com.escodro.task.provider.RelativeDateTimeProvider
|
||||
import org.koin.core.module.dsl.factoryOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
/**
|
||||
* Provides the platform-specific dependencies.
|
||||
*/
|
||||
actual val platformTaskModule = module {
|
||||
factoryOf(::DesktopRelativeDateTimeProvider) bind RelativeDateTimeProvider::class
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.escodro.task.extension
|
||||
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toInstant
|
||||
import java.text.DateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Formats the [LocalDateTime] to a user-friendly string.
|
||||
*/
|
||||
actual fun LocalDateTime.format(): String {
|
||||
val dateFormat = DateFormat.getDateTimeInstance(
|
||||
DateFormat.LONG,
|
||||
DateFormat.SHORT,
|
||||
Locale.getDefault(),
|
||||
)
|
||||
val calendar = Calendar.getInstance().apply {
|
||||
timeInMillis = toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
|
||||
}
|
||||
return dateFormat.format(calendar.time)
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.escodro.task.provider
|
||||
|
||||
import com.escodro.resources.Res
|
||||
import com.escodro.resources.relative_date_time_days
|
||||
import com.escodro.resources.relative_date_time_hours
|
||||
import com.escodro.resources.relative_date_time_just_now
|
||||
import com.escodro.resources.relative_date_time_minutes
|
||||
import com.escodro.resources.relative_date_time_one_hour
|
||||
import com.escodro.resources.relative_date_time_one_minute
|
||||
import com.escodro.resources.relative_date_time_yesterday
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toInstant
|
||||
import org.jetbrains.compose.resources.getString
|
||||
|
||||
internal class DesktopRelativeDateTimeProvider : RelativeDateTimeProvider {
|
||||
|
||||
override fun toRelativeDateTimeString(dateTime: LocalDateTime): String {
|
||||
val currentTime = Clock.System.now()
|
||||
val targetInstant = dateTime.toInstant(TimeZone.currentSystemDefault())
|
||||
val duration = currentTime - targetInstant
|
||||
|
||||
return runBlocking {
|
||||
when {
|
||||
duration.inWholeMinutes < 1 ->
|
||||
getString(Res.string.relative_date_time_just_now)
|
||||
|
||||
duration.inWholeMinutes == 1L ->
|
||||
getString(Res.string.relative_date_time_one_minute)
|
||||
|
||||
duration.inWholeMinutes < 60 ->
|
||||
getString(Res.string.relative_date_time_minutes, duration.inWholeMinutes)
|
||||
|
||||
duration.inWholeHours == 1L ->
|
||||
getString(Res.string.relative_date_time_one_hour)
|
||||
|
||||
duration.inWholeHours < 24 ->
|
||||
getString(Res.string.relative_date_time_hours, duration.inWholeHours)
|
||||
|
||||
duration.inWholeDays == 1L ->
|
||||
getString(Res.string.relative_date_time_yesterday)
|
||||
|
||||
duration.inWholeDays < 7 ->
|
||||
getString(Res.string.relative_date_time_days, duration.inWholeDays)
|
||||
|
||||
else -> dateTime.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -54,6 +54,9 @@ sqldelight = "2.0.2"
|
||||
moko = "0.16.1"
|
||||
moko_permissions = "0.19.1"
|
||||
|
||||
# Multiplatform Utils
|
||||
multiplatform_paths = "0.2.2"
|
||||
|
||||
# Test
|
||||
test_junit = "4.13.2"
|
||||
test_uiautomator = "2.3.0"
|
||||
@ -81,6 +84,7 @@ stately = { module = "co.touchlab:stately-common", version.ref = "stately" }
|
||||
# KotlinX
|
||||
kotlinx_coroutines_core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx_coroutines" }
|
||||
kotlinx_coroutines_test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx_coroutines" }
|
||||
kotlinx_coroutines_swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx_coroutines" }
|
||||
kotlinx_serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx_serialization" }
|
||||
kotlinx_collections_immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinx_collections_immutable" }
|
||||
kotlinx_datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx_datetime" }
|
||||
@ -118,6 +122,7 @@ koin_compose_jb = { module = "io.insert-koin:koin-compose", version.ref = "koin_
|
||||
# SQLDelight
|
||||
sqldelight_driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
|
||||
sqldelight_native = { module = "app.cash.sqldelight:native-driver", version.ref = "sqldelight" }
|
||||
sqldelight_jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" }
|
||||
sqldelight_coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
|
||||
|
||||
# Moko
|
||||
@ -126,6 +131,9 @@ moko_mvvm_compose = { module = "dev.icerock.moko:mvvm-flow-compose", version.ref
|
||||
moko_permissions_compose = { module = "dev.icerock.moko:permissions-compose", version.ref = "moko_permissions" }
|
||||
moko_permissions_notifications = { module = "dev.icerock.moko:permissions-notifications", version.ref = "moko_permissions" }
|
||||
|
||||
## Multiplatform Utils
|
||||
multiplatform_path = { module = "me.sujanpoudel.multiplatform.utils:multiplatform-paths", version.ref = "multiplatform_paths" }
|
||||
|
||||
# Test
|
||||
test_junit = { module = "junit:junit", version.ref = "test_junit" }
|
||||
test_uiautomator = { module = "androidx.test.uiautomator:uiautomator", version.ref = "test_uiautomator" }
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.escodro.designsystem.di
|
||||
|
||||
import com.escodro.designsystem.provider.DesktopThemeProvider
|
||||
import com.escodro.designsystem.provider.ThemeProvider
|
||||
import org.koin.core.module.dsl.factoryOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
actual val platformDesignSystemModule = module {
|
||||
factoryOf(::DesktopThemeProvider) bind ThemeProvider::class
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.escodro.designsystem.provider
|
||||
|
||||
import androidx.compose.material3.ColorScheme
|
||||
|
||||
internal class DesktopThemeProvider : ThemeProvider {
|
||||
override val isDynamicColorSupported: Boolean
|
||||
get() = false
|
||||
|
||||
override val dynamicDarkColorScheme: ColorScheme
|
||||
get() = throw UnsupportedOperationException("Dynamic Theme not supported on Desktop")
|
||||
|
||||
override val dynamicLightColorScheme: ColorScheme
|
||||
get() = throw UnsupportedOperationException("Dynamic Theme not supported on Desktop")
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.escodro.di
|
||||
|
||||
import dev.icerock.moko.mvvm.viewmodel.ViewModel
|
||||
import org.koin.core.definition.Definition
|
||||
import org.koin.core.definition.KoinDefinition
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.core.qualifier.Qualifier
|
||||
|
||||
/**
|
||||
* Defines an Desktop [ViewModel] in the Koin module.
|
||||
*/
|
||||
actual inline fun <reified T : ViewModel> Module.viewModelDefinition(
|
||||
qualifier: Qualifier?,
|
||||
noinline definition: Definition<T>,
|
||||
): KoinDefinition<T> = factory(qualifier = qualifier, definition = definition)
|
@ -0,0 +1,3 @@
|
||||
package com.escodro.parcelable
|
||||
|
||||
actual interface CommonParcelable
|
@ -0,0 +1,10 @@
|
||||
package com.escodro.permission.api
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
actual fun BindPermissionEffect(
|
||||
permissionController: PermissionController,
|
||||
) {
|
||||
// Do nothing - not required on Desktop
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.escodro.permission.api
|
||||
|
||||
internal class DesktopPermissionController : PermissionController {
|
||||
|
||||
override val controller: Any = Any()
|
||||
|
||||
override suspend fun requestPermission(permission: Permission) {
|
||||
// TODO: Implement requestPermission
|
||||
}
|
||||
|
||||
override suspend fun isPermissionGranted(permission: Permission): Boolean {
|
||||
// TODO: Implement isPermissionGranted
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.escodro.permission.di
|
||||
|
||||
import com.escodro.permission.api.DesktopPermissionController
|
||||
import com.escodro.permission.api.PermissionController
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
actual val platformPermissionModule = module {
|
||||
singleOf(::DesktopPermissionController) bind PermissionController::class
|
||||
}
|
@ -8,6 +8,8 @@ kotlin {
|
||||
setFrameworkBaseName("test")
|
||||
|
||||
sourceSets {
|
||||
val desktopMain by getting
|
||||
|
||||
commonMain.dependencies {
|
||||
implementation(kotlin("test"))
|
||||
api(libs.kotlinx.coroutines.test)
|
||||
@ -16,6 +18,11 @@ kotlin {
|
||||
androidMain.dependencies {
|
||||
implementation(kotlin("test-junit"))
|
||||
}
|
||||
|
||||
desktopMain.dependencies {
|
||||
implementation(kotlin("test-junit"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package extension
|
||||
|
||||
import org.gradle.kotlin.dsl.get
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
|
||||
/**
|
||||
@ -18,4 +17,5 @@ fun KotlinMultiplatformExtension.setFrameworkBaseName(name: String) {
|
||||
baseName = name
|
||||
}
|
||||
}
|
||||
jvm("desktop")
|
||||
}
|
||||
|
@ -119,4 +119,13 @@
|
||||
<string name="dialog_picker_confirm">Confirmar</string>
|
||||
|
||||
<string name="default_ok">OK</string>
|
||||
|
||||
<!-- Relative Date -->
|
||||
<string name="relative_date_time_just_now">agora</string>
|
||||
<string name="relative_date_time_one_minute">há 1 minuto</string>
|
||||
<string name="relative_date_time_minutes">há %d minutos</string>
|
||||
<string name="relative_date_time_one_hour">há 1 hora</string>
|
||||
<string name="relative_date_time_hours">há %d horas</string>
|
||||
<string name="relative_date_time_yesterday">ontem</string>
|
||||
<string name="relative_date_time_days">há %d dias</string>
|
||||
</resources>
|
||||
|
@ -123,4 +123,13 @@
|
||||
|
||||
<string name="default_ok">OK</string>
|
||||
|
||||
<!-- Relative Date -->
|
||||
<string name="relative_date_time_just_now">just now</string>
|
||||
<string name="relative_date_time_one_minute">1 minute ago</string>
|
||||
<string name="relative_date_time_minutes">%d minutes ago</string>
|
||||
<string name="relative_date_time_one_hour">1 hour ago</string>
|
||||
<string name="relative_date_time_hours">%d hours ago</string>
|
||||
<string name="relative_date_time_yesterday">yesterday</string>
|
||||
<string name="relative_date_time_days">%d days ago</string>
|
||||
|
||||
</resources>
|
||||
|
@ -1,4 +1,5 @@
|
||||
include(":app")
|
||||
include(":desktop-app")
|
||||
include(":features:alarm-api")
|
||||
include(":features:alarm")
|
||||
include(":features:task")
|
||||
|
@ -24,9 +24,12 @@ kotlin {
|
||||
baseName = "shared"
|
||||
isStatic = true
|
||||
}
|
||||
jvm("desktop")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
val desktopTest by getting
|
||||
|
||||
commonMain.dependencies {
|
||||
implementation(projects.data.local)
|
||||
implementation(projects.data.datastore)
|
||||
@ -74,6 +77,11 @@ kotlin {
|
||||
implementation(libs.koin.test)
|
||||
implementation(libs.kotlinx.datetime)
|
||||
}
|
||||
|
||||
desktopTest.dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation(libs.kotlinx.coroutines.swing)
|
||||
}
|
||||
}
|
||||
|
||||
androidTarget {
|
||||
|
@ -0,0 +1,8 @@
|
||||
package com.escodro.shared.di
|
||||
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.dsl.module
|
||||
|
||||
internal actual val platformSharedModule: Module = module {
|
||||
// No specific modules for Desktop
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.escodro.alkaa.test
|
||||
|
||||
actual class PlatformAnimation actual constructor() {
|
||||
/**
|
||||
* Disable the animations.
|
||||
*/
|
||||
actual fun disable() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the animations.
|
||||
*/
|
||||
actual fun enable() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.escodro.alkaa.test
|
||||
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.dsl.module
|
||||
|
||||
/**
|
||||
* Koin module to provide the platform dependencies.
|
||||
*/
|
||||
actual val platformModule: Module
|
||||
get() = module { }
|
Reference in New Issue
Block a user