diff --git a/.github/config/configuration.json b/.github/config/configuration.json
new file mode 100644
index 0000000..8729ce9
--- /dev/null
+++ b/.github/config/configuration.json
@@ -0,0 +1,29 @@
+{
+ "categories": [
+ {
+ "title": "## 🚀 Features",
+ "labels": [
+ "feature"
+ ]
+ },
+ {
+ "title": "## 🐛 Fixes",
+ "labels": [
+ "fix"
+ ]
+ },
+ {
+ "title": "## 🧪 Tests",
+ "labels": [
+ "test"
+ ]
+ },
+ {
+ "title": "## 💬 Other",
+ "labels": [
+ "other",
+ "dependencies"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index db12478..1a87522 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,27 +2,35 @@ name: Build
on:
push:
- branches: [ develop ]
+ branches: [ develop, main ]
pull_request:
branches: [ main, develop ]
+concurrency:
+ group: build-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
build:
name: 🔨 Build
runs-on: ubuntu-latest
steps:
-
- name: Checkout code
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
+
+ - name: Validate Gradle Wrapper
+ uses: gradle/wrapper-validation-action@v3
- name: Set up JDK 17
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v4
with:
- java-version: 17
+ java-version: '17'
+ distribution: 'adopt'
+ cache: gradle
- name: Make gradle executable
run: chmod +x ./gradlew
- - name: Build with gradle
- run: ./gradlew build --stacktrace
\ No newline at end of file
+ - name: Build app
+ run: ./gradlew assemble --stacktrace
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..937f9c5
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,144 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - '*'
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ release_desktop:
+ name: Release Desktop App
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ macos-latest, ubuntu-latest, windows-latest ]
+ runs-on: ${{ matrix.os }}
+ if: startsWith(github.ref, 'refs/tags/')
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Validate Gradle Wrapper
+ uses: gradle/wrapper-validation-action@v3
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'adopt'
+ cache: gradle
+
+ - name: Make gradle executable
+ run: chmod +x ./gradlew
+
+ - name: Checkout Gradle Build Cache
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ !~/.gradle/wrapper/dists/**/gradle*.zip
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
+ restore-keys: |
+ gradle-${{ runner.os }}-
+
+ - name: Build app
+ run: ./gradlew :desktop:assemble --stacktrace
+
+ - name: Build Release App
+ run: |
+ ./gradlew packageUberJarForCurrentOS
+ ./gradlew package
+
+ - name: Archive Artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ name: distributable-${{ matrix.os }}
+ if-no-files-found: ignore
+ path: |
+ desktop/build/**/*.deb
+ desktop/build/**/*.msi
+ desktop/build/**/*.dmg
+ desktop/build/compose/jars/*.jar
+
+ - name: Release
+ uses: softprops/action-gh-release@91409e712cf565ce9eff10c87a8d1b11b81757ae
+ with:
+ prerelease: ${{ contains(github.event.inputs.version, '-rc') || contains(github.event.inputs.version, '-b') || contains(github.event.inputs.version, '-a') }}
+ files: |
+ desktop/build/**/*.deb
+ desktop/build/**/*.msi
+ desktop/build/**/*.dmg
+ desktop/build/compose/jars/*.jar
+ env:
+ GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }}
+
+ release_android:
+ name: Release Android App
+ runs-on: ubuntu-latest
+ if: startsWith(github.ref, 'refs/tags/')
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Validate Gradle Wrapper
+ uses: gradle/wrapper-validation-action@v3
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'adopt'
+ cache: gradle
+
+ - name: Make gradle executable
+ run: chmod +x ./gradlew
+
+ - name: Build app
+ run: ./gradlew :android:assembleRelease --stacktrace
+
+ - name: Archive Artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ name: android-app
+ if-no-files-found: ignore
+ path: android/build/outputs/apk/release/*.apk
+
+ - name: Release
+ uses: softprops/action-gh-release@91409e712cf565ce9eff10c87a8d1b11b81757ae
+ with:
+ prerelease: ${{ contains(github.event.inputs.version, '-rc') || contains(github.event.inputs.version, '-b') || contains(github.event.inputs.version, '-a') }}
+ files: |
+ android/build/outputs/apk/release/*.apk
+ env:
+ GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }}
+
+ changelog:
+ name: Changelog
+ runs-on: ubuntu-latest
+ if: startsWith(github.ref, 'refs/tags/')
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Build Changelog
+ id: github_release
+ uses: mikepenz/release-changelog-builder-action@v1
+ with:
+ configuration: ".github/config/configuration.json"
+ commitMode: true
+ ignorePreReleases: ${{ !contains(github.ref, '-') }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Release
+ uses: softprops/action-gh-release@91409e712cf565ce9eff10c87a8d1b11b81757ae
+ with:
+ body: ${{steps.github_release.outputs.changelog}}
+ prerelease: ${{ contains(github.event.inputs.version, '-rc') || contains(github.event.inputs.version, '-b') || contains(github.event.inputs.version, '-a') }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index bf68fba..28887f3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,103 @@
-*.iml
+# Gradle
.gradle
+build/
+
+captures
+
/local.properties
-.idea
+
+# IntelliJ .idea folder
+.idea/workspace.xml
+.idea/misc.xml
+.idea/libraries
+.idea/caches
+.idea/navEditor.xml
+.idea/tasks.xml
+.idea/modules.xml
+.idea/compiler.xml
+.idea/jarRepositories.xml
+.idea/deploymentTargetDropDown.xml
+.idea/androidTestResultsUserPreferences.xml
+.idea/appInsightsSettings.xml
+.idea/artifacts
+gradle.xml
+*.iml
+.fleet
+
+# General
.DS_Store
-/build
-*/build
-/captures
.externalNativeBuild
-.cxx
-local.properties
\ No newline at end of file
+
+# Do not commit plain-text release keys
+app-release.jks
+play-account.p12
+play-account.json
+
+# Do not commit firebase config
+google-services.json
+
+# VS Code config
+org.eclipse.buildship.core.prefs
+.classpath
+.project
+bin/
+
+# Docs
+site/
+.cache/
+
+# Ignore baseline profile files in samples
+sample/**/generated
+
+##########################################################################################
+# Imported from https://github.com/github/gitignore/blob/main/Swift.gitignore
+##########################################################################################
+
+# Xcode
+#
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+## User settings
+xcuserdata/
+
+## Obj-C/Swift specific
+*.hmap
+
+## App packaging
+*.ipa
+*.dSYM.zip
+*.dSYM
+
+## Playgrounds
+timeline.xctimeline
+playground.xcworkspace
+
+# Swift Package Manager
+#
+# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
+# Packages/
+# Package.pins
+# Package.resolved
+# *.xcodeproj
+#
+# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
+# hence it is not needed unless you have added a package configuration file to your project
+# .swiftpm
+
+.build/
+
+# fastlane
+#
+# It is recommended to not store the screenshots in the git repo.
+# Instead, use fastlane to re-generate the screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://docs.fastlane.tools/best-practices/source-control/#source-control
+
+report.xml
+Preview.html
+screenshots/**/*.png
+test_output
+
+*.env*
+
+.kotlin
\ No newline at end of file
diff --git a/.scripts/pre-commit b/.scripts/pre-commit
index 7516da5..bab6c63 100644
--- a/.scripts/pre-commit
+++ b/.scripts/pre-commit
@@ -32,12 +32,6 @@ else
exit 1
fi
-./gradlew app:ktlintCheck --daemon
-STATUS=$?
-
-# return 1 exit code if running checks
-[ $STATUS -ne 0 ] && exit 1
-exit 0
# Branch
branch="$(git rev-parse --abbrev-ref HEAD)"
diff --git a/README.md b/README.md
index af155d8..15873a3 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
-
-
# FocusBloom
FocusBloom is a Kotlin Multiplatform app that helps users enhance their productivity and time management skills through focused work intervals and short breaks.
@@ -12,7 +10,6 @@ FocusBloom is a Kotlin Multiplatform app that helps users enhance their producti
![](https://img.shields.io/badge/Android-black.svg?style=for-the-badge&logo=android) | ![](https://img.shields.io/badge/iOS-black.svg?style=for-the-badge&logo=apple) | ![](https://img.shields.io/badge/Desktop-black.svg?style=for-the-badge&logo=windows) | ![](https://img.shields.io/badge/Web-black.svg?style=for-the-badge&logo=google-chrome)
:----: | :----: | :----: | :----:
✅ | ✅ | ✅ | Planned
-
## Screenshots
### Android
@@ -29,6 +26,18 @@ FocusBloom is a Kotlin Multiplatform app that helps users enhance their producti
## Architecture
The app is shared between Android, iOS and Desktop. The shared code is written in Kotlin and the UI is built with Compose Multiplatform. Shared code, written in Kotlin, is compiled to JVM bytecode for Android and Desktop with Kotlin/JVM and to native binaries for iOS with Kotlin/Native.
### Modules
+
+```mermaid
+%%{
+ init: {
+ 'theme': 'neutral'
+ }
+}%%
+
+graph LR
+ :desktop --> :shared
+ :android --> :shared
+```
- shared:
- contains all the shared code between the platforms
- android:
@@ -51,8 +60,6 @@ The app is shared between Android, iOS and Desktop. The shared code is written i
- [Compose Components Resources](https://mvnrepository.com/artifact/org.jetbrains.compose.components/components-resources) - Resources For Compose Multiplatform.
- [Material3 Window Size Multiplatform](https://github.com/chrisbanes/material3-windowsizeclass-multiplatform) - About Material 3 Window Size Class for Compose Multiplatform.
- [Spotless](https://github.com/diffplug/spotless) - A code formatter that helps keep the codebase clean.
-- [Detekt](https://github.com/detekt/detekt) - Static code analysis for Kotlin.
-- [Ktlint](https://github.com/pinterest/ktlint) - A static code analysis tool and formatter for Kotlin.
- [Github Actions](https://docs.github.com/en/actions) - A CI/CD tool that helps automate workflows.
- [Renovate](https://docs.renovatebot.com/) - An open-source software tool designed to help automate the process of updating dependencies in software projects.
@@ -85,4 +92,4 @@ Copyright 2023 JoelKanyi
See the License for the specific language governing permissions and
limitations under the License.
```
-
+
\ No newline at end of file
diff --git a/android/build.gradle.kts b/android/build.gradle.kts
index 85d056f..56347ce 100644
--- a/android/build.gradle.kts
+++ b/android/build.gradle.kts
@@ -17,6 +17,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.android.kotlin)
alias(libs.plugins.compose.multiplatform)
+ alias(libs.plugins.compose.compiler)
}
android {
@@ -37,7 +38,13 @@ android {
isDebuggable = true
}
getByName("release") {
- isMinifyEnabled = false
+ isMinifyEnabled = true
+ isShrinkResources = true
+
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro",
+ )
}
}
@@ -54,14 +61,10 @@ android {
buildFeatures {
compose = true
}
-
- composeOptions {
- kotlinCompilerExtensionVersion = "1.5.2"
- }
}
dependencies {
- implementation(project(":shared"))
+ implementation(projects.shared)
implementation(libs.compose.activity)
implementation(libs.koin.android)
coreLibraryDesugaring(libs.core.library.desugaring)
diff --git a/android/src/main/java/com/joelkanyi/focusbloom/android/BloomApp.kt b/android/src/main/java/com/joelkanyi/focusbloom/android/BloomApp.kt
index e46adbc..228dbaf 100644
--- a/android/src/main/java/com/joelkanyi/focusbloom/android/BloomApp.kt
+++ b/android/src/main/java/com/joelkanyi/focusbloom/android/BloomApp.kt
@@ -18,7 +18,7 @@ package com.joelkanyi.focusbloom.android
import android.app.Application
import com.joelkanyi.focusbloom.android.di.androidModule
import com.joelkanyi.focusbloom.di.KoinInit
-import io.github.aakira.napier.BuildConfig
+import com.russhwolf.settings.BuildConfig
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.logger.Level
@@ -32,8 +32,8 @@ class BloomApp : Application() {
androidContext(androidContext = this@BloomApp)
modules(
listOf(
- androidModule
- )
+ androidModule,
+ ),
)
}
}
diff --git a/android/src/main/java/com/joelkanyi/focusbloom/android/MainActivity.kt b/android/src/main/java/com/joelkanyi/focusbloom/android/MainActivity.kt
index f9fba09..9f4bf8d 100644
--- a/android/src/main/java/com/joelkanyi/focusbloom/android/MainActivity.kt
+++ b/android/src/main/java/com/joelkanyi/focusbloom/android/MainActivity.kt
@@ -40,8 +40,8 @@ class MainActivity : ComponentActivity() {
mutableStateOf(
ContextCompat.checkSelfPermission(
this,
- android.Manifest.permission.POST_NOTIFICATIONS
- ) == PackageManager.PERMISSION_GRANTED
+ android.Manifest.permission.POST_NOTIFICATIONS,
+ ) == PackageManager.PERMISSION_GRANTED,
)
} else {
mutableStateOf(true)
@@ -52,7 +52,7 @@ class MainActivity : ComponentActivity() {
contract = ActivityResultContracts.RequestPermission(),
onResult = { granted ->
hasCamPermission = granted
- }
+ },
)
LaunchedEffect(key1 = true, block = {
diff --git a/build.gradle.kts b/build.gradle.kts
index e65d207..1ff05a6 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,9 +7,13 @@ plugins {
alias(libs.plugins.nativeCocoapod) apply false
alias(libs.plugins.compose.multiplatform)
alias(libs.plugins.spotless)
- alias(libs.plugins.ktlint)
- alias(libs.plugins.detekt)
- alias(libs.plugins.gradleVersionUpdates)
+ id("dev.iurysouza.modulegraph") version "0.8.1"
+ alias(libs.plugins.compose.compiler) apply false
+}
+
+moduleGraphConfig {
+ readmePath.set("./README.md")
+ heading = "### Module Graph"
}
allprojects {
@@ -19,44 +23,16 @@ allprojects {
maven(url = "https://jitpack.io")
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
-
- apply(plugin = "org.jlleitschuh.gradle.ktlint")
- ktlint {
- debug.set(true)
- verbose.set(true)
- android.set(false)
- outputToConsole.set(true)
- outputColorName.set("RED")
- filter {
- enableExperimentalRules.set(true)
- exclude { projectDir.toURI().relativize(it.file.toURI()).path.contains("/generated/") }
- include("**/kotlin/**")
- }
- }
}
subprojects {
- apply(plugin = "io.gitlab.arturbosch.detekt")
- detekt {
- parallel = true
- config = files("${project.rootDir}/config/detekt/detekt.yml")
- }
-
- tasks.withType {
- checkForGradleUpdate = true
- outputFormatter = "html"
- outputDir = "build/reports/dependencyUpdates"
- reportfileName = "report"
- }
-
apply(plugin = "com.diffplug.spotless")
spotless {
kotlin {
target("**/*.kt")
- ktlint().userData(mapOf("disabled_rules" to "filename"))
licenseHeaderFile(
rootProject.file("${project.rootDir}/spotless/copyright.kt"),
- "^(package|object|import|interface)"
+ "^(package|object|import|interface)",
)
trimTrailingWhitespace()
endWithNewline()
@@ -74,11 +50,3 @@ subprojects {
}
}
}
-
-task("addPreCommitGitHookOnBuild") {
- println("⚈ ⚈ ⚈ Running Add Pre Commit Git Hook Script on Build ⚈ ⚈ ⚈")
- exec {
- commandLine("cp", "./.scripts/pre-commit", "./.git/hooks")
- }
- println("✅ Added Pre Commit Git Hook Script.")
-}
diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts
index 6072b87..84217e6 100644
--- a/desktop/build.gradle.kts
+++ b/desktop/build.gradle.kts
@@ -13,28 +13,60 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat
+
plugins {
alias(libs.plugins.jvm)
alias(libs.plugins.compose.multiplatform)
+ alias(libs.plugins.compose.compiler)
}
dependencies {
- implementation(project(":shared"))
+ implementation(projects.shared)
implementation(compose.desktop.currentOs)
}
+group = "com.joelkanyi"
+version = "1.0.0"
+
compose.desktop {
application {
mainClass = "DesktopAppKt"
nativeDistributions {
- targetFormats(
- org.jetbrains.compose.desktop.application.dsl.TargetFormat.Dmg,
- org.jetbrains.compose.desktop.application.dsl.TargetFormat.Msi,
- org.jetbrains.compose.desktop.application.dsl.TargetFormat.Deb,
- org.jetbrains.compose.desktop.application.dsl.TargetFormat.Rpm
+ targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
+
+ packageName = "FocusBloom"
+ packageVersion = project.version as String
+ description =
+ "An app that helps users enhance their productivity and time management skills through focused work intervals and short breaks."
+ copyright = "© 2023 Joel Kanyi"
+ vendor = "Joel Kanyi"
+
+ // .gradlew suggestRuntimeModules
+ modules(
+ "java.instrument",
+ "java.management",
+ "java.prefs",
+ "java.sql",
+ "jdk.unsupported"
)
- packageName = "focusbloom"
- packageName = "1.0.0"
+
+ val iconsRoot = project.file("src/main/resources/drawables")
+
+ linux {
+ iconFile.set(iconsRoot.resolve("launcher_icons/linuxos.png"))
+ }
+
+ windows {
+ iconFile.set(iconsRoot.resolve("launcher_icons/windowsos.ico"))
+ upgradeUuid = "31575EDF-D0D5-4CEF-A4D2-7562083D6D88"
+ menuGroup = packageName
+ perUserInstall = true
+ }
+
+ macOS {
+ iconFile.set(iconsRoot.resolve("launcher_icons/macos.icns"))
+ }
}
}
}
diff --git a/desktop/src/main/kotlin/DesktopApp.kt b/desktop/src/main/kotlin/DesktopApp.kt
index 1a07857..eae6e3a 100644
--- a/desktop/src/main/kotlin/DesktopApp.kt
+++ b/desktop/src/main/kotlin/DesktopApp.kt
@@ -31,7 +31,7 @@ lateinit var koin: Koin
fun main() {
koin = KoinInit().init()
koin.loadModules(
- listOf()
+ listOf(),
)
return application {
@@ -41,8 +41,8 @@ fun main() {
state = rememberWindowState(
position = WindowPosition.Aligned(Alignment.Center),
width = 1200.dp,
- height = 700.dp
- )
+ height = 700.dp,
+ ),
) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
FocusBloomApp()
diff --git a/desktop/src/main/resources/drawables/launcher_icons/linuxos.png b/desktop/src/main/resources/drawables/launcher_icons/linuxos.png
new file mode 100644
index 0000000..48b7447
Binary files /dev/null and b/desktop/src/main/resources/drawables/launcher_icons/linuxos.png differ
diff --git a/desktop/src/main/resources/drawables/launcher_icons/macos.icns b/desktop/src/main/resources/drawables/launcher_icons/macos.icns
new file mode 100644
index 0000000..4ca6232
Binary files /dev/null and b/desktop/src/main/resources/drawables/launcher_icons/macos.icns differ
diff --git a/desktop/src/main/resources/drawables/launcher_icons/windowsos.ico b/desktop/src/main/resources/drawables/launcher_icons/windowsos.ico
new file mode 100644
index 0000000..0b5d718
Binary files /dev/null and b/desktop/src/main/resources/drawables/launcher_icons/windowsos.ico differ
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a78a0ca..1df20f0 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,64 +1,43 @@
[versions]
-componentsResources = "1.5.3"
-core = "1.12.0"
-koalaplotCore = "0.4.0-dev1"
-korau = "4.0.6"
-kotlin = "1.9.10"
-gradle = "8.1.2"
-kotlinxCoroutinesSwing = "1.7.3"
-detekt = "1.19.0"
-gradleVersionUpdate = "0.46.0"
-koinCore = "3.5.0"
-koinAndroid = "3.5.0"
-kotlinxSerializationJson = "1.6.0"
-kotlinxDateTime = "0.4.1"
-material3WindowSizeClassMultiplatform = "0.3.1"
-napier = "2.6.1"
-sqlDelight = "2.0.0"
-multiplatformSettings = "1.1.0"
-compose = "1.5.10-beta01"
-core-library-desugaring = "2.0.3"
-toast4j = "0.2.0"
-voyager = "1.0.0-rc07"
-compose-activity = "1.8.0"
-koin-compose = "1.1.0"
-spotless = "5.17.1"
-ktlint = "11.6.1"
-accompanist-systemUIController = "0.30.1"
-annotationJvm = "1.7.0"
-[plugins]
-detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
-compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "compose" }
-gradleVersionUpdates = { id = "com.github.ben-manes.versions", version.ref = "gradleVersionUpdate" }
-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
-nativeCocoapod = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" }
-android-kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
-android-library = { id = "com.android.library", version.ref = "gradle" }
-android-application = { id = "com.android.application", version.ref = "gradle" }
-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
-kotlinX-serialization-plugin = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
-sqlDelight-plugin = { id = "app.cash.sqldelight", version.ref = "sqlDelight" }
-spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
-ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
+androidDriver = "2.0.2"
+kotlin = "2.0.0"
+compose = "1.6.10"
+koinCore = "3.5.6"
+koinAndroid = "3.5.6"
+gradle = "8.4.0"
+sqlDelight = " 2.0.2"
+voyager = "1.0.0"
+multiplatformSettings = "1.1.1"
+koin-compose = "1.1.5"
+core = "1.13.1"
+jna = "5.14.0"
+koalaplotCore = "0.5.4"
+kotlinxCoroutinesSwing = "1.8.0"
+kotlinxSerializationJson = "1.6.3"
+kotlinxDateTime = "0.5.0"
+material3WindowSizeClassMultiplatform = "0.5.0"
+napier = "2.7.1"
+core-library-desugaring = "2.0.4"
+toast4j = "0.2.0"
+compose-activity = "1.9.0"
+spotless = "6.25.0"
+accompanist-systemUIController = "0.34.0"
[libraries]
-components-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "componentsResources" }
+android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "androidDriver" }
core = { module = "androidx.core:core", version.ref = "core" }
+coroutines-extensions = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "androidDriver" }
+jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
koalaplot-core = { module = "io.github.koalaplot:koalaplot-core", version.ref = "koalaplotCore" }
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koinCore" }
koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin-compose"}
-korau = { module = "com.soywiz.korlibs.korau:korau", version.ref = "korau" }
kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinxCoroutinesSwing" }
kotlinX-serializationJson = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinxSerializationJson" }
material3-window-size-multiplatform = { module = "dev.chrisbanes.material3:material3-window-size-class-multiplatform", version.ref = "material3WindowSizeClassMultiplatform" }
-primitive-adapters = { module = "app.cash.sqldelight:primitive-adapters", version.ref = "sqlDelight" }
+native-driver = { module = "app.cash.sqldelight:native-driver", version.ref = "androidDriver" }
+primitive-adapters = { module = "app.cash.sqldelight:primitive-adapters", version.ref = "androidDriver" }
sqlDelight-runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sqlDelight" }
-sqlDelight-coroutine = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqlDelight" }
-sqlDelight-android = { 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-driver-sqljs = { module = "app.cash.sqldelight:sqljs-driver", version = "2.0.0-alpha05" }
napier = { module = "io.github.aakira:napier", version.ref = "napier" }
kotlinX-dateTime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDateTime" }
multiplatformSettings-noArg = { module = "com.russhwolf:multiplatform-settings-no-arg", version.ref = "multiplatformSettings" }
@@ -66,14 +45,30 @@ multiplatformSettings-coroutines = { module = "com.russhwolf:multiplatform-setti
compose-activity = { module = "androidx.activity:activity-compose", version.ref = "compose-activity" }
koin-android = { module = "io.insert-koin:koin-android", version.ref = "koinAndroid" }
+sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "androidDriver" }
toast4j = { module = "de.mobanisto:toast4j", version.ref = "toast4j" }
+
+# Voyager
voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" }
voyager-bottomSheetNavigator = { module = "cafe.adriel.voyager:voyager-bottom-sheet-navigator", version.ref = "voyager" }
voyager-tabNavigator = { module = "cafe.adriel.voyager:voyager-tab-navigator", version.ref = "voyager" }
voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" }
+voyager-koin = { module = "cafe.adriel.voyager:voyager-koin", version.ref = "voyager" }
+
core-library-desugaring = { module = "com.android.tools:desugar_jdk_libs", version.ref = "core-library-desugaring" }
accompanist-systemUIController = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist-systemUIController" }
-lifecycle-common = { group = "androidx.lifecycle", name = "lifecycle-common", version = "2.6.2" }
-annotation-jvm = { group = "androidx.annotation", name = "annotation-jvm", version.ref = "annotationJvm" }
-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
\ No newline at end of file
+stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
+
+[plugins]
+compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "compose" }
+multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
+compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
+nativeCocoapod = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" }
+android-kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+android-library = { id = "com.android.library", version.ref = "gradle" }
+android-application = { id = "com.android.application", version.ref = "gradle" }
+jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
+kotlinX-serialization-plugin = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
+sqlDelight-plugin = { id = "app.cash.sqldelight", version.ref = "sqlDelight" }
+spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e708b1c..d64cd49 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 5f9cae7..b82aa23 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
-#Fri Aug 18 22:40:35 EAT 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 4f906e0..1aa94a4 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
#
-# Copyright 2015 the original author or authors.
+# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,67 +17,99 @@
#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +119,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,88 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
fi
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
fi
- i=`expr $i + 1`
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index 107acd3..25da30d 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
-@if "%DEBUG%" == "" @echo off
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
+if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index d90cf18..8352fa8 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -9,8 +9,8 @@ EXTERNAL SOURCES:
:path: "../shared"
SPEC CHECKSUMS:
- shared: 3e0befb0fecedf50640d928d7650c497b1d237ab
+ shared: c3b82c05e553e3953cbbc618b8894285fa4cf610
PODFILE CHECKSUM: 83af500b7f00be241df85ae41eabbcbb267800e4
-COCOAPODS: 1.12.1
+COCOAPODS: 1.15.2
diff --git a/ios/Pods/Local Podspecs/shared.podspec.json b/ios/Pods/Local Podspecs/shared.podspec.json
index 9e70a8c..0e6a5b8 100644
--- a/ios/Pods/Local Podspecs/shared.podspec.json
+++ b/ios/Pods/Local Podspecs/shared.podspec.json
@@ -13,6 +13,9 @@
"platforms": {
"ios": "14.1"
},
+ "xcconfig": {
+ "ENABLE_USER_SCRIPT_SANDBOXING": "NO"
+ },
"pod_target_xcconfig": {
"KOTLIN_PROJECT_PATH": ":shared",
"PRODUCT_MODULE_NAME": "shared"
@@ -26,6 +29,6 @@
}
],
"resources": [
- "build/compose/ios/shared/compose-resources"
+ "build/compose/cocoapods/compose-resources"
]
}
diff --git a/ios/Pods/Manifest.lock b/ios/Pods/Manifest.lock
index d90cf18..8352fa8 100644
--- a/ios/Pods/Manifest.lock
+++ b/ios/Pods/Manifest.lock
@@ -9,8 +9,8 @@ EXTERNAL SOURCES:
:path: "../shared"
SPEC CHECKSUMS:
- shared: 3e0befb0fecedf50640d928d7650c497b1d237ab
+ shared: c3b82c05e553e3953cbbc618b8894285fa4cf610
PODFILE CHECKSUM: 83af500b7f00be241df85ae41eabbcbb267800e4
-COCOAPODS: 1.12.1
+COCOAPODS: 1.15.2
diff --git a/ios/Pods/Pods.xcodeproj/project.pbxproj b/ios/Pods/Pods.xcodeproj/project.pbxproj
index b0610c3..9395803 100644
--- a/ios/Pods/Pods.xcodeproj/project.pbxproj
+++ b/ios/Pods/Pods.xcodeproj/project.pbxproj
@@ -22,12 +22,12 @@
/* Begin PBXBuildFile section */
648F16425FEF89525AE0325F5A984B86 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; };
- 8749C8E8DC500B064FA0BC7A78C38A2A /* Pods-iosApp-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E6DB2A5F5DADA1DDE45F36B1A2D6AC16 /* Pods-iosApp-dummy.m */; };
- 8801CBFD38B946597BD07145B2EEFC9F /* Pods-iosApp-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 015E0D7EA7331961AB63E5AFECA86BB5 /* Pods-iosApp-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8749C8E8DC500B064FA0BC7A78C38A2A /* Pods-iosApp-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 54DC7F9924F99FEE67A9AD3BEE09A10C /* Pods-iosApp-dummy.m */; };
+ 8801CBFD38B946597BD07145B2EEFC9F /* Pods-iosApp-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F87A626222A8D9B26448A9FEB04FD0DF /* Pods-iosApp-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
- 3B3DD97234976EAE23DEF848B521F3BD /* PBXContainerItemProxy */ = {
+ C1E4F2F8101E860063100BCC8448BC3B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
proxyType = 1;
@@ -37,25 +37,23 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
- 015E0D7EA7331961AB63E5AFECA86BB5 /* Pods-iosApp-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iosApp-umbrella.h"; sourceTree = ""; };
- 11C9B998CE0869936AE6BE69270DAAC9 /* Pods-iosApp.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iosApp.modulemap"; sourceTree = ""; };
- 15C62982CC8B1FD56214604CE982F646 /* compose-resources */ = {isa = PBXFileReference; includeInIndex = 1; name = "compose-resources"; path = "build/compose/ios/shared/compose-resources"; sourceTree = ""; };
- 215D65FA831B0E4F8AC0B3826A846FDA /* shared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = shared.debug.xcconfig; sourceTree = ""; };
- 244FC2DAA936A0B07ACEFDC74E2D54B8 /* Pods-iosApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iosApp.release.xcconfig"; sourceTree = ""; };
- 45CF8D032A049A7012F30257A8F121AF /* shared-copy-dsyms.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "shared-copy-dsyms.sh"; sourceTree = ""; };
- 55ABB06C8A1800962A74E007E7733796 /* Pods-iosApp-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iosApp-frameworks.sh"; sourceTree = ""; };
- 5F931FED0EB9A618FB9EFF402884E1AC /* shared.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = shared.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
- 670597F16E31933FDD530ED5140D4EEF /* shared.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = shared.framework; path = build/cocoapods/framework/shared.framework; sourceTree = ""; };
- 6F3B5FED07117E377CFAC3D49B490F17 /* Pods-iosApp-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iosApp-resources.sh"; sourceTree = ""; };
+ 0187F135D5F61750CD24C3E04B6E8B64 /* Pods-iosApp-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-iosApp-frameworks.sh"; sourceTree = ""; };
+ 1192783415C3DAB1D0759742CCB1D491 /* shared.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = shared.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
+ 1E3AA4BB27FB47FC8730ED18E97BE3F7 /* shared-copy-dsyms.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "shared-copy-dsyms.sh"; sourceTree = ""; };
+ 20D1F143BB7A4CD522117C279A4C293E /* shared.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = shared.release.xcconfig; sourceTree = ""; };
+ 3F64BADB16C311E9D09DAD0116F684F4 /* Pods-iosApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iosApp.debug.xcconfig"; sourceTree = ""; };
+ 54DC7F9924F99FEE67A9AD3BEE09A10C /* Pods-iosApp-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iosApp-dummy.m"; sourceTree = ""; };
+ 5AC974169B09D4545F741E9A2147610E /* Pods-iosApp-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iosApp-Info.plist"; sourceTree = ""; };
73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
- 76A263267985B0185D85E24D40FCEE9A /* Pods-iosApp-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iosApp-Info.plist"; sourceTree = ""; };
- 76D28488EA8CF5C697DFF07967A9960E /* Pods-iosApp-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iosApp-acknowledgements.plist"; sourceTree = ""; };
+ 8B524AABE529FB8A2D151B05321336E0 /* Pods-iosApp.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iosApp.modulemap"; sourceTree = ""; };
+ 8C79858733E6BECC4D9CD03C15051A72 /* shared.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = shared.framework; path = build/cocoapods/framework/shared.framework; sourceTree = ""; };
+ 9BB0B8B698D4C35D4F9A07EF70910170 /* Pods-iosApp-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iosApp-acknowledgements.plist"; sourceTree = ""; };
9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
+ 9F1FFC8B10F4D7D4F37606E8959B3F29 /* Pods-iosApp-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iosApp-acknowledgements.markdown"; sourceTree = ""; };
+ 9FECCB5AFF87D121F15BA01E683C7932 /* Pods-iosApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iosApp.release.xcconfig"; sourceTree = ""; };
B097DD7534E741D5C41838011D755842 /* Pods-iosApp */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-iosApp"; path = Pods_iosApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
- B7C6BC0A7177E1D2CCCA8D9834206E64 /* shared.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = shared.release.xcconfig; sourceTree = ""; };
- E462E23B3674BF94EAB1504D506F2803 /* Pods-iosApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iosApp.debug.xcconfig"; sourceTree = ""; };
- E4C923318724794E3CC670804C2D6A6B /* Pods-iosApp-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-iosApp-acknowledgements.markdown"; sourceTree = ""; };
- E6DB2A5F5DADA1DDE45F36B1A2D6AC16 /* Pods-iosApp-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-iosApp-dummy.m"; sourceTree = ""; };
+ F87A626222A8D9B26448A9FEB04FD0DF /* Pods-iosApp-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-iosApp-umbrella.h"; sourceTree = ""; };
+ FD7FD28F3CCDF64520DA04A7CA0DDDC7 /* shared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = shared.debug.xcconfig; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -70,110 +68,108 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
- 0BDC589A39A26B9CF449BC4DB7EAC506 /* shared */ = {
+ 036E461C32C1F48BA43823A2282B0000 /* Support Files */ = {
isa = PBXGroup;
children = (
- 15C62982CC8B1FD56214604CE982F646 /* compose-resources */,
- DFA1DB9AC4A7CFB0C413CC312D0FE2B7 /* Frameworks */,
- 2D40657AD4B86DBF0DA60AE3E13CDCB8 /* Pod */,
- DAC212B1D8E90084ABE25A3B3FFC6E00 /* Support Files */,
+ 1E3AA4BB27FB47FC8730ED18E97BE3F7 /* shared-copy-dsyms.sh */,
+ FD7FD28F3CCDF64520DA04A7CA0DDDC7 /* shared.debug.xcconfig */,
+ 20D1F143BB7A4CD522117C279A4C293E /* shared.release.xcconfig */,
);
- name = shared;
- path = ../../shared;
+ name = "Support Files";
+ path = "../ios/Pods/Target Support Files/shared";
sourceTree = "";
};
- 1F86AA6785DF34AFD5A71790761717DE /* Products */ = {
+ 11C970DEAE48C6D0282DFE54684F53F1 /* Targets Support Files */ = {
isa = PBXGroup;
children = (
- B097DD7534E741D5C41838011D755842 /* Pods-iosApp */,
+ 52A898E555C2DBD7D25A7E44754C3FC6 /* Pods-iosApp */,
);
- name = Products;
+ name = "Targets Support Files";
sourceTree = "";
};
- 2D40657AD4B86DBF0DA60AE3E13CDCB8 /* Pod */ = {
+ 1F86AA6785DF34AFD5A71790761717DE /* Products */ = {
isa = PBXGroup;
children = (
- 5F931FED0EB9A618FB9EFF402884E1AC /* shared.podspec */,
+ B097DD7534E741D5C41838011D755842 /* Pods-iosApp */,
);
- name = Pod;
+ name = Products;
sourceTree = "";
};
- 578452D2E740E91742655AC8F1636D1F /* iOS */ = {
+ 2D696F51575A4504A458FD9155B8919F /* Pod */ = {
isa = PBXGroup;
children = (
- 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */,
+ 1192783415C3DAB1D0759742CCB1D491 /* shared.podspec */,
);
- name = iOS;
+ name = Pod;
sourceTree = "";
};
- 58AAD176B64323B9974E5B70EC8B12DC /* Development Pods */ = {
+ 313FE5FE915A4A924C55AAC02A910D61 /* Development Pods */ = {
isa = PBXGroup;
children = (
- 0BDC589A39A26B9CF449BC4DB7EAC506 /* shared */,
+ CD6C10345B56CBB7EE822B2D6ED267E2 /* shared */,
);
name = "Development Pods";
sourceTree = "";
};
- BA6B7BC2729F657E9D3682E55CA6E980 /* Pods-iosApp */ = {
+ 52A898E555C2DBD7D25A7E44754C3FC6 /* Pods-iosApp */ = {
isa = PBXGroup;
children = (
- 11C9B998CE0869936AE6BE69270DAAC9 /* Pods-iosApp.modulemap */,
- E4C923318724794E3CC670804C2D6A6B /* Pods-iosApp-acknowledgements.markdown */,
- 76D28488EA8CF5C697DFF07967A9960E /* Pods-iosApp-acknowledgements.plist */,
- E6DB2A5F5DADA1DDE45F36B1A2D6AC16 /* Pods-iosApp-dummy.m */,
- 55ABB06C8A1800962A74E007E7733796 /* Pods-iosApp-frameworks.sh */,
- 76A263267985B0185D85E24D40FCEE9A /* Pods-iosApp-Info.plist */,
- 6F3B5FED07117E377CFAC3D49B490F17 /* Pods-iosApp-resources.sh */,
- 015E0D7EA7331961AB63E5AFECA86BB5 /* Pods-iosApp-umbrella.h */,
- E462E23B3674BF94EAB1504D506F2803 /* Pods-iosApp.debug.xcconfig */,
- 244FC2DAA936A0B07ACEFDC74E2D54B8 /* Pods-iosApp.release.xcconfig */,
+ 8B524AABE529FB8A2D151B05321336E0 /* Pods-iosApp.modulemap */,
+ 9F1FFC8B10F4D7D4F37606E8959B3F29 /* Pods-iosApp-acknowledgements.markdown */,
+ 9BB0B8B698D4C35D4F9A07EF70910170 /* Pods-iosApp-acknowledgements.plist */,
+ 54DC7F9924F99FEE67A9AD3BEE09A10C /* Pods-iosApp-dummy.m */,
+ 0187F135D5F61750CD24C3E04B6E8B64 /* Pods-iosApp-frameworks.sh */,
+ 5AC974169B09D4545F741E9A2147610E /* Pods-iosApp-Info.plist */,
+ F87A626222A8D9B26448A9FEB04FD0DF /* Pods-iosApp-umbrella.h */,
+ 3F64BADB16C311E9D09DAD0116F684F4 /* Pods-iosApp.debug.xcconfig */,
+ 9FECCB5AFF87D121F15BA01E683C7932 /* Pods-iosApp.release.xcconfig */,
);
name = "Pods-iosApp";
path = "Target Support Files/Pods-iosApp";
sourceTree = "";
};
- CF1408CF629C7361332E53B88F7BD30C = {
+ 578452D2E740E91742655AC8F1636D1F /* iOS */ = {
isa = PBXGroup;
children = (
- 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */,
- 58AAD176B64323B9974E5B70EC8B12DC /* Development Pods */,
- D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */,
- 1F86AA6785DF34AFD5A71790761717DE /* Products */,
- D456857FB6E5BC3266BEC21401D60DB5 /* Targets Support Files */,
+ 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */,
);
+ name = iOS;
sourceTree = "";
};
- D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = {
+ 6E2D88EA0A916D116383DAFCE4BC46DD /* Frameworks */ = {
isa = PBXGroup;
children = (
- 578452D2E740E91742655AC8F1636D1F /* iOS */,
+ 8C79858733E6BECC4D9CD03C15051A72 /* shared.framework */,
);
name = Frameworks;
sourceTree = "";
};
- D456857FB6E5BC3266BEC21401D60DB5 /* Targets Support Files */ = {
+ CD6C10345B56CBB7EE822B2D6ED267E2 /* shared */ = {
isa = PBXGroup;
children = (
- BA6B7BC2729F657E9D3682E55CA6E980 /* Pods-iosApp */,
+ 6E2D88EA0A916D116383DAFCE4BC46DD /* Frameworks */,
+ 2D696F51575A4504A458FD9155B8919F /* Pod */,
+ 036E461C32C1F48BA43823A2282B0000 /* Support Files */,
);
- name = "Targets Support Files";
+ name = shared;
+ path = ../../shared;
sourceTree = "";
};
- DAC212B1D8E90084ABE25A3B3FFC6E00 /* Support Files */ = {
+ CF1408CF629C7361332E53B88F7BD30C = {
isa = PBXGroup;
children = (
- 45CF8D032A049A7012F30257A8F121AF /* shared-copy-dsyms.sh */,
- 215D65FA831B0E4F8AC0B3826A846FDA /* shared.debug.xcconfig */,
- B7C6BC0A7177E1D2CCCA8D9834206E64 /* shared.release.xcconfig */,
+ 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */,
+ 313FE5FE915A4A924C55AAC02A910D61 /* Development Pods */,
+ D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */,
+ 1F86AA6785DF34AFD5A71790761717DE /* Products */,
+ 11C970DEAE48C6D0282DFE54684F53F1 /* Targets Support Files */,
);
- name = "Support Files";
- path = "../ios/Pods/Target Support Files/shared";
sourceTree = "";
};
- DFA1DB9AC4A7CFB0C413CC312D0FE2B7 /* Frameworks */ = {
+ D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = {
isa = PBXGroup;
children = (
- 670597F16E31933FDD530ED5140D4EEF /* shared.framework */,
+ 578452D2E740E91742655AC8F1636D1F /* iOS */,
);
name = Frameworks;
sourceTree = "";
@@ -204,7 +200,7 @@
buildRules = (
);
dependencies = (
- 6D08CF75140F29DD6A6970543E494B09 /* PBXTargetDependency */,
+ 4A9525469F8E46F3883CC6599FCCFEDB /* PBXTargetDependency */,
);
name = "Pods-iosApp";
productName = Pods_iosApp;
@@ -217,8 +213,8 @@
BFDFE7DC352907FC980B868725387E98 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastSwiftUpdateCheck = 1300;
- LastUpgradeCheck = 1300;
+ LastSwiftUpdateCheck = 1500;
+ LastUpgradeCheck = 1500;
};
buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 12.0";
@@ -291,18 +287,18 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
- 6D08CF75140F29DD6A6970543E494B09 /* PBXTargetDependency */ = {
+ 4A9525469F8E46F3883CC6599FCCFEDB /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = shared;
target = 8777C9F6889E59EFFD631D80AEE9048B /* shared */;
- targetProxy = 3B3DD97234976EAE23DEF848B521F3BD /* PBXContainerItemProxy */;
+ targetProxy = C1E4F2F8101E860063100BCC8448BC3B /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
02DDCCED053337F381DEBAFDEC6F354F /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 244FC2DAA936A0B07ACEFDC74E2D54B8 /* Pods-iosApp.release.xcconfig */;
+ baseConfigurationReference = 9FECCB5AFF87D121F15BA01E683C7932 /* Pods-iosApp.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
CLANG_ENABLE_OBJC_WEAK = NO;
@@ -402,7 +398,7 @@
};
8E1767EF3E210BC4C8DDA6D5A57FC3C6 /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 215D65FA831B0E4F8AC0B3826A846FDA /* shared.debug.xcconfig */;
+ baseConfigurationReference = FD7FD28F3CCDF64520DA04A7CA0DDDC7 /* shared.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
@@ -485,7 +481,7 @@
};
AF088B6CD92A52AC4DCB62DEEC871231 /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = E462E23B3674BF94EAB1504D506F2803 /* Pods-iosApp.debug.xcconfig */;
+ baseConfigurationReference = 3F64BADB16C311E9D09DAD0116F684F4 /* Pods-iosApp.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
CLANG_ENABLE_OBJC_WEAK = NO;
@@ -522,7 +518,7 @@
};
E387420B1FEC2EAB6CA01993F647E86F /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = B7C6BC0A7177E1D2CCCA8D9834206E64 /* shared.release.xcconfig */;
+ baseConfigurationReference = 20D1F143BB7A4CD522117C279A4C293E /* shared.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
diff --git a/ios/Pods/Pods.xcodeproj/xcuserdata/joelkanyi.xcuserdatad/xcschemes/Pods-iosApp.xcscheme b/ios/Pods/Pods.xcodeproj/xcuserdata/joelkanyi.xcuserdatad/xcschemes/Pods-iosApp.xcscheme
index 0673282..d58b01a 100644
--- a/ios/Pods/Pods.xcodeproj/xcuserdata/joelkanyi.xcuserdatad/xcschemes/Pods-iosApp.xcscheme
+++ b/ios/Pods/Pods.xcodeproj/xcuserdata/joelkanyi.xcuserdatad/xcschemes/Pods-iosApp.xcscheme
@@ -1,6 +1,6 @@
{
binaries.withType {
+ @OptIn(ExperimentalKotlinGradlePluginApi::class)
transitiveExport = true
compilations.all {
kotlinOptions.freeCompilerArgs += arrayOf("-linker-options", "-lsqlite3")
@@ -70,87 +72,74 @@ kotlin {
}
sourceSets {
- val commonMain by getting {
- dependencies {
- api(libs.koin.core)
- api(libs.koin.compose)
+ commonMain.dependencies {
+ api(libs.koin.core)
+ api(libs.koin.compose)
- implementation(compose.material3)
- implementation(compose.material)
- implementation(compose.materialIconsExtended)
+ implementation(compose.material3)
+ implementation(compose.material)
+ implementation(compose.materialIconsExtended)
- @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
- implementation(compose.components.resources)
+ implementation(compose.components.resources)
- implementation(libs.voyager.navigator)
- implementation(libs.voyager.bottomSheetNavigator)
- implementation(libs.voyager.transitions)
- implementation(libs.voyager.tabNavigator)
+ implementation(libs.voyager.navigator)
+ implementation(libs.voyager.bottomSheetNavigator)
+ implementation(libs.voyager.transitions)
+ implementation(libs.voyager.tabNavigator)
+ implementation(libs.voyager.koin)
- implementation(libs.kotlinX.serializationJson)
+ implementation(libs.kotlinX.serializationJson)
- implementation(libs.material3.window.size.multiplatform)
+ implementation(libs.material3.window.size.multiplatform)
- implementation(libs.sqlDelight.runtime)
- implementation(libs.sqlDelight.coroutine)
- implementation(libs.primitive.adapters)
+ implementation(libs.sqlDelight.runtime)
+ implementation(libs.coroutines.extensions)
+ implementation(libs.primitive.adapters)
- api(libs.multiplatformSettings.noArg)
- api(libs.multiplatformSettings.coroutines)
+ api(libs.multiplatformSettings.noArg)
+ api(libs.multiplatformSettings.coroutines)
- api(libs.napier)
+ api(libs.napier)
- implementation(libs.kotlinX.dateTime)
- implementation(libs.koalaplot.core)
+ implementation(libs.kotlinX.dateTime)
+ implementation(libs.koalaplot.core)
- implementation(libs.korau)
- implementation(libs.stdlib)
- }
+ implementation(libs.stdlib)
}
- val androidMain by getting {
- dependencies {
- implementation(libs.sqlDelight.android)
- implementation(libs.accompanist.systemUIController)
- implementation(libs.core)
- implementation(libs.compose.activity)
- }
- }
+ androidMain.dependencies {
+ implementation(libs.android.driver)
- val nativeMain by creating {
- dependsOn(commonMain)
+ implementation(libs.accompanist.systemUIController)
+ implementation(libs.core)
+ implementation(libs.compose.activity)
}
- val jvmMain by getting {
- dependencies {
- implementation(libs.sqlDelight.jvm)
- implementation(libs.kotlinx.coroutines.swing)
+ jvmMain.dependencies {
+ implementation(libs.sqlite.driver)
- // Toaster for Windows
- implementation(libs.toast4j)
+ implementation(libs.kotlinx.coroutines.swing)
- // JNA for Linux
- implementation("de.jangassen:jfa:1.2.0") {
- // not excluding this leads to a strange error during build:
- // > Could not find jna-5.13.0-jpms.jar (net.java.dev.jna:jna:5.13.0)
- exclude(group = "net.java.dev.jna", module = "jna")
- }
- }
- }
+ // Toaster for Windows
+ implementation(libs.toast4j)
- val iosX64Main by getting
- val iosArm64Main by getting
- val iosSimulatorArm64Main by getting
- val iosMain by creating {
- dependsOn(commonMain)
- iosArm64Main.dependsOn(this)
- iosX64Main.dependsOn(this)
- iosSimulatorArm64Main.dependsOn(this)
- dependencies {
- implementation(libs.sqlDelight.native)
- implementation(libs.components.resources)
+ // JNA for Linux
+ implementation("de.jangassen:jfa:1.2.0") {
+ // not excluding this leads to a strange error during build:
+ // > Could not find jna-5.13.0-jpms.jar (net.java.dev.jna:jna:5.13.0)
+ exclude(group = "net.java.dev.jna", module = "jna")
}
+
+ // JNA for Windows
+ implementation(libs.jna)
}
+
+ iosMain.dependencies {
+ implementation(libs.native.driver)
+
+
+ @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
+ implementation(compose.components.resources) }
}
}
@@ -160,4 +149,4 @@ sqldelight {
packageName.set("com.joelkanyi.focusbloom.database")
}
}
-}
+}
\ No newline at end of file
diff --git a/shared/shared.podspec b/shared/shared.podspec
index a3151bc..0854e51 100644
--- a/shared/shared.podspec
+++ b/shared/shared.podspec
@@ -8,9 +8,24 @@ Pod::Spec.new do |spec|
spec.summary = 'Some description for a Kotlin/Native module'
spec.vendored_frameworks = 'build/cocoapods/framework/shared.framework'
spec.libraries = 'c++'
- spec.ios.deployment_target = '14.1'
+ spec.ios.deployment_target = '14.1'
+ if !Dir.exist?('build/cocoapods/framework/shared.framework') || Dir.empty?('build/cocoapods/framework/shared.framework')
+ raise "
+
+ Kotlin framework 'shared' doesn't exist yet, so a proper Xcode project can't be generated.
+ 'pod install' should be executed after running ':generateDummyFramework' Gradle task:
+
+ ./gradlew :shared:generateDummyFramework
+
+ Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)"
+ end
+
+ spec.xcconfig = {
+ 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO',
+ }
+
spec.pod_target_xcconfig = {
'KOTLIN_PROJECT_PATH' => ':shared',
'PRODUCT_MODULE_NAME' => 'shared',
@@ -35,5 +50,5 @@ Pod::Spec.new do |spec|
SCRIPT
}
]
- spec.resources = ['build/compose/ios/shared/compose-resources']
+ spec.resources = ['build/compose/cocoapods/compose-resources']
end
\ No newline at end of file
diff --git a/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt b/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
index b167d04..973d123 100644
--- a/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
+++ b/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
@@ -18,11 +18,9 @@ package com.joelkanyi.focusbloom.di
import com.joelkanyi.focusbloom.platform.DatabaseDriverFactory
import com.joelkanyi.focusbloom.platform.MultiplatformSettingsWrapper
import com.joelkanyi.focusbloom.platform.NotificationsManager
-import com.russhwolf.settings.ExperimentalSettingsApi
import org.koin.core.module.Module
import org.koin.dsl.module
-@OptIn(ExperimentalSettingsApi::class)
actual fun platformModule(): Module = module {
single { MultiplatformSettingsWrapper(context = get()).createSettings() }
single { DatabaseDriverFactory(context = get()) }
diff --git a/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/platform/Font.android.kt b/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/platform/Font.android.kt
deleted file mode 100644
index 6585ad5..0000000
--- a/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/platform/Font.android.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2023 Joel Kanyi.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.joelkanyi.focusbloom.platform
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.text.font.Font
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontWeight
-
-@Composable
-actual fun font(name: String, res: String, weight: FontWeight, style: FontStyle): Font {
- val context = LocalContext.current
- val id = context.resources.getIdentifier(res, "font", context.packageName)
- return Font(id, weight, style)
-}
diff --git a/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.android.kt b/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.android.kt
index 19cdefe..68d0133 100644
--- a/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.android.kt
+++ b/shared/src/androidMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.android.kt
@@ -28,14 +28,14 @@ import androidx.core.app.NotificationManagerCompat
import com.joelkanyi.focusbloom.shared.R
actual class NotificationsManager(
- private val context: Context
+ private val context: Context,
) {
private val notificationManager get() = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@SuppressLint("MissingPermission")
actual fun showNotification(
title: String,
- description: String
+ description: String,
) {
// TODO: use a PendingIntent to open the app on notification click
// Intent for the notification click
@@ -45,7 +45,7 @@ actual class NotificationsManager(
}*/
val sound = Uri.parse(
- "${ContentResolver.SCHEME_ANDROID_RESOURCE}://${context.applicationContext.packageName}/${R.raw.alarm}"
+ "${ContentResolver.SCHEME_ANDROID_RESOURCE}://${context.applicationContext.packageName}/${R.raw.alarm}",
)
println("sound: $sound")
@@ -76,7 +76,7 @@ actual class NotificationsManager(
channelId,
channelName,
- NotificationManager.IMPORTANCE_HIGH
+ NotificationManager.IMPORTANCE_HIGH,
).apply {
description = channelDescription
setSound(sound, Notification.AUDIO_ATTRIBUTES_DEFAULT)
diff --git a/shared/src/commonMain/resources/add_filled.xml b/shared/src/commonMain/composeResources/drawable/add_filled.xml
similarity index 100%
rename from shared/src/commonMain/resources/add_filled.xml
rename to shared/src/commonMain/composeResources/drawable/add_filled.xml
diff --git a/shared/src/commonMain/resources/add_outlined.xml b/shared/src/commonMain/composeResources/drawable/add_outlined.xml
similarity index 100%
rename from shared/src/commonMain/resources/add_outlined.xml
rename to shared/src/commonMain/composeResources/drawable/add_outlined.xml
diff --git a/shared/src/commonMain/resources/calendar_filled.xml b/shared/src/commonMain/composeResources/drawable/calendar_filled.xml
similarity index 100%
rename from shared/src/commonMain/resources/calendar_filled.xml
rename to shared/src/commonMain/composeResources/drawable/calendar_filled.xml
diff --git a/shared/src/commonMain/resources/calendar_outlined.xml b/shared/src/commonMain/composeResources/drawable/calendar_outlined.xml
similarity index 100%
rename from shared/src/commonMain/resources/calendar_outlined.xml
rename to shared/src/commonMain/composeResources/drawable/calendar_outlined.xml
diff --git a/shared/src/commonMain/resources/end_time.xml b/shared/src/commonMain/composeResources/drawable/end_time.xml
similarity index 100%
rename from shared/src/commonMain/resources/end_time.xml
rename to shared/src/commonMain/composeResources/drawable/end_time.xml
diff --git a/shared/src/commonMain/resources/home_filled.xml b/shared/src/commonMain/composeResources/drawable/home_filled.xml
similarity index 100%
rename from shared/src/commonMain/resources/home_filled.xml
rename to shared/src/commonMain/composeResources/drawable/home_filled.xml
diff --git a/shared/src/commonMain/resources/home_outlined.xml b/shared/src/commonMain/composeResources/drawable/home_outlined.xml
similarity index 100%
rename from shared/src/commonMain/resources/home_outlined.xml
rename to shared/src/commonMain/composeResources/drawable/home_outlined.xml
diff --git a/shared/src/commonMain/resources/ic_complete.xml b/shared/src/commonMain/composeResources/drawable/ic_complete.xml
similarity index 100%
rename from shared/src/commonMain/resources/ic_complete.xml
rename to shared/src/commonMain/composeResources/drawable/ic_complete.xml
diff --git a/shared/src/commonMain/resources/ic_school.xml b/shared/src/commonMain/composeResources/drawable/ic_school.xml
similarity index 100%
rename from shared/src/commonMain/resources/ic_school.xml
rename to shared/src/commonMain/composeResources/drawable/ic_school.xml
diff --git a/shared/src/commonMain/resources/ic_time.xml b/shared/src/commonMain/composeResources/drawable/ic_time.xml
similarity index 100%
rename from shared/src/commonMain/resources/ic_time.xml
rename to shared/src/commonMain/composeResources/drawable/ic_time.xml
diff --git a/shared/src/commonMain/resources/ic_work.xml b/shared/src/commonMain/composeResources/drawable/ic_work.xml
similarity index 100%
rename from shared/src/commonMain/resources/ic_work.xml
rename to shared/src/commonMain/composeResources/drawable/ic_work.xml
diff --git a/shared/src/commonMain/resources/il_completed.xml b/shared/src/commonMain/composeResources/drawable/il_completed.xml
similarity index 100%
rename from shared/src/commonMain/resources/il_completed.xml
rename to shared/src/commonMain/composeResources/drawable/il_completed.xml
diff --git a/shared/src/commonMain/resources/il_empty.xml b/shared/src/commonMain/composeResources/drawable/il_empty.xml
similarity index 100%
rename from shared/src/commonMain/resources/il_empty.xml
rename to shared/src/commonMain/composeResources/drawable/il_empty.xml
diff --git a/shared/src/commonMain/resources/il_statistics.xml b/shared/src/commonMain/composeResources/drawable/il_statistics.xml
similarity index 100%
rename from shared/src/commonMain/resources/il_statistics.xml
rename to shared/src/commonMain/composeResources/drawable/il_statistics.xml
diff --git a/shared/src/commonMain/resources/il_tasks.xml b/shared/src/commonMain/composeResources/drawable/il_tasks.xml
similarity index 100%
rename from shared/src/commonMain/resources/il_tasks.xml
rename to shared/src/commonMain/composeResources/drawable/il_tasks.xml
diff --git a/shared/src/commonMain/resources/il_work_time.xml b/shared/src/commonMain/composeResources/drawable/il_work_time.xml
similarity index 100%
rename from shared/src/commonMain/resources/il_work_time.xml
rename to shared/src/commonMain/composeResources/drawable/il_work_time.xml
diff --git a/shared/src/commonMain/resources/other.xml b/shared/src/commonMain/composeResources/drawable/other.xml
similarity index 100%
rename from shared/src/commonMain/resources/other.xml
rename to shared/src/commonMain/composeResources/drawable/other.xml
diff --git a/shared/src/commonMain/resources/personal.xml b/shared/src/commonMain/composeResources/drawable/personal.xml
similarity index 100%
rename from shared/src/commonMain/resources/personal.xml
rename to shared/src/commonMain/composeResources/drawable/personal.xml
diff --git a/shared/src/commonMain/resources/redo.xml b/shared/src/commonMain/composeResources/drawable/redo.xml
similarity index 100%
rename from shared/src/commonMain/resources/redo.xml
rename to shared/src/commonMain/composeResources/drawable/redo.xml
diff --git a/shared/src/commonMain/resources/settings_filled.xml b/shared/src/commonMain/composeResources/drawable/settings_filled.xml
similarity index 100%
rename from shared/src/commonMain/resources/settings_filled.xml
rename to shared/src/commonMain/composeResources/drawable/settings_filled.xml
diff --git a/shared/src/commonMain/resources/settings_outlined.xml b/shared/src/commonMain/composeResources/drawable/settings_outlined.xml
similarity index 100%
rename from shared/src/commonMain/resources/settings_outlined.xml
rename to shared/src/commonMain/composeResources/drawable/settings_outlined.xml
diff --git a/shared/src/commonMain/resources/start_time.xml b/shared/src/commonMain/composeResources/drawable/start_time.xml
similarity index 100%
rename from shared/src/commonMain/resources/start_time.xml
rename to shared/src/commonMain/composeResources/drawable/start_time.xml
diff --git a/shared/src/commonMain/resources/statistics_filled.xml b/shared/src/commonMain/composeResources/drawable/statistics_filled.xml
similarity index 100%
rename from shared/src/commonMain/resources/statistics_filled.xml
rename to shared/src/commonMain/composeResources/drawable/statistics_filled.xml
diff --git a/shared/src/commonMain/resources/statistics_outlined.xml b/shared/src/commonMain/composeResources/drawable/statistics_outlined.xml
similarity index 100%
rename from shared/src/commonMain/resources/statistics_outlined.xml
rename to shared/src/commonMain/composeResources/drawable/statistics_outlined.xml
diff --git a/shared/src/commonMain/resources/study.xml b/shared/src/commonMain/composeResources/drawable/study.xml
similarity index 100%
rename from shared/src/commonMain/resources/study.xml
rename to shared/src/commonMain/composeResources/drawable/study.xml
diff --git a/shared/src/commonMain/resources/work.xml b/shared/src/commonMain/composeResources/drawable/work.xml
similarity index 100%
rename from shared/src/commonMain/resources/work.xml
rename to shared/src/commonMain/composeResources/drawable/work.xml
diff --git a/shared/src/commonMain/resources/font/montserrat_black.ttf b/shared/src/commonMain/composeResources/font/montserrat_black.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_black.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_black.ttf
diff --git a/shared/src/commonMain/resources/font/montserrat_bold.ttf b/shared/src/commonMain/composeResources/font/montserrat_bold.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_bold.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_bold.ttf
diff --git a/shared/src/commonMain/resources/font/montserrat_extrabold.ttf b/shared/src/commonMain/composeResources/font/montserrat_extrabold.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_extrabold.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_extrabold.ttf
diff --git a/shared/src/commonMain/resources/font/montserrat_extralight.ttf b/shared/src/commonMain/composeResources/font/montserrat_extralight.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_extralight.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_extralight.ttf
diff --git a/shared/src/commonMain/resources/font/montserrat_light.ttf b/shared/src/commonMain/composeResources/font/montserrat_light.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_light.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_light.ttf
diff --git a/shared/src/commonMain/resources/font/montserrat_medium.ttf b/shared/src/commonMain/composeResources/font/montserrat_medium.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_medium.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_medium.ttf
diff --git a/shared/src/commonMain/resources/font/montserrat_regular.ttf b/shared/src/commonMain/composeResources/font/montserrat_regular.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_regular.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_regular.ttf
diff --git a/shared/src/commonMain/resources/font/montserrat_semi_bold.ttf b/shared/src/commonMain/composeResources/font/montserrat_semi_bold.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_semi_bold.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_semi_bold.ttf
diff --git a/shared/src/commonMain/resources/font/montserrat_thin.ttf b/shared/src/commonMain/composeResources/font/montserrat_thin.ttf
similarity index 100%
rename from shared/src/commonMain/resources/font/montserrat_thin.ttf
rename to shared/src/commonMain/composeResources/font/montserrat_thin.ttf
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/FocusBloomApp.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/FocusBloomApp.kt
index bf8a8b4..f0dec41 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/FocusBloomApp.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/FocusBloomApp.kt
@@ -21,56 +21,56 @@ import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
+import cafe.adriel.voyager.navigator.CurrentScreen
import cafe.adriel.voyager.navigator.Navigator
-import cafe.adriel.voyager.transitions.SlideTransition
import com.joelkanyi.focusbloom.core.presentation.theme.FocusBloomTheme
-import com.joelkanyi.focusbloom.core.utils.ProvideAppNavigator
import com.joelkanyi.focusbloom.feature.onboarding.OnboardingScreen
import com.joelkanyi.focusbloom.main.MainScreen
import com.joelkanyi.focusbloom.main.MainViewModel
import com.joelkanyi.focusbloom.main.OnBoardingState
import com.joelkanyi.focusbloom.platform.StatusBarColors
-import org.koin.compose.rememberKoinInject
+import org.koin.compose.KoinContext
+import org.koin.compose.koinInject
@Composable
-fun FocusBloomApp() {
- val mainViewModel = rememberKoinInject()
+fun FocusBloomApp(
+ mainViewModel: MainViewModel = koinInject(),
+) {
val darkTheme = when (mainViewModel.appTheme.collectAsState().value) {
1 -> true
else -> false
}
val onBoardingCompleted = mainViewModel.onBoardingCompleted.collectAsState().value
- FocusBloomTheme(
- useDarkTheme = darkTheme
- ) {
- StatusBarColors(
- statusBarColor = MaterialTheme.colorScheme.background,
- navBarColor = MaterialTheme.colorScheme.background
- )
- when (onBoardingCompleted) {
- is OnBoardingState.Success -> {
- Surface(
- modifier = Modifier.fillMaxSize(),
- color = MaterialTheme.colorScheme.background
- ) {
- Navigator(
- screen = if (onBoardingCompleted.completed) {
- MainScreen()
- } else {
- OnboardingScreen()
- },
- content = { navigator ->
- ProvideAppNavigator(
- navigator = navigator,
- content = { SlideTransition(navigator = navigator) }
- )
- }
- )
+ KoinContext {
+ FocusBloomTheme(
+ useDarkTheme = darkTheme,
+ ) {
+ StatusBarColors(
+ statusBarColor = MaterialTheme.colorScheme.background,
+ navBarColor = MaterialTheme.colorScheme.background,
+ )
+ when (onBoardingCompleted) {
+ is OnBoardingState.Success -> {
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colorScheme.background,
+ ) {
+ Navigator(
+ screen = if (onBoardingCompleted.completed) {
+ MainScreen()
+ } else {
+ OnboardingScreen()
+ },
+ content = {
+ CurrentScreen()
+ },
+ )
+ }
}
- }
- else -> {}
+ else -> {}
+ }
}
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/local/setting/PreferenceManager.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/local/setting/PreferenceManager.kt
index 47dec2e..7161f67 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/local/setting/PreferenceManager.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/local/setting/PreferenceManager.kt
@@ -38,7 +38,7 @@ class PreferenceManager constructor(private val settings: Settings) {
@OptIn(ExperimentalSettingsApi::class)
fun getNonFlowString(key: String) = observableSettings.getString(
key = key,
- defaultValue = ""
+ defaultValue = "",
)
@OptIn(ExperimentalCoroutinesApi::class, ExperimentalSettingsApi::class)
@@ -77,7 +77,7 @@ class PreferenceManager constructor(private val settings: Settings) {
fun getBoolean(key: String): Flow {
return observableSettings.getBooleanFlow(
key = key,
- defaultValue = false
+ defaultValue = false,
)
}
@@ -90,11 +90,10 @@ class PreferenceManager constructor(private val settings: Settings) {
fun getLong(key: Any): Flow {
return observableSettings.getLongFlow(
key = key.toString(),
- defaultValue = 0
+ defaultValue = 0,
)
}
- @OptIn(ExperimentalSettingsApi::class)
fun setLong(key: String, value: Long) {
observableSettings.set(key = key, value = value)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/mapper/Mappers.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/mapper/Mappers.kt
index b5a0e9b..6ed9b12 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/mapper/Mappers.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/mapper/Mappers.kt
@@ -36,7 +36,7 @@ fun TaskEntity.toTask() = Task(
consumedLongBreakTime = consumedLongBreakTime,
inProgressTask = inProgressTask,
currentCycle = currentCycle,
- active = active
+ active = active,
)
fun Task.toTaskEntity() = TaskEntity(
@@ -55,5 +55,5 @@ fun Task.toTaskEntity() = TaskEntity(
consumedLongBreakTime = consumedLongBreakTime,
inProgressTask = inProgressTask,
currentCycle = currentCycle,
- active = active
+ active = active,
)
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/repository/settings/SettingsRepositoryImpl.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/repository/settings/SettingsRepositoryImpl.kt
index f92d328..1b70482 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/repository/settings/SettingsRepositoryImpl.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/repository/settings/SettingsRepositoryImpl.kt
@@ -20,7 +20,7 @@ import com.joelkanyi.focusbloom.core.domain.repository.settings.SettingsReposito
import kotlinx.coroutines.flow.Flow
class SettingsRepositoryImpl(
- private val preferenceManager: PreferenceManager
+ private val preferenceManager: PreferenceManager,
) : SettingsRepository {
override suspend fun saveAppTheme(theme: Int) {
preferenceManager.setInt(key = PreferenceManager.APP_THEME, value = theme)
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/repository/tasks/TasksRepositoryImpl.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/repository/tasks/TasksRepositoryImpl.kt
index d1e9716..64e22ab 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/repository/tasks/TasksRepositoryImpl.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/repository/tasks/TasksRepositoryImpl.kt
@@ -27,7 +27,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class TasksRepositoryImpl(
- bloomDatabase: BloomDatabase
+ bloomDatabase: BloomDatabase,
) : TasksRepository {
private val dbQuery = bloomDatabase.taskQueries
override fun getTasks(): Flow> {
@@ -69,7 +69,7 @@ class TasksRepositoryImpl(
consumedLongBreakTime = it.consumedLongBreakTime,
inProgressTask = it.inProgressTask,
currentCycle = it.currentCycle,
- active = it.active
+ active = it.active,
)
}
}
@@ -86,7 +86,7 @@ class TasksRepositoryImpl(
date = it.date,
focusSessions = it.focusSessions,
completed = it.completed,
- active = it.active
+ active = it.active,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/utils/DbHelpers.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/utils/DbHelpers.kt
index 3b20f50..64ad8a8 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/utils/DbHelpers.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/data/utils/DbHelpers.kt
@@ -26,7 +26,7 @@ import kotlin.jvm.JvmOverloads
@JvmOverloads
fun Flow>.mapToOne(
- context: CoroutineContext = Dispatchers.Default
+ context: CoroutineContext = Dispatchers.Default,
): Flow = map {
withContext(context) {
it.executeAsOne()
@@ -36,7 +36,7 @@ fun Flow>.mapToOne(
@JvmOverloads
fun Flow>.mapToOneOrDefault(
defaultValue: T,
- context: CoroutineContext = Dispatchers.Default
+ context: CoroutineContext = Dispatchers.Default,
): Flow = map {
withContext(context) {
it.executeAsOneOrNull() ?: defaultValue
@@ -45,7 +45,7 @@ fun Flow>.mapToOneOrDefault(
@JvmOverloads
fun Flow>.mapToOneOrNull(
- context: CoroutineContext = Dispatchers.Default
+ context: CoroutineContext = Dispatchers.Default,
): Flow = map {
withContext(context) {
it.executeAsOneOrNull()
@@ -54,7 +54,7 @@ fun Flow>.mapToOneOrNull(
@JvmOverloads
fun Flow>.mapToOneNotNull(
- context: CoroutineContext = Dispatchers.Default
+ context: CoroutineContext = Dispatchers.Default,
): Flow = mapNotNull {
withContext(context) {
it.executeAsOneOrNull()
@@ -63,7 +63,7 @@ fun Flow>.mapToOneNotNull(
@JvmOverloads
fun Flow>.mapToList(
- context: CoroutineContext = Dispatchers.Default
+ context: CoroutineContext = Dispatchers.Default,
): Flow> = map {
withContext(context) {
it.executeAsList()
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/Task.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/Task.kt
index cbb7eaa..92d3168 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/Task.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/Task.kt
@@ -33,5 +33,5 @@ data class Task(
val consumedShortBreakTime: Long,
val consumedLongBreakTime: Long,
val inProgressTask: Boolean,
- val active: Boolean
+ val active: Boolean,
)
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/TaskType.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/TaskType.kt
index 5376696..1fe93de 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/TaskType.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/TaskType.kt
@@ -15,35 +15,44 @@
*/
package com.joelkanyi.focusbloom.core.domain.model
-data class TaskType(
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.other
+import focusbloom.shared.generated.resources.personal
+import focusbloom.shared.generated.resources.study
+import focusbloom.shared.generated.resources.work
+import org.jetbrains.compose.resources.DrawableResource
+import org.jetbrains.compose.resources.ExperimentalResourceApi
+
+data class TaskType @OptIn(ExperimentalResourceApi::class) constructor(
val name: String,
- val icon: String,
- val color: Long
+ val icon: DrawableResource,
+ val color: Long,
) {
override fun toString(): String {
return name
}
}
+@OptIn(ExperimentalResourceApi::class)
val taskTypes = listOf(
TaskType(
name = "Work",
- icon = "work.xml",
- color = 0xFF3375fd
+ icon = Res.drawable.work,
+ color = 0xFF3375fd,
),
TaskType(
name = "Study",
- icon = "study.xml",
- color = 0xFFff686d
+ icon = Res.drawable.study,
+ color = 0xFFff686d,
),
TaskType(
name = "Personal",
- icon = "personal.xml",
- color = 0xFF24c469
+ icon = Res.drawable.personal,
+ color = 0xFF24c469,
),
TaskType(
name = "Other",
- icon = "other.xml",
- color = 0xFF734efe
- )
+ icon = Res.drawable.other,
+ color = 0xFF734efe,
+ ),
)
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/TextFieldState.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/TextFieldState.kt
index 73f1114..f231d8f 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/TextFieldState.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/domain/model/TextFieldState.kt
@@ -17,5 +17,5 @@ package com.joelkanyi.focusbloom.core.domain.model
data class TextFieldState(
val text: String = "",
- val error: String? = null
+ val error: String? = null,
)
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomButton.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomButton.kt
index b5e473b..0ef329a 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomButton.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomButton.kt
@@ -24,14 +24,20 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
@Composable
-fun BloomButton(modifier: Modifier = Modifier, onClick: () -> Unit, shape: Shape = MaterialTheme.shapes.medium, backgroundColor: Color = MaterialTheme.colorScheme.primary, content: @Composable () -> Unit) {
+fun BloomButton(
+ modifier: Modifier = Modifier,
+ onClick: () -> Unit,
+ shape: Shape = MaterialTheme.shapes.medium,
+ backgroundColor: Color = MaterialTheme.colorScheme.primary,
+ content: @Composable () -> Unit,
+) {
Button(
modifier = modifier,
onClick = onClick,
shape = shape,
colors = ButtonDefaults.buttonColors(
- containerColor = backgroundColor
- )
+ containerColor = backgroundColor,
+ ),
) {
content()
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomCircleButton.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomCircleButton.kt
index b5ff5e0..87a530c 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomCircleButton.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomCircleButton.kt
@@ -28,7 +28,12 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
-fun BloomCircleButton(modifier: Modifier = Modifier, icon: @Composable () -> Unit, onClick: () -> Unit, color: Color) {
+fun BloomCircleButton(
+ modifier: Modifier = Modifier,
+ icon: @Composable () -> Unit,
+ onClick: () -> Unit,
+ color: Color,
+) {
Box(
modifier = modifier
.size(48.dp)
@@ -37,7 +42,7 @@ fun BloomCircleButton(modifier: Modifier = Modifier, icon: @Composable () -> Uni
.clickable {
onClick()
},
- contentAlignment = Alignment.Center
+ contentAlignment = Alignment.Center,
) {
icon()
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomDropDown.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomDropDown.kt
index e0c2601..14b4fd7 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomDropDown.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomDropDown.kt
@@ -57,7 +57,7 @@ fun BloomDropDown(
selectedOption: TextFieldState,
onOptionSelected: (T) -> Unit,
textStyle: TextStyle = MaterialTheme.typography.titleSmall,
- shape: CornerBasedShape = MaterialTheme.shapes.small
+ shape: CornerBasedShape = MaterialTheme.shapes.small,
) {
var expanded by remember { mutableStateOf(false) }
Column {
@@ -76,7 +76,7 @@ fun BloomDropDown(
} else {
MaterialTheme.colorScheme.onBackground.copy(alpha = .4f)
},
- shape = shape
+ shape = shape,
)
.clip(shape)
.clickable {
@@ -84,21 +84,21 @@ fun BloomDropDown(
expanded = !expanded
}
},
- contentAlignment = Alignment.CenterStart
+ contentAlignment = Alignment.CenterStart,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
vertical = 8.dp,
- horizontal = 12.dp
+ horizontal = 12.dp,
),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = selectedOption.text,
- style = textStyle
+ style = textStyle,
)
if (enabled) {
Icon(
@@ -110,26 +110,26 @@ fun BloomDropDown(
} else {
Icons.Filled.ArrowDropDown
},
- contentDescription = null
+ contentDescription = null,
)
}
}
DropdownMenu(
expanded = expanded,
- onDismissRequest = { expanded = false }
+ onDismissRequest = { expanded = false },
) {
options.forEach { selectionOption ->
DropdownMenuItem(
text = {
Text(
text = selectionOption.toString(),
- style = MaterialTheme.typography.labelLarge
+ style = MaterialTheme.typography.labelLarge,
)
},
onClick = {
onOptionSelected(selectionOption)
expanded = false
- }
+ },
)
}
}
@@ -140,7 +140,7 @@ fun BloomDropDown(
text = selectedOption.error,
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.error,
- textAlign = TextAlign.End
+ textAlign = TextAlign.End,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomIncrementer.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomIncrementer.kt
index 0c6e9ed..8f9f04a 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomIncrementer.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomIncrementer.kt
@@ -31,29 +31,34 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
-fun BloomIncrementer(modifier: Modifier = Modifier, onClickRemove: () -> Unit, onClickAdd: () -> Unit, currentValue: Int) {
+fun BloomIncrementer(
+ modifier: Modifier = Modifier,
+ onClickRemove: () -> Unit,
+ onClickAdd: () -> Unit,
+ currentValue: Int,
+) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.Center
+ horizontalArrangement = Arrangement.Center,
) {
BloomCircleButton(
icon = {
Icon(
imageVector = Icons.Filled.Remove,
contentDescription = null,
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
},
onClick = onClickRemove,
- color = MaterialTheme.colorScheme.primary
+ color = MaterialTheme.colorScheme.primary,
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "$currentValue",
- style = MaterialTheme.typography.titleLarge
+ style = MaterialTheme.typography.titleLarge,
)
Spacer(modifier = Modifier.width(12.dp))
@@ -63,11 +68,11 @@ fun BloomIncrementer(modifier: Modifier = Modifier, onClickRemove: () -> Unit, o
Icon(
imageVector = Icons.Filled.Add,
contentDescription = null,
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
},
onClick = onClickAdd,
- color = MaterialTheme.colorScheme.primary
+ color = MaterialTheme.colorScheme.primary,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomInputTextField.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomInputTextField.kt
index d670b75..adfc1ea 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomInputTextField.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomInputTextField.kt
@@ -57,10 +57,10 @@ fun BloomInputTextField(
onValueChange: (String) -> Unit,
textStyle: TextStyle = MaterialTheme.typography.titleSmall,
shape: CornerBasedShape = MaterialTheme.shapes.small,
- keyboardOptions: KeyboardOptions = KeyboardOptions.Default
+ keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
) {
Column(
- modifier = modifier
+ modifier = modifier,
) {
if (label != null) {
label()
@@ -79,21 +79,29 @@ fun BloomInputTextField(
maxLines = maxLines,
singleLine = maxLines == 1,
keyboardOptions = keyboardOptions,
- readOnly = !editable
+ readOnly = !editable,
)
if (!value.error.isNullOrEmpty()) {
Text(
text = value.error,
style = MaterialTheme.typography.bodyMedium.copy(
- color = MaterialTheme.colorScheme.error
- )
+ color = MaterialTheme.colorScheme.error,
+ ),
)
}
}
}
@Composable
-fun BloomDateBoxField(modifier: Modifier = Modifier, label: (@Composable () -> Unit)? = null, enabled: Boolean = true, currentTextState: TextFieldState, onClick: () -> Unit, textStyle: TextStyle = MaterialTheme.typography.titleSmall, shape: CornerBasedShape = MaterialTheme.shapes.small) {
+fun BloomDateBoxField(
+ modifier: Modifier = Modifier,
+ label: (@Composable () -> Unit)? = null,
+ enabled: Boolean = true,
+ currentTextState: TextFieldState,
+ onClick: () -> Unit,
+ textStyle: TextStyle = MaterialTheme.typography.titleSmall,
+ shape: CornerBasedShape = MaterialTheme.shapes.small,
+) {
Column {
if (label != null) {
label()
@@ -109,27 +117,27 @@ fun BloomDateBoxField(modifier: Modifier = Modifier, label: (@Composable () -> U
} else {
MaterialTheme.colorScheme.onBackground.copy(alpha = .4f)
},
- shape = shape
+ shape = shape,
)
.clip(shape)
.clickable {
onClick()
},
- contentAlignment = Alignment.CenterStart
+ contentAlignment = Alignment.CenterStart,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
vertical = 8.dp,
- horizontal = 12.dp
+ horizontal = 12.dp,
),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = currentTextState.text,
- style = textStyle
+ style = textStyle,
)
if (enabled) {
Icon(
@@ -137,7 +145,7 @@ fun BloomDateBoxField(modifier: Modifier = Modifier, label: (@Composable () -> U
.padding(start = 8.dp)
.size(24.dp),
imageVector = Icons.Default.DateRange,
- contentDescription = null
+ contentDescription = null,
)
}
}
@@ -148,7 +156,7 @@ fun BloomDateBoxField(modifier: Modifier = Modifier, label: (@Composable () -> U
text = currentTextState.error,
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.error,
- textAlign = TextAlign.End
+ textAlign = TextAlign.End,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomNavigationRailBar.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomNavigationRailBar.kt
index 1d73cbc..ecddbac 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomNavigationRailBar.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomNavigationRailBar.kt
@@ -31,7 +31,11 @@ import cafe.adriel.voyager.navigator.tab.TabNavigator
import com.joelkanyi.focusbloom.core.presentation.utils.FilledIcon
@Composable
-fun BloomNavigationRailBar(modifier: Modifier = Modifier, tabNavigator: TabNavigator, navRailItems: List) {
+fun BloomNavigationRailBar(
+ modifier: Modifier = Modifier,
+ tabNavigator: TabNavigator,
+ navRailItems: List,
+) {
NavigationRail(
modifier = modifier.fillMaxHeight().alpha(0.95F),
containerColor = MaterialTheme.colorScheme.surface,
@@ -43,7 +47,7 @@ fun BloomNavigationRailBar(modifier: Modifier = Modifier, tabNavigator: TabNavig
contentDescription = "Logo",
)*/
},
- contentColor = MaterialTheme.colorScheme.onSurface
+ contentColor = MaterialTheme.colorScheme.onSurface,
) {
navRailItems.forEach { item ->
val isSelected = tabNavigator.current == item
@@ -57,14 +61,14 @@ fun BloomNavigationRailBar(modifier: Modifier = Modifier, tabNavigator: TabNavig
} else {
it
},
- contentDescription = item.options.title
+ contentDescription = item.options.title,
)
}
},
label = { Text(text = item.options.title) },
alwaysShowLabel = true,
selected = tabNavigator.current == item,
- onClick = { tabNavigator.current = item }
+ onClick = { tabNavigator.current = item },
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTab.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTab.kt
index 79375f8..9552c38 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTab.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTab.kt
@@ -24,6 +24,12 @@ import com.joelkanyi.focusbloom.feature.calendar.CalendarScreen
import com.joelkanyi.focusbloom.feature.home.HomeScreen
import com.joelkanyi.focusbloom.feature.settings.SettingsScreen
import com.joelkanyi.focusbloom.feature.statistics.StatisticsScreen
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.add_outlined
+import focusbloom.shared.generated.resources.calendar_outlined
+import focusbloom.shared.generated.resources.home_outlined
+import focusbloom.shared.generated.resources.settings_outlined
+import focusbloom.shared.generated.resources.statistics_outlined
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
@@ -34,13 +40,13 @@ internal sealed class BloomTab {
@Composable
get() {
val title = "Home"
- val icon = painterResource("home_outlined.xml")
+ val icon = painterResource(Res.drawable.home_outlined)
return remember {
TabOptions(
index = 0u,
title = title,
- icon = icon
+ icon = icon,
)
}
}
@@ -57,13 +63,13 @@ internal sealed class BloomTab {
@Composable
get() {
val title = "Calendar"
- val icon = painterResource("calendar_outlined.xml")
+ val icon = painterResource(Res.drawable.calendar_outlined)
return remember {
TabOptions(
index = 1u,
title = title,
- icon = icon
+ icon = icon,
)
}
}
@@ -80,13 +86,13 @@ internal sealed class BloomTab {
@Composable
get() {
val title = "Statistics"
- val icon = painterResource("statistics_outlined.xml")
+ val icon = painterResource(Res.drawable.statistics_outlined)
return remember {
TabOptions(
index = 2u,
title = title,
- icon = icon
+ icon = icon,
)
}
}
@@ -103,13 +109,13 @@ internal sealed class BloomTab {
@Composable
get() {
val title = "Settings"
- val icon = painterResource("settings_outlined.xml")
+ val icon = painterResource(Res.drawable.settings_outlined)
return remember {
TabOptions(
index = 3u,
title = title,
- icon = icon
+ icon = icon,
)
}
}
@@ -121,20 +127,20 @@ internal sealed class BloomTab {
}
internal data class AddTaskTab(
- val taskId: Int? = null
+ val taskId: Int? = null,
) : Tab {
@OptIn(ExperimentalResourceApi::class)
override val options: TabOptions
@Composable
get() {
val title = "Add Task"
- val icon = painterResource("add_outlined.xml")
+ val icon = painterResource(Res.drawable.add_outlined)
return remember {
TabOptions(
index = 4u,
title = title,
- icon = icon
+ icon = icon,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTimerControls.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTimerControls.kt
index 3538aa5..7176790 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTimerControls.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTimerControls.kt
@@ -33,18 +33,24 @@ import androidx.compose.ui.unit.dp
import com.joelkanyi.focusbloom.feature.taskprogress.TimerState
@Composable
-fun BloomTimerControls(modifier: Modifier = Modifier, state: TimerState, onClickReset: () -> Unit, onClickNext: () -> Unit, onClickAction: (state: TimerState) -> Unit) {
+fun BloomTimerControls(
+ modifier: Modifier = Modifier,
+ state: TimerState,
+ onClickReset: () -> Unit,
+ onClickNext: () -> Unit,
+ onClickAction: (state: TimerState) -> Unit,
+) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceAround
+ horizontalArrangement = Arrangement.SpaceAround,
) {
IconButton(onClick = onClickReset) {
Icon(
modifier = Modifier.size(120.dp),
imageVector = Icons.Filled.Replay,
contentDescription = "Reset Timer",
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
}
@@ -57,24 +63,27 @@ fun BloomTimerControls(modifier: Modifier = Modifier, state: TimerState, onClick
TimerState.Paused -> {
Icons.Filled.PlayArrow
}
+
TimerState.Ticking -> {
Icons.Filled.Pause
}
+
TimerState.Finished -> {
Icons.Filled.Replay
}
+
else -> {
Icons.Filled.PlayArrow
}
},
contentDescription = null,
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
},
onClick = {
onClickAction(state)
},
- color = MaterialTheme.colorScheme.primary
+ color = MaterialTheme.colorScheme.primary,
)
IconButton(onClick = onClickNext) {
@@ -82,7 +91,7 @@ fun BloomTimerControls(modifier: Modifier = Modifier, state: TimerState, onClick
modifier = Modifier.size(120.dp),
imageVector = Icons.Filled.SkipNext,
contentDescription = "Next Timer",
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTopAppBar.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTopAppBar.kt
index 4d9a727..dada451 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTopAppBar.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/BloomTopAppBar.kt
@@ -31,9 +31,9 @@ fun BloomTopAppBar(
actions: (@Composable () -> Unit)? = null,
navigationIcon: (@Composable () -> Unit)? = null,
colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(
- containerColor = MaterialTheme.colorScheme.background
+ containerColor = MaterialTheme.colorScheme.background,
),
- title: @Composable () -> Unit = {}
+ title: @Composable () -> Unit = {},
) {
TopAppBar(
modifier = modifier,
@@ -50,6 +50,6 @@ fun BloomTopAppBar(
}
}
},
- colors = colors
+ colors = colors,
)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/TaskCard.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/TaskCard.kt
index d98dec0..92dfd25 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/TaskCard.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/TaskCard.kt
@@ -32,7 +32,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Card
-import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -55,20 +54,32 @@ import com.joelkanyi.focusbloom.core.utils.calculateEndTime
import com.joelkanyi.focusbloom.core.utils.durationInMinutes
import com.joelkanyi.focusbloom.core.utils.prettyFormat
import com.joelkanyi.focusbloom.core.utils.prettyTimeDifference
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.ic_complete
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
-@OptIn(ExperimentalMaterial3Api::class, ExperimentalResourceApi::class)
+@OptIn(ExperimentalResourceApi::class)
@Composable
-fun TaskCard(task: Task, focusSessions: Int, sessionTime: Int, shortBreakTime: Int, longBreakTime: Int, hourFormat: Int, onClick: (task: Task) -> Unit, onShowTaskOption: (task: Task) -> Unit, type: String) {
+fun TaskCard(
+ task: Task,
+ focusSessions: Int,
+ sessionTime: Int,
+ shortBreakTime: Int,
+ longBreakTime: Int,
+ hourFormat: Int,
+ onClick: (task: Task) -> Unit,
+ onShowTaskOption: (task: Task) -> Unit,
+ type: String,
+) {
val end by remember {
mutableStateOf(
task.start.calculateEndTime(
focusSessions = focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
- )
+ longBreakTime = longBreakTime,
+ ),
)
}
Card(
@@ -76,38 +87,38 @@ fun TaskCard(task: Task, focusSessions: Int, sessionTime: Int, shortBreakTime: I
.fillMaxWidth(),
onClick = {
onClick(task)
- }
+ },
) {
Column(
modifier = Modifier
.padding(12.dp),
- verticalArrangement = Arrangement.spacedBy(8.dp)
+ verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Row(
modifier = Modifier
.fillMaxWidth(),
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Column(
modifier = Modifier
.fillMaxWidth(.85f),
- verticalArrangement = Arrangement.spacedBy(4.dp)
+ verticalArrangement = Arrangement.spacedBy(4.dp),
) {
Text(
text = task.name,
style = MaterialTheme.typography.titleSmall.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 16.sp
+ fontSize = 16.sp,
),
maxLines = 2,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
)
if (task.description != null) {
Text(
text = task.description,
style = MaterialTheme.typography.bodyMedium,
maxLines = 3,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
)
}
}
@@ -117,7 +128,7 @@ fun TaskCard(task: Task, focusSessions: Int, sessionTime: Int, shortBreakTime: I
onShowTaskOption(task)
},
imageVector = Icons.Filled.MoreVert,
- contentDescription = "Task Options"
+ contentDescription = "Task Options",
)
}
@@ -125,7 +136,7 @@ fun TaskCard(task: Task, focusSessions: Int, sessionTime: Int, shortBreakTime: I
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
Column {
Text(
@@ -133,13 +144,13 @@ fun TaskCard(task: Task, focusSessions: Int, sessionTime: Int, shortBreakTime: I
withStyle(
style = SpanStyle(
fontWeight = FontWeight.SemiBold,
- fontSize = 18.sp
- )
+ fontSize = 18.sp,
+ ),
) {
append("${task.currentCycle}")
}
append("/${task.focusSessions}")
- }
+ },
)
Spacer(modifier = Modifier.height(4.dp))
Text(
@@ -148,27 +159,27 @@ fun TaskCard(task: Task, focusSessions: Int, sessionTime: Int, shortBreakTime: I
focusSessions = focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
} minutes",
- style = MaterialTheme.typography.bodySmall
+ style = MaterialTheme.typography.bodySmall,
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = prettyTimeDifference(
start = task.start,
end = end,
- timeFormat = hourFormat
+ timeFormat = hourFormat,
),
- style = MaterialTheme.typography.bodySmall
+ style = MaterialTheme.typography.bodySmall,
)
if (type == "overdue") {
Spacer(modifier = Modifier.height(4.dp))
Text(
text = task.date.date.prettyFormat(),
style = MaterialTheme.typography.bodySmall.copy(
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
}
}
@@ -176,8 +187,9 @@ fun TaskCard(task: Task, focusSessions: Int, sessionTime: Int, shortBreakTime: I
Image(
modifier = Modifier
.size(48.dp),
- painter = painterResource("ic_complete.xml"),
- contentDescription = "Task Options"
+ painter = painterResource(
+ Res.drawable.ic_complete),
+ contentDescription = "Task Options",
)
} else {
Box(
@@ -185,12 +197,12 @@ fun TaskCard(task: Task, focusSessions: Int, sessionTime: Int, shortBreakTime: I
.size(48.dp)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.primary),
- contentAlignment = Alignment.Center
+ contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
contentDescription = "Task Options",
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/TaskProgress.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/TaskProgress.kt
index 56b812a..c3354e1 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/TaskProgress.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/component/TaskProgress.kt
@@ -43,7 +43,16 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
-fun TaskProgress(content: String? = null, percentage: Float, radius: Dp = 20.dp, mainColor: Color, counterColor: Color, strokeWidth: Dp = 8.dp, animationDuration: Int = 800, animDelay: Int = 0) {
+fun TaskProgress(
+ content: String? = null,
+ percentage: Float,
+ radius: Dp = 20.dp,
+ mainColor: Color,
+ counterColor: Color,
+ strokeWidth: Dp = 8.dp,
+ animationDuration: Int = 800,
+ animDelay: Int = 0,
+) {
var animationPlayed by remember {
mutableStateOf(false)
}
@@ -52,9 +61,9 @@ fun TaskProgress(content: String? = null, percentage: Float, radius: Dp = 20.dp,
targetValue = if (animationPlayed) percentage else 0f,
animationSpec = tween(
durationMillis = animationDuration,
- delayMillis = animDelay
+ delayMillis = animDelay,
),
- label = ""
+ label = "",
)
LaunchedEffect(key1 = true) {
@@ -62,18 +71,18 @@ fun TaskProgress(content: String? = null, percentage: Float, radius: Dp = 20.dp,
}
Box(
- contentAlignment = Alignment.Center
+ contentAlignment = Alignment.Center,
) {
Canvas(
modifier = Modifier
- .size(radius * 5f)
+ .size(radius * 5f),
) {
drawArc(
color = Color.LightGray,
startAngle = 0f,
sweepAngle = 360f,
useCenter = false,
- style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round)
+ style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round),
)
drawArc(
@@ -81,7 +90,7 @@ fun TaskProgress(content: String? = null, percentage: Float, radius: Dp = 20.dp,
startAngle = -360f,
sweepAngle = (360 * (currentPercentage.value * 0.01)).toFloat(),
useCenter = false,
- style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round)
+ style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round),
)
}
@@ -89,25 +98,25 @@ fun TaskProgress(content: String? = null, percentage: Float, radius: Dp = 20.dp,
contentAlignment = Alignment.Center,
modifier = Modifier
.size(110.dp)
- .clip(CircleShape)
+ .clip(CircleShape),
) {
Column(
modifier = Modifier.padding(8.dp),
verticalArrangement = Arrangement.Center,
- horizontalAlignment = Alignment.CenterHorizontally
+ horizontalAlignment = Alignment.CenterHorizontally,
) {
if (content?.isEmpty()?.not() == true) {
Text(
text = content,
fontSize = 22.sp,
- fontWeight = FontWeight.Bold
+ fontWeight = FontWeight.Bold,
)
} else {
Text(
text = "${(currentPercentage.value).toInt()}%",
fontSize = 22.sp,
fontWeight = FontWeight.Bold,
- color = counterColor
+ color = counterColor,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Shapes.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Shapes.kt
index d79b5ca..368a953 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Shapes.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Shapes.kt
@@ -22,5 +22,5 @@ import androidx.compose.ui.unit.dp
internal val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(8.dp),
- large = RoundedCornerShape(12.dp)
+ large = RoundedCornerShape(12.dp),
)
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Theme.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Theme.kt
index 1a0bd4e..1d4fce6 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Theme.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Theme.kt
@@ -38,7 +38,7 @@ private val LightColors = lightColorScheme(
secondaryContainer = PrimaryColor,
onSecondaryContainer = Color.White,
error = ErrorColor,
- onError = OnErrorColor
+ onError = OnErrorColor,
)
private val DarkColors = darkColorScheme(
@@ -57,17 +57,20 @@ private val DarkColors = darkColorScheme(
secondaryContainer = PrimaryColor,
onSecondaryContainer = Color.White,
error = ErrorColor,
- onError = OnErrorColor
+ onError = OnErrorColor,
)
@Composable
-internal fun FocusBloomTheme(useDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
+internal fun FocusBloomTheme(
+ useDarkTheme: Boolean = isSystemInDarkTheme(),
+ content: @Composable () -> Unit,
+) {
val autoColors = if (useDarkTheme) DarkColors else LightColors
MaterialTheme(
colorScheme = autoColors,
typography = getTypography(),
shapes = Shapes,
- content = content
+ content = content,
)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Type.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Type.kt
index d452888..d4447b9 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Type.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/theme/Type.kt
@@ -22,82 +22,82 @@ 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 com.joelkanyi.focusbloom.platform.font
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.montserrat_black
+import focusbloom.shared.generated.resources.montserrat_bold
+import focusbloom.shared.generated.resources.montserrat_extrabold
+import focusbloom.shared.generated.resources.montserrat_extralight
+import focusbloom.shared.generated.resources.montserrat_light
+import focusbloom.shared.generated.resources.montserrat_medium
+import focusbloom.shared.generated.resources.montserrat_regular
+import focusbloom.shared.generated.resources.montserrat_semi_bold
+import focusbloom.shared.generated.resources.montserrat_thin
+import org.jetbrains.compose.resources.Font
@Composable
-internal fun getTypography(): Typography {
+fun montserrat(): FontFamily {
val montserratRegular =
- font(
- "Montserrat",
- "montserrat_regular",
- FontWeight.Normal,
- FontStyle.Normal
+ Font(
+ resource = Res.font.montserrat_regular,
+ weight = FontWeight.Normal,
+ style = FontStyle.Normal,
)
val montserratBold =
- font(
- "Montserrat",
- "montserrat_bold",
+ Font(
+ resource = Res.font.montserrat_bold,
FontWeight.Bold,
- FontStyle.Normal
+ FontStyle.Normal,
)
val montserratLight =
- font(
- "Montserrat",
- "montserrat_light",
+ Font(
+ resource = Res.font.montserrat_light,
FontWeight.Light,
- FontStyle.Normal
+ FontStyle.Normal,
)
val montserratMedium =
- font(
- "Montserrat",
- "montserrat_medium",
+ Font(
+ resource = Res.font.montserrat_medium,
FontWeight.Medium,
- FontStyle.Normal
+ FontStyle.Normal,
)
val montserratSemiBold =
- font(
- "Montserrat",
- "montserrat_semi_bold",
+ Font(
+ resource = Res.font.montserrat_semi_bold,
FontWeight.SemiBold,
- FontStyle.Normal
+ FontStyle.Normal,
)
val montserratThin =
- font(
- "Montserrat",
- "montserrat_thin",
+ Font(
+ resource = Res.font.montserrat_thin,
FontWeight.Thin,
- FontStyle.Normal
+ FontStyle.Normal,
)
val montserratExtraBold =
- font(
- "Montserrat",
- "montserrat_extrabold",
+ Font(
+ resource = Res.font.montserrat_extrabold,
FontWeight.ExtraBold,
- FontStyle.Normal
+ FontStyle.Normal,
)
val montserratExtraLight =
- font(
- "Montserrat",
- "montserrat_extralight",
+ Font(
+ resource = Res.font.montserrat_extralight,
FontWeight.ExtraLight,
- FontStyle.Normal
+ FontStyle.Normal,
)
- val montserratBlack = font(
- "Montserrat",
- "montserrat_black",
+ val montserratBlack = Font(
+ resource = Res.font.montserrat_black,
FontWeight.Black,
- FontStyle.Normal
+ FontStyle.Normal,
)
- @Composable
- fun montserrat() = FontFamily(
+ return FontFamily(
montserratThin,
montserratExtraLight,
montserratLight,
@@ -106,107 +106,88 @@ internal fun getTypography(): Typography {
montserratSemiBold,
montserratBold,
montserratExtraBold,
- montserratBlack
+ montserratBlack,
)
+}
+@Composable
+internal fun getTypography(): Typography {
+ val montserrat = montserrat()
return Typography(
displayLarge = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 50.sp
- // lineHeight = 64.sp,
- // letterSpacing = (-0.25).sp,
+ fontSize = 50.sp,
),
displayMedium = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 40.sp
- // lineHeight = 52.sp,
+ fontSize = 40.sp,
),
displaySmall = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 30.sp
- // lineHeight = 44.sp,
+ fontSize = 30.sp,
),
headlineLarge = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 28.sp
- // lineHeight = 40.sp,
+ fontSize = 28.sp,
),
headlineMedium = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 24.sp
- // lineHeight = 36.sp,
+ fontSize = 24.sp,
),
headlineSmall = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 20.sp
- // lineHeight = 32.sp,
+ fontSize = 20.sp,
),
titleLarge = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W700,
- fontSize = 18.sp
- // lineHeight = 28.sp,
+ fontSize = 18.sp,
),
titleMedium = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W700,
- fontSize = 14.sp
- // lineHeight = 24.sp,
- // letterSpacing = 0.1.sp,
+ fontSize = 14.sp,
),
titleSmall = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W500,
- fontSize = 12.sp
- // lineHeight = 20.sp,
- // letterSpacing = 0.1.sp,
+ fontSize = 12.sp,
),
bodyLarge = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 14.sp
- // lineHeight = 24.sp,
- // letterSpacing = 0.5.sp,
+ fontSize = 14.sp,
),
bodyMedium = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 12.sp
- // lineHeight = 20.sp,
- // letterSpacing = 0.25.sp,
+ fontSize = 12.sp,
),
bodySmall = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 11.sp
- // lineHeight = 16.sp,
- // letterSpacing = 0.4.sp,
+ fontSize = 11.sp,
),
labelLarge = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 13.sp
- // lineHeight = 20.sp,
- // letterSpacing = 0.1.sp,
+ fontSize = 13.sp,
),
labelMedium = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W400,
- fontSize = 11.sp
- // lineHeight = 16.sp,
- // letterSpacing = 0.5.sp,
+ fontSize = 11.sp,
),
labelSmall = TextStyle(
- fontFamily = montserrat(),
+ fontFamily = montserrat,
fontWeight = FontWeight.W500,
- fontSize = 9.sp
- // lineHeight = 16.sp,
- )
+ fontSize = 9.sp,
+ ),
)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/utils/FilledIcon.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/utils/FilledIcon.kt
index 11cb1e3..2d11724 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/utils/FilledIcon.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/presentation/utils/FilledIcon.kt
@@ -17,16 +17,22 @@ package com.joelkanyi.focusbloom.core.presentation.utils
import androidx.compose.runtime.Composable
import cafe.adriel.voyager.navigator.tab.Tab
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.add_filled
+import focusbloom.shared.generated.resources.calendar_filled
+import focusbloom.shared.generated.resources.home_filled
+import focusbloom.shared.generated.resources.settings_filled
+import focusbloom.shared.generated.resources.statistics_filled
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
@Composable
@OptIn(ExperimentalResourceApi::class)
fun FilledIcon(item: Tab) = when (item.options.index) {
- (0u).toUShort() -> painterResource("home_filled.xml")
- (1u).toUShort() -> painterResource("calendar_filled.xml")
- (2u).toUShort() -> painterResource("statistics_filled.xml")
- (3u).toUShort() -> painterResource("settings_filled.xml")
- (4u).toUShort() -> painterResource("add_filled.xml")
- else -> painterResource("home_filled.xml")
+ (0u).toUShort() -> painterResource(Res.drawable.home_filled)
+ (1u).toUShort() -> painterResource(Res.drawable.calendar_filled)
+ (2u).toUShort() -> painterResource(Res.drawable.statistics_filled)
+ (3u).toUShort() -> painterResource(Res.drawable.settings_filled)
+ (4u).toUShort() -> painterResource(Res.drawable.add_filled)
+ else -> painterResource(Res.drawable.home_filled)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/utils/Utils.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/utils/Utils.kt
index d50a63f..0ebd70b 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/utils/Utils.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/core/utils/Utils.kt
@@ -16,9 +16,6 @@
package com.joelkanyi.focusbloom.core.utils
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.ProvidableCompositionLocal
-import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ParentDataModifier
import androidx.compose.ui.platform.LocalDensity
@@ -26,10 +23,11 @@ import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
-import cafe.adriel.voyager.navigator.Navigator
import com.joelkanyi.focusbloom.core.domain.model.SessionType
import com.joelkanyi.focusbloom.core.domain.model.Task
import com.joelkanyi.focusbloom.core.domain.model.taskTypes
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.other
import kotlinx.datetime.Clock
import kotlinx.datetime.DateTimeUnit
import kotlinx.datetime.Instant
@@ -42,6 +40,7 @@ import kotlinx.datetime.minus
import kotlinx.datetime.plus
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
+import org.jetbrains.compose.resources.DrawableResource
import kotlin.jvm.JvmInline
@Composable
@@ -51,7 +50,10 @@ fun differenceBetweenMinutes(minTime: LocalTime, maxTime: LocalTime): Int {
return (maxTime.hour - minTime.hour) * 60
}
-fun differenceBetweenDays(minDate: LocalDate = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date, maxDate: LocalDate = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date): Int {
+fun differenceBetweenDays(
+ minDate: LocalDate = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date,
+ maxDate: LocalDate = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date,
+): Int {
Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).time
return (maxDate.dayOfMonth - minDate.dayOfMonth)
}
@@ -64,14 +66,6 @@ fun LocalDateTime.plusDays(days: Int): LocalDateTime {
return this.date.plus(days, DateTimeUnit.DAY).atTime(this.time)
}
-fun LocalDate.minusDays(days: Int): LocalDate {
- return this.minus(days, DateTimeUnit.DAY)
-}
-
-fun LocalDateTime.minusDays(days: Int): LocalDateTime {
- return this.date.minus(days, DateTimeUnit.DAY).atTime(this.time)
-}
-
fun LocalTime.plusHours(hours: Int): LocalTime {
val addedHours = this.hour + hours
return LocalTime(addedHours, this.minute)
@@ -107,7 +101,7 @@ data class PositionedTask(
val end: LocalTime,
val col: Int = 0,
val colSpan: Int = 1,
- val colTotal: Int = 1
+ val colTotal: Int = 1,
)
sealed class ScheduleSize {
@@ -118,21 +112,26 @@ sealed class ScheduleSize {
}
class TaskDataModifier(
- private val positionedTask: PositionedTask
+ private val positionedTask: PositionedTask,
) : ParentDataModifier {
override fun Density.modifyParentData(parentData: Any?) = positionedTask
}
fun Modifier.taskData(positionedTask: PositionedTask) = this.then(TaskDataModifier(positionedTask))
-fun splitTasks(tasks: List, sessionTime: Int, shortBreakTime: Int, longBreakTime: Int): List {
+fun splitTasks(
+ tasks: List,
+ sessionTime: Int,
+ shortBreakTime: Int,
+ longBreakTime: Int,
+): List {
return tasks
.map { task ->
val end = task.start.calculateEndTime(
focusSessions = task.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
val startDate = task.start.date
val endDate = end.date
@@ -143,8 +142,8 @@ fun splitTasks(tasks: List, sessionTime: Int, shortBreakTime: Int, longBre
SplitType.None,
task.start.date,
task.start.time,
- end.time
- )
+ end.time,
+ ),
)
} else {
val days = differenceBetweenDays(startDate, endDate)
@@ -164,7 +163,7 @@ fun splitTasks(tasks: List, sessionTime: Int, shortBreakTime: Int, longBre
end.time
} else {
max()
- }
+ },
)
}
splitTasks
@@ -240,7 +239,13 @@ fun Long?.selectedDateMillisToLocalDateTime(): LocalDateTime {
.toLocalDateTime(TimeZone.currentSystemDefault())
}
-fun calculateFromFocusSessions(focusSessions: Int, sessionTime: Int = 25, shortBreakTime: Int = 5, longBreakTime: Int = 15, currentLocalDateTime: LocalDateTime): LocalTime {
+fun calculateFromFocusSessions(
+ focusSessions: Int,
+ sessionTime: Int = 25,
+ shortBreakTime: Int = 5,
+ longBreakTime: Int = 15,
+ currentLocalDateTime: LocalDateTime,
+): LocalTime {
return if (focusSessions <= 0) {
currentLocalDateTime.time
} else {
@@ -268,7 +273,7 @@ fun LocalDateTime.dateTimeToString(): String {
fun toLocalDateTime(hour: Int, minute: Int, date: LocalDate): LocalDateTime {
return LocalDateTime(
date,
- LocalTime(hour, minute)
+ LocalTime(hour, minute),
)
}
@@ -310,8 +315,8 @@ fun String.taskColor(): Long {
return taskTypes.find { it.name == this }?.color ?: 0xFFAFBBF2
}
-fun String.taskIcon(): String {
- return taskTypes.find { it.name == this }?.icon ?: "other.xml"
+fun String.taskIcon(): DrawableResource {
+ return taskTypes.find { it.name == this }?.icon ?: Res.drawable.other
}
fun getThisWeek(): List {
@@ -371,13 +376,13 @@ fun getLast52Weeks(): List>> {
weeks += "${
week.first().month.name.lowercase().capitalize(Locale.current).substring(
0,
- 3
+ 3,
)
} ${week.first().dayOfMonth} ${if (week.first().year != thisYear) week.first().year else ""}" +
" - ${
week.last().month.name.lowercase().capitalize(Locale.current).substring(
0,
- 3
+ 3,
)
} ${week.last().dayOfMonth} ${if (week.last().year != thisYear) week.last().year else ""}" to week
}
@@ -478,12 +483,17 @@ fun Int.timeFormat(): String {
}
}
-fun Task.durationInMinutes(focusSessions: Int, sessionTime: Int, shortBreakTime: Int, longBreakTime: Int): Int {
+fun Task.durationInMinutes(
+ focusSessions: Int,
+ sessionTime: Int,
+ shortBreakTime: Int,
+ longBreakTime: Int,
+): Int {
val end = start.calculateEndTime(
focusSessions = focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
return (end.time.toSecondOfDay() - start.time.toSecondOfDay()) / 60
}
@@ -568,20 +578,16 @@ fun String?.sessionType(): SessionType {
}
}
-val LocalAppNavigator: ProvidableCompositionLocal = staticCompositionLocalOf { null }
-
-@Composable
-fun ProvideAppNavigator(navigator: Navigator, content: @Composable () -> Unit) {
- CompositionLocalProvider(LocalAppNavigator provides navigator) {
- content()
- }
-}
-
fun String.pickFirstName(): String {
return this.split(" ").first()
}
-fun LocalDateTime.calculateEndTime(focusSessions: Int, sessionTime: Int, shortBreakTime: Int, longBreakTime: Int): LocalDateTime {
+fun LocalDateTime.calculateEndTime(
+ focusSessions: Int,
+ sessionTime: Int,
+ shortBreakTime: Int,
+ longBreakTime: Int,
+): LocalDateTime {
val totalSessionTimeMinutes = sessionTime * focusSessions
val totalShortBreakTimeMinutes = shortBreakTime * (focusSessions - 1)
val totalLongBreakTimeMinutes = longBreakTime * (focusSessions / 4)
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/di/CommonModule.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/di/CommonModule.kt
index 271f5dc..ee51fce 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/di/CommonModule.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/di/CommonModule.kt
@@ -38,12 +38,10 @@ import com.joelkanyi.focusbloom.feature.statistics.StatisticsScreenModel
import com.joelkanyi.focusbloom.feature.taskprogress.TaskProgressScreenModel
import com.joelkanyi.focusbloom.main.MainViewModel
import com.joelkanyi.focusbloom.platform.DatabaseDriverFactory
-import com.russhwolf.settings.ExperimentalSettingsApi
import database.TaskEntity
import org.koin.core.module.Module
import org.koin.dsl.module
-@OptIn(ExperimentalSettingsApi::class)
fun commonModule() = module {
/**
* Database
@@ -59,8 +57,8 @@ fun commonModule() = module {
consumedShortBreakTimeAdapter = consumedShortBreakTimeAdapter,
currentAdapter = currentAdapter,
currentCycleAdapter = currentCycleAdapter,
- focusSessionsAdapter = focusSessionsAdapter
- )
+ focusSessionsAdapter = focusSessionsAdapter,
+ ),
)
}
/**
@@ -75,13 +73,13 @@ fun commonModule() = module {
*/
single {
SettingsRepositoryImpl(
- preferenceManager = get()
+ preferenceManager = get(),
)
}
single {
TasksRepositoryImpl(
- bloomDatabase = get()
+ bloomDatabase = get(),
)
}
@@ -90,31 +88,31 @@ fun commonModule() = module {
*/
single {
SettingsScreenModel(
- settingsRepository = get()
+ settingsRepository = get(),
)
}
single {
AddTaskScreenModel(
settingsRepository = get(),
- tasksRepository = get()
+ tasksRepository = get(),
)
}
single {
HomeScreenModel(
tasksRepository = get(),
- settingsRepository = get()
+ settingsRepository = get(),
)
}
single {
StatisticsScreenModel(
tasksRepository = get(),
- settingsRepository = get()
+ settingsRepository = get(),
)
}
single {
CalendarScreenModel(
tasksRepository = get(),
- settingsRepository = get()
+ settingsRepository = get(),
)
}
@@ -122,19 +120,19 @@ fun commonModule() = module {
TaskProgressScreenModel(
settingsRepository = get(),
tasksRepository = get(),
- notificationManager = get()
+ notificationManager = get(),
)
}
single {
MainViewModel(
- settingsRepository = get()
+ settingsRepository = get(),
)
}
single {
OnboadingViewModel(
- settingsRepository = get()
+ settingsRepository = get(),
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/di/KoinInit.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/di/KoinInit.kt
index 5a484ab..ccdbe13 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/di/KoinInit.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/di/KoinInit.kt
@@ -25,8 +25,8 @@ class KoinInit {
modules(
listOf(
platformModule(),
- commonModule()
- )
+ commonModule(),
+ ),
)
appDeclaration()
}.koin
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/addtask/AddTaskScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/addtask/AddTaskScreen.kt
index b65c6c7..6226bb7 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/addtask/AddTaskScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/addtask/AddTaskScreen.kt
@@ -54,12 +54,9 @@ import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically
-import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathEffect
@@ -92,26 +89,29 @@ import com.joelkanyi.focusbloom.core.utils.selectedDateMillisToLocalDateTime
import com.joelkanyi.focusbloom.core.utils.toLocalDateTime
import com.joelkanyi.focusbloom.core.utils.today
import com.joelkanyi.focusbloom.platform.StatusBarColors
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.end_time
+import focusbloom.shared.generated.resources.ic_complete
+import focusbloom.shared.generated.resources.start_time
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.withContext
import kotlinx.datetime.Clock
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.LocalTime
+import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
-import org.koin.compose.rememberKoinInject
+import org.koin.compose.koinInject
-@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
+@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AddTaskScreen(
- taskId: Int? = null
+ taskId: Int? = null,
+ screenModel: AddTaskScreenModel = koinInject(),
) {
- val screenModel: AddTaskScreenModel = rememberKoinInject()
-
StatusBarColors(
statusBarColor = MaterialTheme.colorScheme.background,
- navBarColor = MaterialTheme.colorScheme.background
+ navBarColor = MaterialTheme.colorScheme.background,
)
val snackbarHostState = remember { SnackbarHostState() }
val keyboardController = LocalSoftwareKeyboardController.current
@@ -134,28 +134,11 @@ fun AddTaskScreen(
val startTimeState = rememberTimePickerState(
initialHour = today().hour,
initialMinute = today().minute,
- is24Hour = hourFormat == 24
+ is24Hour = hourFormat == 24,
)
val datePickerState = rememberDatePickerState(
- initialSelectedDateMillis = Clock.System.now().toEpochMilliseconds()
+ initialSelectedDateMillis = Clock.System.now().toEpochMilliseconds(),
)
- val calculatedFocusTime by remember {
- mutableStateOf(
- calculateFromFocusSessions(
- focusSessions = focusSessions,
- sessionTime = sessionTime,
- shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime,
- currentLocalDateTime = LocalDateTime(
- year = taskDate.year,
- month = taskDate.month,
- dayOfMonth = taskDate.dayOfMonth,
- hour = startTime.hour,
- minute = startTime.minute
- )
- )
- )
- }
LaunchedEffect(key1 = true) {
screenModel.getTask(taskId)
@@ -170,16 +153,16 @@ fun AddTaskScreen(
month = taskDate.month,
dayOfMonth = taskDate.dayOfMonth,
hour = startTime.hour,
- minute = startTime.minute
- )
- )
+ minute = startTime.minute,
+ ),
+ ),
)
withContext(Dispatchers.Main.immediate) {
screenModel.eventsFlow.collect { event ->
when (event) {
is UiEvents.ShowSnackbar -> {
snackbarHostState.showSnackbar(
- message = event.message
+ message = event.message,
)
}
@@ -213,12 +196,12 @@ fun AddTaskScreen(
month = taskDate.month,
dayOfMonth = taskDate.dayOfMonth,
hour = it.hour,
- minute = it.minute
- )
- )
+ minute = it.minute,
+ ),
+ ),
)
screenModel.setShowStartTimeInputDialog(false)
- }
+ },
)
}
@@ -231,14 +214,13 @@ fun AddTaskScreen(
onConfirmDate = {
screenModel.setTaskDate(it)
screenModel.setShowTaskDatePickerDialog(false)
- }
+ },
)
}
AddTaskScreenContent(
snackbarHostState = snackbarHostState,
hourFormat = hourFormat,
- calculatedFocusTime = calculatedFocusTime,
taskOptions = taskTypes,
selectedTaskType = selectedTaskType,
taskName = taskName,
@@ -279,7 +261,7 @@ fun AddTaskScreen(
start = toLocalDateTime(
date = taskDate.date,
hour = startTime.hour,
- minute = startTime.minute
+ minute = startTime.minute,
),
color = selectedTaskType.color,
current = "Focus",
@@ -292,8 +274,8 @@ fun AddTaskScreen(
consumedLongBreakTime = 0L,
inProgressTask = false,
currentCycle = 0,
- active = false
- )
+ active = false,
+ ),
)
} else {
screenModel.addTask(
@@ -303,7 +285,7 @@ fun AddTaskScreen(
start = toLocalDateTime(
date = taskDate.date,
hour = startTime.hour,
- minute = startTime.minute
+ minute = startTime.minute,
),
color = selectedTaskType.color,
current = "Focus",
@@ -316,11 +298,11 @@ fun AddTaskScreen(
consumedLongBreakTime = 0L,
inProgressTask = false,
currentCycle = 0,
- active = false
- )
+ active = false,
+ ),
)
}
- }
+ },
)
}
@@ -328,7 +310,6 @@ fun AddTaskScreen(
@Composable
private fun AddTaskScreenContent(
snackbarHostState: SnackbarHostState,
- calculatedFocusTime: LocalTime,
hourFormat: Int,
taskOptions: List,
selectedTaskType: TaskType,
@@ -347,13 +328,13 @@ private fun AddTaskScreenContent(
// datePickerState: DatePickerState,
taskDate: LocalDateTime,
startTime: LocalTime,
- endTime: LocalTime
+ endTime: LocalTime,
) {
Scaffold(
snackbarHost = {
Box(
modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.TopCenter // Change to your desired position
+ contentAlignment = Alignment.TopCenter, // Change to your desired position
) {
SnackbarHost(
hostState = snackbarHostState,
@@ -366,33 +347,34 @@ private fun AddTaskScreenContent(
},
border = BorderStroke(2.dp, MaterialTheme.colorScheme.primary),
colors = CardDefaults.cardColors(
- containerColor = MaterialTheme.colorScheme.secondary
- )
+ containerColor = MaterialTheme.colorScheme.secondary,
+ ),
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
modifier = Modifier
.fillMaxWidth(.85f),
text = it.visuals.message,
style = MaterialTheme.typography.titleSmall.copy(
- color = MaterialTheme.colorScheme.onPrimary
- )
+ color = MaterialTheme.colorScheme.onPrimary,
+ ),
)
Image(
modifier = Modifier
.size(32.dp),
- painter = painterResource("ic_complete.xml"),
- contentDescription = "Task Options"
+ painter = painterResource(
+ Res.drawable.ic_complete),
+ contentDescription = "Task Options",
)
}
}
- }
+ },
)
}
},
@@ -400,12 +382,12 @@ private fun AddTaskScreenContent(
BloomTopAppBar {
Text(text = "Add Task")
}
- }
+ },
) { paddingValues ->
LazyColumn(
modifier = Modifier.padding(paddingValues),
contentPadding = PaddingValues(horizontal = 16.dp),
- verticalArrangement = Arrangement.spacedBy(8.dp)
+ verticalArrangement = Arrangement.spacedBy(8.dp),
) {
item {
BloomInputTextField(
@@ -416,8 +398,8 @@ private fun AddTaskScreenContent(
text = "Task Name",
style = MaterialTheme.typography.titleSmall.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
},
value = TextFieldState(text = taskName),
@@ -425,16 +407,16 @@ private fun AddTaskScreenContent(
placeholder = {
Text(
text = "Enter Task Name",
- style = MaterialTheme.typography.titleSmall
+ style = MaterialTheme.typography.titleSmall,
)
},
keyboardOptions = KeyboardOptions.Default.copy(
- capitalization = KeyboardCapitalization.Words
+ capitalization = KeyboardCapitalization.Words,
),
textStyle = MaterialTheme.typography.titleSmall.copy(
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
item {
@@ -446,8 +428,8 @@ private fun AddTaskScreenContent(
text = "Description",
style = MaterialTheme.typography.titleSmall.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
},
@@ -456,15 +438,15 @@ private fun AddTaskScreenContent(
placeholder = {
Text(
text = "Enter Description",
- style = MaterialTheme.typography.titleSmall
+ style = MaterialTheme.typography.titleSmall,
)
},
keyboardOptions = KeyboardOptions.Default.copy(
- capitalization = KeyboardCapitalization.Sentences
+ capitalization = KeyboardCapitalization.Sentences,
),
textStyle = MaterialTheme.typography.titleSmall.copy(
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
item {
@@ -476,17 +458,17 @@ private fun AddTaskScreenContent(
text = "Date",
style = MaterialTheme.typography.titleSmall.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
},
currentTextState = TextFieldState(
- text = taskDate.date.toString()
+ text = taskDate.date.toString(),
),
onClick = onClickPickDate,
textStyle = MaterialTheme.typography.titleSmall.copy(
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
@@ -497,8 +479,8 @@ private fun AddTaskScreenContent(
text = "Task Type",
style = MaterialTheme.typography.titleSmall.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
},
modifier = Modifier.fillMaxWidth(),
@@ -506,8 +488,8 @@ private fun AddTaskScreenContent(
selectedOption = TextFieldState(selectedTaskType.name),
onOptionSelected = onSelectedTaskTypeChange,
textStyle = MaterialTheme.typography.titleSmall.copy(
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
@@ -516,16 +498,16 @@ private fun AddTaskScreenContent(
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
TimeComponent(
time = startTime,
hourFormat = hourFormat,
title = "Start Time",
- icon = "start_time.xml",
+ icon = Res.drawable.start_time,
iconColor = MaterialTheme.colorScheme.primary,
iconSize = 24,
- onClick = onClickPickStartTime
+ onClick = onClickPickStartTime,
)
DashedDivider(
@@ -533,16 +515,16 @@ private fun AddTaskScreenContent(
thickness = 3.dp,
phase = 5f,
modifier = Modifier
- .width(180.dp)
+ .width(180.dp),
)
TimeComponent(
time = endTime,
hourFormat = hourFormat,
title = "End Time",
- icon = "end_time.xml",
+ icon = Res.drawable.end_time,
iconColor = SuccessColor,
- onClick = {}
+ onClick = {},
)
}
}
@@ -554,8 +536,8 @@ private fun AddTaskScreenContent(
style = MaterialTheme.typography.titleMedium.copy(
textAlign = TextAlign.Center,
fontWeight = FontWeight.SemiBold,
- fontSize = 18.sp
- )
+ fontSize = 18.sp,
+ ),
)
}
@@ -568,7 +550,7 @@ private fun AddTaskScreenContent(
onClickAdd = {
onIncrementFocusSessions()
},
- currentValue = focusSessions
+ currentValue = focusSessions,
)
}
@@ -584,7 +566,7 @@ private fun AddTaskScreenContent(
onClick = onClickAddTask,
content = {
Text(text = "Save")
- }
+ },
)
}
}
@@ -593,30 +575,38 @@ private fun AddTaskScreenContent(
@OptIn(ExperimentalResourceApi::class)
@Composable
-private fun TimeComponent(title: String, icon: String, iconColor: Color, iconSize: Int = 32, time: LocalTime, hourFormat: Int, onClick: () -> Unit) {
+private fun TimeComponent(
+ title: String,
+ icon: DrawableResource,
+ iconColor: Color,
+ iconSize: Int = 32,
+ time: LocalTime,
+ hourFormat: Int,
+ onClick: () -> Unit,
+) {
Column(
modifier = Modifier.clickable {
onClick()
},
- verticalArrangement = Arrangement.spacedBy(8.dp)
+ verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(
text = title,
style = MaterialTheme.typography.titleMedium.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
Row(
modifier = Modifier,
horizontalArrangement = Arrangement.spacedBy(8.dp),
- verticalAlignment = CenterVertically
+ verticalAlignment = CenterVertically,
) {
Text(
text = time.formattedTimeBasedOnTimeFormat(hourFormat),
style = MaterialTheme.typography.titleSmall.copy(
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
Icon(
@@ -624,7 +614,7 @@ private fun TimeComponent(title: String, icon: String, iconColor: Color, iconSiz
.size(iconSize.dp),
painter = painterResource(icon),
contentDescription = title,
- tint = iconColor
+ tint = iconColor,
)
}
}
@@ -632,7 +622,13 @@ private fun TimeComponent(title: String, icon: String, iconColor: Color, iconSiz
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun TimerInputDialog(title: String, modifier: Modifier = Modifier, onDismiss: () -> Unit, state: TimePickerState, onConfirmStartTime: (LocalTime) -> Unit) {
+fun TimerInputDialog(
+ title: String,
+ modifier: Modifier = Modifier,
+ onDismiss: () -> Unit,
+ state: TimePickerState,
+ onConfirmStartTime: (LocalTime) -> Unit,
+) {
AlertDialog(
properties = DialogProperties(usePlatformDefaultWidth = true),
modifier = modifier,
@@ -640,13 +636,13 @@ fun TimerInputDialog(title: String, modifier: Modifier = Modifier, onDismiss: ()
title = {
Text(
text = title,
- style = MaterialTheme.typography.titleMedium
+ style = MaterialTheme.typography.titleMedium,
)
},
text = {
TimeInput(
modifier = Modifier.fillMaxWidth(),
- state = state
+ state = state,
)
},
dismissButton = {
@@ -654,7 +650,7 @@ fun TimerInputDialog(title: String, modifier: Modifier = Modifier, onDismiss: ()
onClick = onDismiss,
content = {
Text(text = "Cancel")
- }
+ },
)
},
confirmButton = {
@@ -663,22 +659,26 @@ fun TimerInputDialog(title: String, modifier: Modifier = Modifier, onDismiss: ()
onConfirmStartTime(
LocalTime(
hour = state.hour,
- minute = state.minute
- )
+ minute = state.minute,
+ ),
)
onDismiss()
},
content = {
Text(text = "OK")
- }
+ },
)
- }
+ },
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun TaskDatePicker(datePickerState: DatePickerState, dismiss: () -> Unit, onConfirmDate: (LocalDateTime) -> Unit) {
+fun TaskDatePicker(
+ datePickerState: DatePickerState,
+ dismiss: () -> Unit,
+ onConfirmDate: (LocalDateTime) -> Unit,
+) {
DatePickerDialog(
onDismissRequest = { dismiss() },
dismissButton = {
@@ -691,20 +691,26 @@ fun TaskDatePicker(datePickerState: DatePickerState, dismiss: () -> Unit, onConf
onClick = {
onConfirmDate(datePickerState.selectedDateMillis.selectedDateMillisToLocalDateTime())
dismiss()
- }
+ },
) {
Text(text = "OK")
}
- }
+ },
) {
DatePicker(state = datePickerState)
}
}
@Composable
-fun DashedDivider(thickness: Dp, color: Color = MaterialTheme.colorScheme.onSurfaceVariant, phase: Float = 10f, intervals: FloatArray = floatArrayOf(10f, 10f), modifier: Modifier) {
+fun DashedDivider(
+ thickness: Dp,
+ color: Color = MaterialTheme.colorScheme.onSurfaceVariant,
+ phase: Float = 10f,
+ intervals: FloatArray = floatArrayOf(10f, 10f),
+ modifier: Modifier,
+) {
Canvas(
- modifier = modifier
+ modifier = modifier,
) {
val dividerHeight = thickness.toPx()
drawRoundRect(
@@ -713,9 +719,9 @@ fun DashedDivider(thickness: Dp, color: Color = MaterialTheme.colorScheme.onSurf
width = dividerHeight,
pathEffect = PathEffect.dashPathEffect(
intervals = intervals,
- phase = phase
- )
- )
+ phase = phase,
+ ),
+ ),
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/addtask/AddTaskScreenModel.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/addtask/AddTaskScreenModel.kt
index 3be92d1..cfc2a4c 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/addtask/AddTaskScreenModel.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/addtask/AddTaskScreenModel.kt
@@ -18,7 +18,7 @@ package com.joelkanyi.focusbloom.feature.addtask
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import cafe.adriel.voyager.core.model.ScreenModel
-import cafe.adriel.voyager.core.model.coroutineScope
+import cafe.adriel.voyager.core.model.screenModelScope
import com.joelkanyi.focusbloom.core.domain.model.Task
import com.joelkanyi.focusbloom.core.domain.model.TaskType
import com.joelkanyi.focusbloom.core.domain.model.taskTypes
@@ -41,7 +41,7 @@ import kotlinx.datetime.LocalTime
class AddTaskScreenModel(
settingsRepository: SettingsRepository,
- private val tasksRepository: TasksRepository
+ private val tasksRepository: TasksRepository,
) : ScreenModel {
private val _eventsFlow = Channel(Channel.UNLIMITED)
val eventsFlow = _eventsFlow.receiveAsFlow()
@@ -51,30 +51,30 @@ class AddTaskScreenModel(
it
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val shortBreakTime = settingsRepository.getShortBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val longBreakTime = settingsRepository.getLongBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val hourFormat = settingsRepository.getHourFormat()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
private val _focusSessions = MutableStateFlow(1)
@@ -92,9 +92,9 @@ class AddTaskScreenModel(
month = taskDate.value.month,
dayOfMonth = taskDate.value.dayOfMonth,
hour = startTime.value.hour,
- minute = startTime.value.minute
- )
- )
+ minute = startTime.value.minute,
+ ),
+ ),
)
}
@@ -112,14 +112,14 @@ class AddTaskScreenModel(
month = taskDate.value.month,
dayOfMonth = taskDate.value.dayOfMonth,
hour = startTime.value.hour,
- minute = startTime.value.minute
- )
- )
+ minute = startTime.value.minute,
+ ),
+ ),
)
}
}
- fun setFocusSessions(sessions: Int) {
+ private fun setFocusSessions(sessions: Int) {
_focusSessions.value = sessions
}
@@ -172,7 +172,7 @@ class AddTaskScreenModel(
}
fun addTask(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.addTask(task)
reset()
setEndTime(today().time)
@@ -199,7 +199,7 @@ class AddTaskScreenModel(
private val _task = MutableStateFlow(null)
val task = _task.asStateFlow()
fun getTask(taskId: Int?) {
- coroutineScope.launch {
+ screenModelScope.launch {
if (taskId != null) {
tasksRepository.getTask(taskId).collectLatest {
_task.value = it
@@ -217,7 +217,7 @@ class AddTaskScreenModel(
setSelectedOption(
taskTypes.firstOrNull { taskType ->
taskType.name == it?.type
- } ?: taskTypes.last()
+ } ?: taskTypes.last(),
)
setFocusSessions(it?.focusSessions ?: 1)
setTaskDate(it?.date ?: today())
@@ -233,14 +233,14 @@ class AddTaskScreenModel(
month = it?.date?.month ?: today().month,
dayOfMonth = it?.date?.dayOfMonth ?: today().dayOfMonth,
hour = it?.start?.time?.hour ?: today().time.hour,
- minute = it?.start?.time?.minute ?: today().time.minute
- )
- )
+ minute = it?.start?.time?.minute ?: today().time.minute,
+ ),
+ ),
)
}
fun updateTask(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTask(task)
reset()
setEndTime(today().time)
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/calendar/CalendarScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/calendar/CalendarScreen.kt
index c6d0506..68b086e 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/calendar/CalendarScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/calendar/CalendarScreen.kt
@@ -107,6 +107,8 @@ import com.joelkanyi.focusbloom.core.utils.today
import com.joelkanyi.focusbloom.core.utils.truncatedTo
import com.joelkanyi.focusbloom.feature.home.component.TaskOptionsBottomSheet
import com.joelkanyi.focusbloom.platform.StatusBarColors
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.redo
import kotlinx.coroutines.launch
import kotlinx.datetime.Clock
import kotlinx.datetime.LocalDate
@@ -115,17 +117,17 @@ import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
-import org.koin.compose.rememberKoinInject
+import org.koin.compose.koinInject
import kotlin.math.roundToInt
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class, ExperimentalMaterial3Api::class)
@Composable
-fun CalendarScreen() {
- val screenModel: CalendarScreenModel = rememberKoinInject()
-
+fun CalendarScreen(
+ screenModel: CalendarScreenModel = koinInject(),
+) {
StatusBarColors(
statusBarColor = MaterialTheme.colorScheme.background,
- navBarColor = MaterialTheme.colorScheme.background
+ navBarColor = MaterialTheme.colorScheme.background,
)
val coroutineScope = rememberCoroutineScope()
val tasks = screenModel.tasks.collectAsState().value
@@ -144,7 +146,7 @@ fun CalendarScreen() {
LaunchedEffect(key1 = tasks, block = {
calendarPagerState.animateScrollToItem(
index = calendarLocalDates().indexOf(selectedDay),
- scrollOffset = 0
+ scrollOffset = 0,
)
})
BoxWithConstraints {
@@ -178,7 +180,7 @@ fun CalendarScreen() {
onClickEditTask = {
tabNavigator.current = BloomTab.AddTaskTab(taskId = it.id)
},
- task = selectedTask
+ task = selectedTask,
)
}
}
@@ -201,13 +203,13 @@ fun CalendarScreen() {
calendarPagerState.animateScrollToItem(
index = calendarLocalDates().indexOf(
Clock.System.now()
- .toLocalDateTime(TimeZone.currentSystemDefault()).date
+ .toLocalDateTime(TimeZone.currentSystemDefault()).date,
),
- scrollOffset = 0
+ scrollOffset = 0,
)
screenModel.setSelectedDay(
Clock.System.now()
- .toLocalDateTime(TimeZone.currentSystemDefault()).date
+ .toLocalDateTime(TimeZone.currentSystemDefault()).date,
)
}
},
@@ -217,7 +219,7 @@ fun CalendarScreen() {
onShowTaskOption = {
screenModel.selectTask(it)
screenModel.openBottomSheet(true)
- }
+ },
)
}
}
@@ -237,7 +239,7 @@ fun CalendarScreenContent(
selectedDay: LocalDate,
onClickThisWeek: () -> Unit,
onSelectDay: (LocalDate) -> Unit,
- onShowTaskOption: (task: Task) -> Unit
+ onShowTaskOption: (task: Task) -> Unit,
) {
Scaffold(
topBar = {
@@ -249,37 +251,37 @@ fun CalendarScreenContent(
actions = {
AnimatedVisibility(selectedDay.insideThisWeek().not()) {
TextButton(
- onClick = onClickThisWeek
+ onClick = onClickThisWeek,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(4.dp)
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
Icon(
modifier = Modifier.size(18.dp),
- painter = painterResource("redo.xml"),
- contentDescription = "Today"
+ painter = painterResource(Res.drawable.redo),
+ contentDescription = "Today",
)
Text(
text = "TODAY",
style = MaterialTheme.typography.labelLarge.copy(
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.primary,
- textDecoration = TextDecoration.Underline
- )
+ textDecoration = TextDecoration.Underline,
+ ),
)
}
}
}
- }
+ },
)
- }
+ },
) { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.padding(PaddingValues(horizontal = 16.dp)),
- verticalArrangement = Arrangement.spacedBy(12.dp)
+ verticalArrangement = Arrangement.spacedBy(12.dp),
) {
Text(
modifier = Modifier.fillMaxWidth(),
@@ -287,12 +289,12 @@ fun CalendarScreenContent(
style = MaterialTheme.typography.labelLarge.copy(
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
- textAlign = TextAlign.End
- )
+ textAlign = TextAlign.End,
+ ),
)
LazyRow(
state = calendarPagerState,
- horizontalArrangement = Arrangement.spacedBy(8.dp)
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
items(calendarLocalDates()) { date ->
Box(
@@ -301,27 +303,27 @@ fun CalendarScreenContent(
.clipToBounds()
.background(
color = if (date == selectedDay) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant,
- shape = RoundedCornerShape(4.dp)
+ shape = RoundedCornerShape(4.dp),
)
.clickable {
onSelectDay(date)
},
- contentAlignment = Alignment.Center
+ contentAlignment = Alignment.Center,
) {
Column {
Text(
text = date.dayOfWeek.name.substring(0, 3),
style = MaterialTheme.typography.labelMedium.copy(
- color = if (date == selectedDay) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface
+ color = if (date == selectedDay) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface,
),
- modifier = Modifier.align(Alignment.CenterHorizontally)
+ modifier = Modifier.align(Alignment.CenterHorizontally),
)
Text(
text = date.dayOfMonth.toString(),
style = MaterialTheme.typography.labelMedium.copy(
- color = if (date == selectedDay) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface
+ color = if (date == selectedDay) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface,
),
- modifier = Modifier.align(Alignment.CenterHorizontally)
+ modifier = Modifier.align(Alignment.CenterHorizontally),
)
}
}
@@ -338,7 +340,7 @@ fun CalendarScreenContent(
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
longBreakTime = longBreakTime,
- onShowTaskOption = onShowTaskOption
+ onShowTaskOption = onShowTaskOption,
)
} else {
Text(
@@ -351,7 +353,7 @@ fun CalendarScreenContent(
}",
style = MaterialTheme.typography.labelLarge,
textAlign = TextAlign.Center,
- modifier = Modifier.align(Alignment.Center)
+ modifier = Modifier.align(Alignment.Center),
)
}
}
@@ -361,7 +363,15 @@ fun CalendarScreenContent(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakTime: Int, positionedTask: PositionedTask, modifier: Modifier = Modifier, onShowTaskOption: (task: Task) -> Unit) {
+fun BasicTask(
+ hourFormat: Int,
+ sessionTime: Int,
+ shortBreakTime: Int,
+ longBreakTime: Int,
+ positionedTask: PositionedTask,
+ modifier: Modifier = Modifier,
+ onShowTaskOption: (task: Task) -> Unit,
+) {
val task = positionedTask.task
val end by remember {
mutableStateOf(
@@ -369,8 +379,8 @@ fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakT
focusSessions = task.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
- )
+ longBreakTime = longBreakTime,
+ ),
)
}
val topRadius =
@@ -383,7 +393,7 @@ fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakT
.padding(
top = 2.dp,
end = 2.dp,
- bottom = if (positionedTask.splitType == SplitType.End) 0.dp else 2.dp
+ bottom = if (positionedTask.splitType == SplitType.End) 0.dp else 2.dp,
)
.clipToBounds()
.padding(4.dp),
@@ -391,26 +401,26 @@ fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakT
topStart = topRadius,
topEnd = topRadius,
bottomEnd = bottomRadius,
- bottomStart = bottomRadius
+ bottomStart = bottomRadius,
),
colors = CardDefaults.cardColors(
- containerColor = Color(task.type.taskColor())
+ containerColor = Color(task.type.taskColor()),
),
onClick = {
onShowTaskOption(task)
- }
+ },
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
- verticalArrangement = Arrangement.spacedBy(4.dp)
+ verticalArrangement = Arrangement.spacedBy(4.dp),
) {
Row(
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
Text(
modifier = Modifier
@@ -418,11 +428,11 @@ fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakT
text = task.name,
style = MaterialTheme.typography.labelMedium.copy(
color = MaterialTheme.colorScheme.onPrimary,
- fontSize = 14.sp
+ fontSize = 14.sp,
),
fontWeight = FontWeight.Bold,
maxLines = 1,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
)
Icon(
@@ -433,7 +443,7 @@ fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakT
},
imageVector = Icons.Filled.MoreVert,
contentDescription = "Task Options",
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
}
if (task.description != null) {
@@ -441,10 +451,10 @@ fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakT
text = task.description,
style = MaterialTheme.typography.bodySmall.copy(
color = MaterialTheme.colorScheme.onPrimary,
- fontSize = 12.sp
+ fontSize = 12.sp,
),
maxLines = 1,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
)
}
@@ -452,7 +462,7 @@ fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakT
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = "${
@@ -460,30 +470,30 @@ fun BasicTask(hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakT
focusSessions = task.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
} minutes",
style = MaterialTheme.typography.displaySmall.copy(
color = MaterialTheme.colorScheme.onPrimary,
fontWeight = FontWeight.SemiBold,
- fontSize = 10.sp
- )
+ fontSize = 10.sp,
+ ),
)
Text(
modifier = Modifier.fillMaxWidth(),
text = prettyTimeDifference(
start = task.start,
end = end,
- timeFormat = hourFormat
+ timeFormat = hourFormat,
),
style = MaterialTheme.typography.bodySmall.copy(
color = MaterialTheme.colorScheme.onPrimary,
fontWeight = FontWeight.SemiBold,
- fontSize = 10.sp
+ fontSize = 10.sp,
),
maxLines = 1,
overflow = TextOverflow.Clip,
- textAlign = TextAlign.End
+ textAlign = TextAlign.End,
)
}
}
@@ -498,8 +508,8 @@ fun BasicSidebarLabel(hourFormat: Int, time: LocalTime, modifier: Modifier = Mod
.fillMaxHeight()
.padding(4.dp),
style = MaterialTheme.typography.labelMedium.copy(
- fontSize = 12.sp
- )
+ fontSize = 12.sp,
+ ),
)
}
@@ -513,9 +523,9 @@ fun ScheduleSidebar(
label: @Composable (hourFormat: Int, time: LocalTime) -> Unit = { _, time ->
BasicSidebarLabel(
hourFormat = hourFormat,
- time = time
+ time = time,
)
- }
+ },
) {
val numMinutes = differenceBetweenMinutes(minTime, maxTime) + 1
val numHours = numMinutes / 60
@@ -530,7 +540,7 @@ fun ScheduleSidebar(
Box(modifier = Modifier.height(hourHeight)) {
label(
hourFormat,
- startTime.plusHours(i)
+ startTime.plusHours(i),
)
}
}
@@ -548,7 +558,7 @@ fun Schedule(
verticalScrollState: ScrollState,
modifier: Modifier = Modifier,
taskContent: @Composable (
- positionedTask: PositionedTask
+ positionedTask: PositionedTask,
) -> Unit = { positionedTask ->
BasicTask(
hourFormat = hourFormat,
@@ -556,13 +566,13 @@ fun Schedule(
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
longBreakTime = longBreakTime,
- onShowTaskOption = onShowTaskOption
+ onShowTaskOption = onShowTaskOption,
)
},
timeLabel: @Composable (hourFormat: Int, time: LocalTime) -> Unit = { hrFormat, time ->
BasicSidebarLabel(
hourFormat = hrFormat,
- time = time
+ time = time,
)
},
minDate: LocalDate = tasks.minByOrNull(Task::start)?.start?.date ?: Clock.System.now()
@@ -574,13 +584,13 @@ fun Schedule(
focusSessions = it.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
}.maxOfOrNull { it.date } ?: today().date,
minTime: LocalTime = min(),
maxTime: LocalTime = max(),
daySize: ScheduleSize,
- hourSize: ScheduleSize
+ hourSize: ScheduleSize,
) {
val numDays = 0 + 1
val numMinutes = differenceBetweenMinutes(minTime, maxTime) + 1
@@ -645,7 +655,7 @@ fun Schedule(
is ScheduleSize.Adaptive -> with(LocalDensity.current) {
maxOf(
((constraints.maxWidth - sidebarWidth) / numDays).toDp(),
- daySize.minSize
+ daySize.minSize,
)
}
}
@@ -655,7 +665,7 @@ fun Schedule(
is ScheduleSize.Adaptive -> with(LocalDensity.current) {
maxOf(
((constraints.maxHeight) / numHours).toDp(),
- hourSize.minSize
+ hourSize.minSize,
)
}
}
@@ -663,7 +673,7 @@ fun Schedule(
Row(
modifier = Modifier
.weight(1f)
- .align(Alignment.Start)
+ .align(Alignment.Start),
) {
ScheduleSidebar(
hourFormat = hourFormat,
@@ -673,7 +683,7 @@ fun Schedule(
label = timeLabel,
modifier = Modifier
.verticalScroll(verticalScrollState)
- .onGloballyPositioned { sidebarWidth = it.size.width }
+ .onGloballyPositioned { sidebarWidth = it.size.width },
)
BasicSchedule(
hourFormat = hourFormat,
@@ -691,7 +701,7 @@ fun Schedule(
onShowTaskOption = onShowTaskOption,
modifier = Modifier
.weight(1f)
- .verticalScroll(verticalScrollState)
+ .verticalScroll(verticalScrollState),
)
}
}
@@ -714,7 +724,7 @@ fun BasicSchedule(
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
longBreakTime = longBreakTime,
- onShowTaskOption = onShowTaskOption
+ onShowTaskOption = onShowTaskOption,
)
},
minDate: LocalDate = tasks.minByOrNull(Task::start)?.start?.date ?: Clock.System.now()
@@ -724,13 +734,13 @@ fun BasicSchedule(
focusSessions = it.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
}.maxOfOrNull { it.date } ?: today().date,
minTime: LocalTime = min(),
maxTime: LocalTime = max(),
dayWidth: Dp,
- hourHeight: Dp
+ hourHeight: Dp,
) {
val numDays = differenceBetweenDays(minDate, maxDate) + 1
val numMinutes = differenceBetweenMinutes(minTime, maxTime) + 1
@@ -743,8 +753,8 @@ fun BasicSchedule(
tasks = tasks.sortedBy(Task::start),
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
- )
+ longBreakTime = longBreakTime,
+ ),
).filter { it.end > minTime && it.start < maxTime }
}
Layout(
@@ -763,10 +773,10 @@ fun BasicSchedule(
dividerColor,
start = Offset(0f, (it + 1) * hourHeight.toPx()),
end = Offset(size.width, (it + 1) * hourHeight.toPx()),
- strokeWidth = 1.dp.toPx()
+ strokeWidth = 1.dp.toPx(),
)
}
- }
+ },
) { measureables, constraints ->
val height = (hourHeight.toPx() * (numMinutes / 60f)).roundToInt()
val width = dayWidth.roundToPx() * numDays
@@ -782,8 +792,8 @@ fun BasicSchedule(
minWidth = taskWidth,
maxWidth = taskWidth,
minHeight = taskHeight,
- maxHeight = taskHeight
- )
+ maxHeight = taskHeight,
+ ),
)
Pair(placeable, splitTask)
}
@@ -792,7 +802,7 @@ fun BasicSchedule(
val taskOffsetMinutes = if (splitTask.start > minTime) {
differenceBetweenMinutes(
minTime,
- splitTask.start
+ splitTask.start,
)
} else {
0
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/calendar/CalendarScreenModel.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/calendar/CalendarScreenModel.kt
index 79ff600..67e1320 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/calendar/CalendarScreenModel.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/calendar/CalendarScreenModel.kt
@@ -16,7 +16,7 @@
package com.joelkanyi.focusbloom.feature.calendar
import cafe.adriel.voyager.core.model.ScreenModel
-import cafe.adriel.voyager.core.model.coroutineScope
+import cafe.adriel.voyager.core.model.screenModelScope
import com.joelkanyi.focusbloom.core.domain.model.Task
import com.joelkanyi.focusbloom.core.domain.repository.settings.SettingsRepository
import com.joelkanyi.focusbloom.core.domain.repository.tasks.TasksRepository
@@ -33,19 +33,19 @@ import kotlinx.datetime.toLocalDateTime
class CalendarScreenModel(
private val tasksRepository: TasksRepository,
- settingsRepository: SettingsRepository
+ settingsRepository: SettingsRepository,
) : ScreenModel {
private val _selectedDay = MutableStateFlow(
Clock.System.now().toLocalDateTime(
- TimeZone.currentSystemDefault()
- ).date
+ TimeZone.currentSystemDefault(),
+ ).date,
)
val selectedDay = _selectedDay.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = Clock.System.now().toLocalDateTime(
- TimeZone.currentSystemDefault()
- ).date
+ TimeZone.currentSystemDefault(),
+ ).date,
)
fun setSelectedDay(date: kotlinx.datetime.LocalDate) {
@@ -59,17 +59,17 @@ class CalendarScreenModel(
}
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = emptyList()
+ initialValue = emptyList(),
)
val hourFormat = settingsRepository.getHourFormat()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val sessionTime = settingsRepository.getSessionTime()
@@ -77,23 +77,23 @@ class CalendarScreenModel(
it
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val shortBreakTime = settingsRepository.getShortBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val longBreakTime = settingsRepository.getLongBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
private val _selectedTask = MutableStateFlow(null)
@@ -109,35 +109,35 @@ class CalendarScreenModel(
}
fun pushToTomorrow(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTask(
task.copy(
date = task.date.plusDays(1),
- start = task.start.plusDays(1)
- )
+ start = task.start.plusDays(1),
+ ),
)
}
}
fun markAsCompleted(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTaskCompleted(
id = task.id,
- completed = true
+ completed = true,
)
tasksRepository.updateTaskActive(
id = task.id,
- active = false
+ active = false,
)
tasksRepository.updateTaskInProgress(
id = task.id,
- inProgressTask = false
+ inProgressTask = false,
)
}
}
fun deleteTask(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.deleteTask(task.id)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/AllTasksScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/AllTasksScreen.kt
index 02ece1b..7bd838c 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/AllTasksScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/AllTasksScreen.kt
@@ -46,20 +46,21 @@ import com.joelkanyi.focusbloom.core.presentation.component.TaskCard
import com.joelkanyi.focusbloom.feature.home.component.TaskOptionsBottomSheet
import com.joelkanyi.focusbloom.feature.taskprogress.TaskProgressScreen
import com.joelkanyi.focusbloom.platform.StatusBarColors
+import org.koin.compose.rememberKoinInject
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
data class AllTasksScreen(
- val type: String
+ val type: String,
) : Screen, KoinComponent {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
override fun Content() {
- val screenModel = get()
+ val screenModel = rememberKoinInject()
StatusBarColors(
statusBarColor = MaterialTheme.colorScheme.background,
- navBarColor = MaterialTheme.colorScheme.background
+ navBarColor = MaterialTheme.colorScheme.background,
)
val navigator = LocalNavigator.currentOrThrow
val tasksState = screenModel.tasks.collectAsState().value
@@ -97,11 +98,11 @@ data class AllTasksScreen(
screenModel.markAsCompleted(it)
},
onClickEditTask = {
- /*tabNavigator.current = BloomTab.AddTaskTab(
- taskId = it.id
- )*/
+ /*tabNavigator.current = BloomTab.AddTaskTab(
+ taskId = it.id
+ )*/
},
- task = selectedTask
+ task = selectedTask,
)
}
}
@@ -122,21 +123,31 @@ data class AllTasksScreen(
},
onClickTask = {
navigator.push(TaskProgressScreen(taskId = it.id))
- }
+ },
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun AllTasksScreenContent(tasksState: TasksState, timeFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakTime: Int, onClickNavigateBack: () -> Unit, onClickTaskOptions: (task: Task) -> Unit, onClickTask: (task: Task) -> Unit, type: String) {
+fun AllTasksScreenContent(
+ tasksState: TasksState,
+ timeFormat: Int,
+ sessionTime: Int,
+ shortBreakTime: Int,
+ longBreakTime: Int,
+ onClickNavigateBack: () -> Unit,
+ onClickTaskOptions: (task: Task) -> Unit,
+ onClickTask: (task: Task) -> Unit,
+ type: String,
+) {
Box(
- modifier = Modifier.fillMaxSize()
+ modifier = Modifier.fillMaxSize(),
) {
when (tasksState) {
is TasksState.Loading -> {
CircularProgressIndicator(
- modifier = Modifier.align(Alignment.Center)
+ modifier = Modifier.align(Alignment.Center),
)
}
@@ -151,10 +162,10 @@ fun AllTasksScreenContent(tasksState: TasksState, timeFormat: Int, sessionTime:
IconButton(onClick = onClickNavigateBack) {
Icon(
imageVector = Icons.Outlined.ArrowBack,
- contentDescription = "Back"
+ contentDescription = "Back",
)
}
- }
+ },
) {
Text(
text = "${
@@ -162,21 +173,21 @@ fun AllTasksScreenContent(tasksState: TasksState, timeFormat: Int, sessionTime:
} Tasks (${
if (type == "today") tasks.size else overdueTasks.size
})",
- color = if (type == "today") MaterialTheme.colorScheme.onBackground else MaterialTheme.colorScheme.error
+ color = if (type == "today") MaterialTheme.colorScheme.onBackground else MaterialTheme.colorScheme.error,
)
}
- }
+ },
) { paddingValues ->
LazyColumn(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize(),
contentPadding = PaddingValues(horizontal = 16.dp),
- verticalArrangement = Arrangement.spacedBy(12.dp)
+ verticalArrangement = Arrangement.spacedBy(12.dp),
) {
items(
items = if (type == "today") tasks else overdueTasks,
- key = { it.id }
+ key = { it.id },
) {
TaskCard(
type = type,
@@ -187,7 +198,7 @@ fun AllTasksScreenContent(tasksState: TasksState, timeFormat: Int, sessionTime:
focusSessions = it.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/HomeScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/HomeScreen.kt
index 0311f9d..40309fe 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/HomeScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/HomeScreen.kt
@@ -55,6 +55,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import cafe.adriel.voyager.navigator.tab.LocalTabNavigator
import com.joelkanyi.focusbloom.core.domain.model.SessionType
@@ -65,7 +66,6 @@ import com.joelkanyi.focusbloom.core.presentation.component.TaskProgress
import com.joelkanyi.focusbloom.core.presentation.theme.LongBreakColor
import com.joelkanyi.focusbloom.core.presentation.theme.SessionColor
import com.joelkanyi.focusbloom.core.presentation.theme.ShortBreakColor
-import com.joelkanyi.focusbloom.core.utils.LocalAppNavigator
import com.joelkanyi.focusbloom.core.utils.pickFirstName
import com.joelkanyi.focusbloom.core.utils.sessionType
import com.joelkanyi.focusbloom.core.utils.taskCompleteMessage
@@ -77,18 +77,20 @@ import com.joelkanyi.focusbloom.feature.taskprogress.TaskProgressScreen
import com.joelkanyi.focusbloom.feature.taskprogress.Timer
import com.joelkanyi.focusbloom.feature.taskprogress.TimerState
import com.joelkanyi.focusbloom.platform.StatusBarColors
-import org.jetbrains.compose.resources.ExperimentalResourceApi
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.il_completed
+import focusbloom.shared.generated.resources.il_empty
import org.jetbrains.compose.resources.painterResource
-import org.koin.compose.rememberKoinInject
+import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun HomeScreen() {
- val screenModel: HomeScreenModel = rememberKoinInject()
-
+fun HomeScreen(
+ screenModel: HomeScreenModel = koinInject(),
+) {
StatusBarColors(
statusBarColor = MaterialTheme.colorScheme.background,
- navBarColor = MaterialTheme.colorScheme.background
+ navBarColor = MaterialTheme.colorScheme.background,
)
val tasksState = screenModel.tasks.collectAsState().value
val username = screenModel.username.collectAsState().value ?: ""
@@ -96,7 +98,8 @@ fun HomeScreen() {
val sessionTime = screenModel.sessionTime.collectAsState().value ?: 25
val shortBreakTime = screenModel.shortBreakTime.collectAsState().value ?: 5
val longBreakTime = screenModel.longBreakTime.collectAsState().value ?: 15
- val navigator = LocalAppNavigator.currentOrThrow
+ val navigator = LocalNavigator.currentOrThrow
+ val tabNavigator = LocalTabNavigator.current
val selectedTask = screenModel.selectedTask.collectAsState().value
val openBottomSheet = screenModel.openBottomSheet.collectAsState().value
val shortBreakColor = screenModel.shortBreakColor.collectAsState().value
@@ -105,7 +108,6 @@ fun HomeScreen() {
val timerState = Timer.timerState.collectAsState().value
val tickingTime = Timer.tickingTime.collectAsState().value
val bottomSheetState = rememberModalBottomSheetState()
- val tabNavigator = LocalTabNavigator.current
val remindersOn = screenModel.remindersOn.collectAsState().value
LaunchedEffect(Unit) {
@@ -150,7 +152,7 @@ fun HomeScreen() {
onClickEditTask = {
tabNavigator.current = BloomTab.AddTaskTab(taskId = it.id)
},
- task = selectedTask
+ task = selectedTask,
)
}
}
@@ -172,11 +174,11 @@ fun HomeScreen() {
screenModel.selectTask(it)
screenModel.openBottomSheet(true)
} else {
- navigator.push(TaskProgressScreen(taskId = it.id))
+ navigator.parent?.push(TaskProgressScreen(taskId = it.id))
}
},
onClickSeeAllTasks = {
- navigator.push(AllTasksScreen(it))
+ navigator.parent?.push(AllTasksScreen(it))
},
onClickTaskOptions = {
screenModel.selectTask(it)
@@ -194,11 +196,10 @@ fun HomeScreen() {
else -> {}
}
- }
+ },
)
}
-@OptIn(ExperimentalResourceApi::class)
@Composable
private fun HomeScreenContent(
tasksState: TasksState,
@@ -215,18 +216,18 @@ private fun HomeScreenContent(
focusTimeColor: Long?,
shortBreakColor: Long?,
longBreakColor: Long?,
- onClickActiveTaskOptions: (task: Task) -> Unit
+ onClickActiveTaskOptions: (task: Task) -> Unit,
) {
Scaffold { paddingValues ->
Box(
modifier = Modifier
.padding(paddingValues)
- .fillMaxSize()
+ .fillMaxSize(),
) {
when (tasksState) {
TasksState.Loading -> {
CircularProgressIndicator(
- modifier = Modifier.align(Alignment.Center)
+ modifier = Modifier.align(Alignment.Center),
)
}
@@ -236,7 +237,7 @@ private fun HomeScreenContent(
val activeTask = tasks.firstOrNull { it.active }
LazyColumn(
contentPadding = PaddingValues(horizontal = 16.dp),
- verticalArrangement = Arrangement.spacedBy(8.dp)
+ verticalArrangement = Arrangement.spacedBy(8.dp),
) {
item {
if (activeTask != null) {
@@ -246,7 +247,7 @@ private fun HomeScreenContent(
Color(SessionColor)
} else {
Color(
- focusTimeColor
+ focusTimeColor,
)
}
}
@@ -256,7 +257,7 @@ private fun HomeScreenContent(
Color(LongBreakColor)
} else {
Color(
- longBreakColor
+ longBreakColor,
)
}
}
@@ -266,7 +267,7 @@ private fun HomeScreenContent(
Color(ShortBreakColor)
} else {
Color(
- shortBreakColor
+ shortBreakColor,
)
}
}
@@ -277,14 +278,14 @@ private fun HomeScreenContent(
containerColor = containerColor,
onClickTaskOptions = onClickActiveTaskOptions,
timerState = timerState,
- tickingTime = tickingTime
+ tickingTime = tickingTime,
)
}
}
item {
Text(
text = "Hello, ${username.pickFirstName()}!",
- style = MaterialTheme.typography.displaySmall
+ style = MaterialTheme.typography.displaySmall,
)
}
item {
@@ -297,14 +298,14 @@ private fun HomeScreenContent(
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = "Overdue Tasks (${overdueTasks.size})",
style = MaterialTheme.typography.titleLarge.copy(
fontWeight = FontWeight.Bold,
- color = MaterialTheme.colorScheme.error
- )
+ color = MaterialTheme.colorScheme.error,
+ ),
)
if (overdueTasks.size > 3) {
Text(
@@ -315,8 +316,8 @@ private fun HomeScreenContent(
style = MaterialTheme.typography.labelLarge.copy(
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.error,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
}
@@ -324,7 +325,7 @@ private fun HomeScreenContent(
items(
items = tasksState.overdueTasks.take(3),
- key = { it.id }
+ key = { it.id },
) {
TaskCard(
type = "overdue",
@@ -335,7 +336,7 @@ private fun HomeScreenContent(
focusSessions = it.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
}
}
@@ -345,13 +346,13 @@ private fun HomeScreenContent(
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = "Today's Tasks (${tasks.size})",
style = MaterialTheme.typography.titleLarge.copy(
- fontWeight = FontWeight.Bold
- )
+ fontWeight = FontWeight.Bold,
+ ),
)
if (tasks.size > 3) {
Text(
@@ -362,8 +363,8 @@ private fun HomeScreenContent(
style = MaterialTheme.typography.labelLarge.copy(
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.primary,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
}
@@ -372,7 +373,7 @@ private fun HomeScreenContent(
if (tasks.all { it.completed }.not()) {
items(
items = tasks.take(3),
- key = { it.id }
+ key = { it.id },
) {
TaskCard(
type = "today",
@@ -383,7 +384,7 @@ private fun HomeScreenContent(
focusSessions = it.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
}
}
@@ -393,17 +394,15 @@ private fun HomeScreenContent(
Column(
modifier = Modifier
.fillMaxWidth(),
- horizontalAlignment = CenterHorizontally
+ horizontalAlignment = CenterHorizontally,
) {
Spacer(modifier = Modifier.height(24.dp))
Image(
modifier = Modifier
.size(300.dp)
.align(CenterHorizontally),
- painter = painterResource(
- if (tasks.isEmpty()) "il_empty.xml" else "il_completed.xml"
- ),
- contentDescription = null
+ painter = painterResource(if (tasks.isEmpty()) Res.drawable.il_empty else Res.drawable.il_completed),
+ contentDescription = null,
)
Spacer(modifier = Modifier.height(24.dp))
Text(
@@ -412,7 +411,7 @@ private fun HomeScreenContent(
.align(CenterHorizontally),
style = MaterialTheme.typography.titleSmall.copy(
fontSize = 14.sp,
- fontWeight = FontWeight.Bold
+ fontWeight = FontWeight.Bold,
),
text = if (tasks.isEmpty()) {
"Start your day productively! Add your first task."
@@ -421,7 +420,7 @@ private fun HomeScreenContent(
} else {
""
},
- textAlign = TextAlign.Center
+ textAlign = TextAlign.Center,
)
Spacer(modifier = Modifier.height(8.dp))
Text(
@@ -436,9 +435,9 @@ private fun HomeScreenContent(
""
},
style = MaterialTheme.typography.labelLarge.copy(
- fontSize = 14.sp
+ fontSize = 14.sp,
),
- textAlign = TextAlign.Center
+ textAlign = TextAlign.Center,
)
}
}
@@ -452,63 +451,70 @@ private fun HomeScreenContent(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun ActiveTaskCard(task: Task, timerState: TimerState, tickingTime: Long, onClick: (task: Task) -> Unit, onClickTaskOptions: (task: Task) -> Unit, containerColor: Color) {
+fun ActiveTaskCard(
+ task: Task,
+ timerState: TimerState,
+ tickingTime: Long,
+ onClick: (task: Task) -> Unit,
+ onClickTaskOptions: (task: Task) -> Unit,
+ containerColor: Color,
+) {
Card(
onClick = {
onClick(task)
},
colors = CardDefaults.cardColors(
- containerColor = containerColor
- )
+ containerColor = containerColor,
+ ),
) {
Row(
modifier = Modifier
.padding(horizontal = 12.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Column(
modifier = Modifier
.fillMaxWidth(.85f),
- verticalArrangement = Arrangement.spacedBy(6.dp)
+ verticalArrangement = Arrangement.spacedBy(6.dp),
) {
Text(
text = task.name,
style = MaterialTheme.typography.titleSmall.copy(
fontWeight = FontWeight.SemiBold,
- color = MaterialTheme.colorScheme.onPrimary
+ color = MaterialTheme.colorScheme.onPrimary,
),
maxLines = 1,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
)
Text(
text = "${
- when (task.current.sessionType()) {
- SessionType.Focus -> {
- "Focus Session"
- }
+ when (task.current.sessionType()) {
+ SessionType.Focus -> {
+ "Focus Session"
+ }
- SessionType.ShortBreak -> {
- "Short Break"
- }
+ SessionType.ShortBreak -> {
+ "Short Break"
+ }
- SessionType.LongBreak -> {
- "Long Break"
+ SessionType.LongBreak -> {
+ "Long Break"
+ }
}
- }
} - ${
- tickingTime.toTimer()
+ tickingTime.toTimer()
}",
style = MaterialTheme.typography.labelMedium.copy(
color = MaterialTheme.colorScheme.onPrimary,
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
}
IconButton(
onClick = {
onClickTaskOptions(task)
- }
+ },
) {
Icon(
modifier = Modifier,
@@ -526,7 +532,7 @@ fun ActiveTaskCard(task: Task, timerState: TimerState, tickingTime: Long, onClic
}
},
contentDescription = "Play/Pause",
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
}
}
@@ -541,29 +547,29 @@ private fun TodayTaskProgressCard(tasks: List) {
.fillMaxWidth()
.padding(12.dp),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(12.dp)
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
TaskProgress(
mainColor = MaterialTheme.colorScheme.primary,
percentage = taskCompletionPercentage(tasks).toFloat(),
- counterColor = MaterialTheme.colorScheme.onSurface
+ counterColor = MaterialTheme.colorScheme.onSurface,
)
Column(
- verticalArrangement = Arrangement.spacedBy(4.dp)
+ verticalArrangement = Arrangement.spacedBy(4.dp),
) {
Text(
text = taskCompleteMessage(tasks),
style = MaterialTheme.typography.headlineSmall.copy(
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "${tasks.filter { it.completed }.size} of ${tasks.size} tasks completed",
style = MaterialTheme.typography.labelMedium.copy(
- color = MaterialTheme.colorScheme.onSurface
- )
+ color = MaterialTheme.colorScheme.onSurface,
+ ),
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/HomeScreenModel.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/HomeScreenModel.kt
index 85d11f6..b1defcc 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/HomeScreenModel.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/HomeScreenModel.kt
@@ -16,7 +16,7 @@
package com.joelkanyi.focusbloom.feature.home
import cafe.adriel.voyager.core.model.ScreenModel
-import cafe.adriel.voyager.core.model.coroutineScope
+import cafe.adriel.voyager.core.model.screenModelScope
import com.joelkanyi.focusbloom.core.domain.model.Task
import com.joelkanyi.focusbloom.core.domain.repository.settings.SettingsRepository
import com.joelkanyi.focusbloom.core.domain.repository.tasks.TasksRepository
@@ -34,7 +34,7 @@ import kotlinx.datetime.toLocalDateTime
class HomeScreenModel(
private val tasksRepository: TasksRepository,
- private val settingsRepository: SettingsRepository
+ private val settingsRepository: SettingsRepository,
) : ScreenModel {
private val _openBottomSheet = MutableStateFlow(false)
val openBottomSheet = _openBottomSheet.asStateFlow()
@@ -45,9 +45,9 @@ class HomeScreenModel(
val hourFormat = settingsRepository.getHourFormat()
.map { it ?: 24 }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = 24
+ initialValue = 24,
)
val sessionTime = settingsRepository.getSessionTime()
@@ -55,23 +55,23 @@ class HomeScreenModel(
it
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val shortBreakTime = settingsRepository.getShortBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val longBreakTime = settingsRepository.getLongBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val remindersOn = settingsRepository.remindersOn()
@@ -79,19 +79,19 @@ class HomeScreenModel(
ReminderState.Success(it)
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = ReminderState.Loading
+ initialValue = ReminderState.Loading,
)
fun deleteTask(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.deleteTask(task.id)
}
}
fun updateTask(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTask(task)
}
}
@@ -103,40 +103,40 @@ class HomeScreenModel(
}
fun pushToTomorrow(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTask(
task.copy(
date = task.date.plusDays(1),
- start = task.start.plusDays(1)
- )
+ start = task.start.plusDays(1),
+ ),
)
}
}
fun pushToToday(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTask(
task.copy(
date = today(),
- start = today()
- )
+ start = today(),
+ ),
)
}
}
fun markAsCompleted(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTaskCompleted(
id = task.id,
- completed = true
+ completed = true,
)
tasksRepository.updateTaskActive(
id = task.id,
- active = false
+ active = false,
)
tasksRepository.updateTaskInProgress(
id = task.id,
- inProgressTask = false
+ inProgressTask = false,
)
}
}
@@ -156,49 +156,49 @@ class HomeScreenModel(
it.date.date < Clock.System.now()
.toLocalDateTime(TimeZone.currentSystemDefault()).date &&
!it.completed
- }
+ },
)
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = TasksState.Loading
+ initialValue = TasksState.Loading,
)
val username = settingsRepository.getUsername()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val shortBreakColor = settingsRepository.shortBreakColor()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val longBreakColor = settingsRepository.longBreakColor()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val focusColor = settingsRepository.focusColor()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
fun toggleReminder(value: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.toggleReminder(value)
}
}
@@ -208,7 +208,7 @@ sealed class TasksState {
data object Loading : TasksState()
data class Success(
val tasks: List,
- val overdueTasks: List
+ val overdueTasks: List,
) : TasksState()
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/component/Option.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/component/Option.kt
index 193fa29..003896b 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/component/Option.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/component/Option.kt
@@ -39,21 +39,21 @@ fun Option(icon: ImageVector, text: String, onClick: () -> Unit) {
.fillMaxWidth()
.clickable { onClick() },
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(12.dp)
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Icon(
modifier = Modifier,
imageVector = icon,
contentDescription = text,
- tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
+ tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f),
)
Text(
modifier = Modifier,
text = text,
style = MaterialTheme.typography.labelMedium.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/component/TaskOptionsBottomSheet.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/component/TaskOptionsBottomSheet.kt
index 4d71230..353f48e 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/component/TaskOptionsBottomSheet.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/home/component/TaskOptionsBottomSheet.kt
@@ -35,13 +35,24 @@ import com.joelkanyi.focusbloom.core.domain.model.Task
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun TaskOptionsBottomSheet(bottomSheetState: SheetState, onClickCancel: (task: Task) -> Unit, onClickDelete: (task: Task) -> Unit, onClickPushToTomorrow: (task: Task) -> Unit, task: Task, onDismissRequest: () -> Unit, onClickMarkAsCompleted: (task: Task) -> Unit, onClickEditTask: (task: Task) -> Unit, type: String, onClickPushToToday: (task: Task) -> Unit) {
+fun TaskOptionsBottomSheet(
+ bottomSheetState: SheetState,
+ onClickCancel: (task: Task) -> Unit,
+ onClickDelete: (task: Task) -> Unit,
+ onClickPushToTomorrow: (task: Task) -> Unit,
+ task: Task,
+ onDismissRequest: () -> Unit,
+ onClickMarkAsCompleted: (task: Task) -> Unit,
+ onClickEditTask: (task: Task) -> Unit,
+ type: String,
+ onClickPushToToday: (task: Task) -> Unit,
+) {
ModalBottomSheet(
onDismissRequest = onDismissRequest,
- sheetState = bottomSheetState
+ sheetState = bottomSheetState,
) {
Column(
- verticalArrangement = Arrangement.spacedBy(24.dp)
+ verticalArrangement = Arrangement.spacedBy(24.dp),
) {
Option(
icon = Icons.Default.Edit,
@@ -49,7 +60,7 @@ fun TaskOptionsBottomSheet(bottomSheetState: SheetState, onClickCancel: (task: T
onClick = {
onClickEditTask(task)
onDismissRequest()
- }
+ },
)
Option(
icon = Icons.Outlined.EditCalendar,
@@ -57,7 +68,7 @@ fun TaskOptionsBottomSheet(bottomSheetState: SheetState, onClickCancel: (task: T
onClick = {
if (type == "overdue") onClickPushToToday(task) else onClickPushToTomorrow(task)
onDismissRequest()
- }
+ },
)
Option(
icon = Icons.Outlined.Done,
@@ -65,7 +76,7 @@ fun TaskOptionsBottomSheet(bottomSheetState: SheetState, onClickCancel: (task: T
onClick = {
onClickMarkAsCompleted(task)
onDismissRequest()
- }
+ },
)
Option(
icon = Icons.Outlined.Delete,
@@ -73,7 +84,7 @@ fun TaskOptionsBottomSheet(bottomSheetState: SheetState, onClickCancel: (task: T
onClick = {
onClickDelete(task)
onDismissRequest()
- }
+ },
)
Option(
icon = Icons.Outlined.Close,
@@ -81,7 +92,7 @@ fun TaskOptionsBottomSheet(bottomSheetState: SheetState, onClickCancel: (task: T
onClick = {
onClickCancel(task)
onDismissRequest()
- }
+ },
)
Spacer(modifier = Modifier.height(32.dp))
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/OnboadingViewModel.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/OnboadingViewModel.kt
index ab66fd6..a54f5a3 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/OnboadingViewModel.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/OnboadingViewModel.kt
@@ -16,7 +16,7 @@
package com.joelkanyi.focusbloom.feature.onboarding
import cafe.adriel.voyager.core.model.ScreenModel
-import cafe.adriel.voyager.core.model.coroutineScope
+import cafe.adriel.voyager.core.model.screenModelScope
import com.joelkanyi.focusbloom.core.domain.repository.settings.SettingsRepository
import com.joelkanyi.focusbloom.core.utils.UiEvents
import kotlinx.coroutines.channels.Channel
@@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
class OnboadingViewModel(
- private val settingsRepository: SettingsRepository
+ private val settingsRepository: SettingsRepository,
) : ScreenModel {
private val _eventsFlow = Channel(Channel.UNLIMITED)
val eventsFlow = _eventsFlow.receiveAsFlow()
@@ -38,7 +38,7 @@ class OnboadingViewModel(
}
fun saveUsername() {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveUsername(username.value.trim())
settingsRepository.toggleReminder(1)
_eventsFlow.send(UiEvents.Navigation)
@@ -58,6 +58,6 @@ class OnboadingViewModel(
"be disciplined",
"be motivated",
"be consistent",
- "be mindful"
+ "be mindful",
)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/OnboardingScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/OnboardingScreen.kt
index ebb5372..357e0be 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/OnboardingScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/OnboardingScreen.kt
@@ -39,7 +39,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -51,7 +50,12 @@ import androidx.compose.ui.unit.sp
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.il_statistics
+import focusbloom.shared.generated.resources.il_tasks
+import focusbloom.shared.generated.resources.il_work_time
import kotlinx.coroutines.launch
+import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
import org.koin.core.component.KoinComponent
@@ -75,39 +79,44 @@ class OnboardingScreen : Screen, KoinComponent {
},
onClickGetStarted = {
navigator.push(UsernameScreen())
- }
+ },
)
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
-fun OnboardingScreenContent(pageCount: Int, pagerState: PagerState, onClickNext: () -> Unit, onClickGetStarted: () -> Unit) {
+fun OnboardingScreenContent(
+ pageCount: Int,
+ pagerState: PagerState,
+ onClickNext: () -> Unit,
+ onClickGetStarted: () -> Unit,
+) {
Scaffold(
bottomBar = {
if (pagerState.currentPage == pageCount - 1) {
OnBoardingNavigationButton(
modifier = Modifier.padding(16.dp),
text = "Get Started",
- onClick = onClickGetStarted
+ onClick = onClickGetStarted,
)
} else {
OnBoardingNavigationButton(
modifier = Modifier.padding(16.dp),
text = "Next",
- onClick = onClickNext
+ onClick = onClickNext,
)
}
- }
+ },
) { paddingValues ->
Column(
- modifier = Modifier.padding(paddingValues)
+ modifier = Modifier.padding(paddingValues),
) {
HorizontalPager(
modifier = Modifier
.weight(.9f)
.padding(16.dp),
- state = pagerState
+ state = pagerState,
) { currentPage ->
when (currentPage) {
0 -> OnboardingFirstPage()
@@ -118,7 +127,7 @@ fun OnboardingScreenContent(pageCount: Int, pagerState: PagerState, onClickNext:
PageIndicators(
pageCount = pageCount,
- currentPage = pagerState.currentPage
+ currentPage = pagerState.currentPage,
)
}
}
@@ -130,7 +139,7 @@ private fun ColumnScope.PageIndicators(pageCount: Int, currentPage: Int) {
Modifier
.weight(.1f)
.fillMaxWidth(),
- horizontalArrangement = Arrangement.Center
+ horizontalArrangement = Arrangement.Center,
) {
repeat(pageCount) { iteration ->
val color =
@@ -138,7 +147,7 @@ private fun ColumnScope.PageIndicators(pageCount: Int, currentPage: Int) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onSurface.copy(
- alpha = 0.2f
+ alpha = 0.2f,
)
}
Box(
@@ -147,51 +156,54 @@ private fun ColumnScope.PageIndicators(pageCount: Int, currentPage: Int) {
.clip(CircleShape)
.background(color)
.width(24.dp)
- .height(8.dp)
+ .height(8.dp),
)
}
}
}
+@OptIn(ExperimentalResourceApi::class)
@Composable
private fun OnboardingFirstPage() {
PageContent(
title = "Organize Tasks and Boost Productivity",
description = "Welcome to FocusBloom, your task management and productivity companion. Effortlessly organize your tasks and supercharge your productivity journey.",
- illustration = "il_tasks.xml"
+ illustration = Res.drawable.il_tasks,
)
}
+@OptIn(ExperimentalResourceApi::class)
@Composable
private fun OnboardingSecondPage() {
PageContent(
title = "Tailor Your Work Sessions",
description = "With FocusBloom, you have the power to customize your work and break durations to match your preferences and maximize efficiency.",
- illustration = "il_work_time.xml"
+ illustration = Res.drawable.il_work_time,
)
}
+@OptIn(ExperimentalResourceApi::class)
@Composable
private fun OnboardingThirdPage() {
PageContent(
title = "Visualize Your Progress",
description = "Experience the power of progress tracking with FocusBloom. Gain insights into your productivity journey and visualize task completion trends.",
- illustration = "il_statistics.xml"
+ illustration = Res.drawable.il_statistics,
)
}
@OptIn(ExperimentalResourceApi::class)
@Composable
-private fun PageContent(title: String, description: String, illustration: String) {
+private fun PageContent(title: String, description: String, illustration: DrawableResource) {
Column(
modifier = Modifier.fillMaxSize(),
- horizontalAlignment = Alignment.CenterHorizontally
+ horizontalAlignment = Alignment.CenterHorizontally,
) {
Image(
painter = painterResource(illustration),
- contentDescription = illustration,
- modifier = Modifier.size(370.dp)
+ contentDescription = null,
+ modifier = Modifier.size(370.dp),
)
Spacer(modifier = Modifier.height(32.dp))
Text(
@@ -199,8 +211,8 @@ private fun PageContent(title: String, description: String, illustration: String
text = title,
style = MaterialTheme.typography.titleLarge.copy(
fontSize = 22.sp,
- textAlign = TextAlign.Center
- )
+ textAlign = TextAlign.Center,
+ ),
)
Spacer(modifier = Modifier.height(16.dp))
Text(
@@ -208,8 +220,8 @@ private fun PageContent(title: String, description: String, illustration: String
text = description,
style = MaterialTheme.typography.labelMedium.copy(
fontSize = 14.sp,
- textAlign = TextAlign.Center
- )
+ textAlign = TextAlign.Center,
+ ),
)
}
}
@@ -221,14 +233,14 @@ fun OnBoardingNavigationButton(modifier: Modifier = Modifier, text: String, onCl
.fillMaxWidth()
.height(56.dp),
onClick = onClick,
- shape = MaterialTheme.shapes.medium
+ shape = MaterialTheme.shapes.medium,
) {
Text(
text = text,
style = MaterialTheme.typography.titleLarge.copy(
fontSize = 16.sp,
- fontWeight = FontWeight.Bold
- )
+ fontWeight = FontWeight.Bold,
+ ),
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/UsernameScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/UsernameScreen.kt
index 91b32a0..d3b4687 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/UsernameScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/onboarding/UsernameScreen.kt
@@ -56,6 +56,7 @@ import com.joelkanyi.focusbloom.main.MainScreen
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
+import org.koin.compose.rememberKoinInject
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
@@ -64,7 +65,7 @@ class UsernameScreen : Screen, KoinComponent {
@OptIn(ExperimentalComposeUiApi::class)
@Composable
override fun Content() {
- val onboadingViewModel = get()
+ val onboadingViewModel = rememberKoinInject()
val navigator = LocalNavigator.currentOrThrow
val username = onboadingViewModel.username.collectAsState().value
val keyboardController = LocalSoftwareKeyboardController.current
@@ -91,22 +92,27 @@ class UsernameScreen : Screen, KoinComponent {
onClickContinue = {
keyboardController?.hide()
onboadingViewModel.saveUsername()
- }
+ },
)
}
}
@Composable
-fun UsernameScreenContent(username: String, typeWriterTextParts: List, onUsernameChange: (String) -> Unit, onClickContinue: () -> Unit) {
+fun UsernameScreenContent(
+ username: String,
+ typeWriterTextParts: List,
+ onUsernameChange: (String) -> Unit,
+ onClickContinue: () -> Unit,
+) {
LazyColumn(
modifier = Modifier
.padding(16.dp)
- .fillMaxSize()
+ .fillMaxSize(),
) {
item {
TypewriterText(
baseText = "Focus Bloom app is what you need to",
- parts = typeWriterTextParts
+ parts = typeWriterTextParts,
)
}
@@ -115,8 +121,8 @@ fun UsernameScreenContent(username: String, typeWriterTextParts: List, o
Text(
text = "What's your username?",
style = MaterialTheme.typography.labelLarge.copy(
- fontSize = 18.sp
- )
+ fontSize = 18.sp,
+ ),
)
}
@@ -135,13 +141,13 @@ fun UsernameScreenContent(username: String, typeWriterTextParts: List, o
},
onClickDone = {
onClickContinue()
- }
+ },
)
}
item {
AnimatedVisibility(
- username.isNotEmpty()
+ username.isNotEmpty(),
) {
Column {
Spacer(modifier = Modifier.height(56.dp))
@@ -150,13 +156,13 @@ fun UsernameScreenContent(username: String, typeWriterTextParts: List, o
.fillMaxWidth()
.height(56.dp),
shape = MaterialTheme.shapes.medium,
- onClick = onClickContinue
+ onClick = onClickContinue,
) {
Text(
text = "Continue",
style = MaterialTheme.typography.labelLarge.copy(
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
}
}
@@ -166,7 +172,12 @@ fun UsernameScreenContent(username: String, typeWriterTextParts: List, o
}
@Composable
-private fun UsernameTextField(modifier: Modifier, name: String, onNameChange: (String) -> Unit, onClickDone: () -> Unit) {
+private fun UsernameTextField(
+ modifier: Modifier,
+ name: String,
+ onNameChange: (String) -> Unit,
+ onClickDone: () -> Unit,
+) {
TextField(
modifier = modifier,
value = name,
@@ -180,8 +191,8 @@ private fun UsernameTextField(modifier: Modifier, name: String, onNameChange: (S
fontWeight = FontWeight.ExtraLight,
fontSize = 18.sp,
letterSpacing = -(1.6).sp,
- lineHeight = 32.sp
- )
+ lineHeight = 32.sp,
+ ),
)
},
colors = TextFieldDefaults.colors(
@@ -189,22 +200,22 @@ private fun UsernameTextField(modifier: Modifier, name: String, onNameChange: (S
focusedContainerColor = MaterialTheme.colorScheme.background,
focusedIndicatorColor = MaterialTheme.colorScheme.primary,
unfocusedIndicatorColor = MaterialTheme.colorScheme.primary,
- disabledIndicatorColor = MaterialTheme.colorScheme.primary
+ disabledIndicatorColor = MaterialTheme.colorScheme.primary,
),
textStyle = MaterialTheme.typography.labelLarge.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 18.sp
+ fontSize = 18.sp,
),
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done,
keyboardType = KeyboardType.Text,
- capitalization = KeyboardCapitalization.Words
+ capitalization = KeyboardCapitalization.Words,
),
keyboardActions = KeyboardActions(
onDone = {
onClickDone()
- }
- )
+ },
+ ),
)
}
@@ -220,8 +231,8 @@ private fun TypewriterText(modifier: Modifier = Modifier, baseText: String, part
fontWeight = FontWeight.SemiBold,
fontSize = 24.sp,
letterSpacing = -(1.6).sp,
- lineHeight = 32.sp
- )
+ lineHeight = 32.sp,
+ ),
)
LaunchedEffect(key1 = parts) {
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/settings/SettingsScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/settings/SettingsScreen.kt
index 3dadf8b..c4e6bb7 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/settings/SettingsScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/settings/SettingsScreen.kt
@@ -86,19 +86,19 @@ import com.joelkanyi.focusbloom.core.presentation.theme.Yellow
import com.joelkanyi.focusbloom.core.utils.isDigitsOnly
import com.joelkanyi.focusbloom.core.utils.timeFormat
import com.joelkanyi.focusbloom.platform.StatusBarColors
-import org.koin.compose.rememberKoinInject
+import org.koin.compose.koinInject
@Composable
-fun SettingsScreen() {
- val screenModel: SettingsScreenModel = rememberKoinInject()
-
+fun SettingsScreen(
+ screenModel: SettingsScreenModel = koinInject(),
+) {
val darkTheme = when (screenModel.appTheme.collectAsState().value) {
1 -> true
else -> false
}
StatusBarColors(
statusBarColor = MaterialTheme.colorScheme.background,
- navBarColor = MaterialTheme.colorScheme.background
+ navBarColor = MaterialTheme.colorScheme.background,
)
val sessionTime = screenModel.sessionTime.collectAsState().value ?: 25
@@ -204,9 +204,9 @@ fun SettingsScreen() {
1
} else {
0
- }
+ },
)
- }
+ },
)
}
@@ -235,23 +235,23 @@ fun SettingsScreenContent(
currentSessionColor: Long,
onSelectColor: (Long) -> Unit,
remindersOn: Boolean,
- onRemindersChange: (Boolean) -> Unit
+ onRemindersChange: (Boolean) -> Unit,
) {
Scaffold(
topBar = {
BloomTopAppBar(
- hasBackNavigation = false
+ hasBackNavigation = false,
) {
Text(text = "Settings")
}
- }
+ },
) { paddingValues ->
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
contentPadding = PaddingValues(16.dp),
- verticalArrangement = Arrangement.spacedBy(8.dp)
+ verticalArrangement = Arrangement.spacedBy(8.dp),
) {
item {
FocusSessionsSetting(
@@ -266,7 +266,7 @@ fun SettingsScreenContent(
},
onExpand = { title ->
openOptions(title)
- }
+ },
)
}
item {
@@ -279,7 +279,7 @@ fun SettingsScreenContent(
},
hourFormats = hourFormats,
selectedHourFormat = selectedHourFormat,
- onHourFormatChange = onHourFormatChange
+ onHourFormatChange = onHourFormatChange,
)
}
/*item {
@@ -309,7 +309,7 @@ fun SettingsScreenContent(
currentShortBreakColor = currentShortBreakColor,
currentLongBreakColor = currentLongBreakColor,
currentSessionColor = currentSessionColor,
- onSelectColor = onSelectColor
+ onSelectColor = onSelectColor,
)
}
item {
@@ -321,7 +321,7 @@ fun SettingsScreenContent(
openOptions(title)
},
remindersOn = remindersOn,
- onRemindersChange = onRemindersChange
+ onRemindersChange = onRemindersChange,
)
}
}
@@ -329,7 +329,16 @@ fun SettingsScreenContent(
}
@Composable
-fun FocusSessionsSetting(focusSessionMinutes: Int, onFocusSessionMinutesChange: (String) -> Unit, shortBreakMinutes: Int, onShortBreakMinutesChange: (String) -> Unit, longBreakMinutes: Int, onLongBreakMinutesChange: (String) -> Unit, onExpand: (String) -> Unit, expanded: (String) -> Boolean) {
+fun FocusSessionsSetting(
+ focusSessionMinutes: Int,
+ onFocusSessionMinutesChange: (String) -> Unit,
+ shortBreakMinutes: Int,
+ onShortBreakMinutesChange: (String) -> Unit,
+ longBreakMinutes: Int,
+ onLongBreakMinutesChange: (String) -> Unit,
+ onExpand: (String) -> Unit,
+ expanded: (String) -> Boolean,
+) {
SettingCard(
onExpand = {
onExpand("Focus Sessions")
@@ -342,7 +351,7 @@ fun FocusSessionsSetting(focusSessionMinutes: Int, onFocusSessionMinutesChange:
var autoStartFocusSession by remember { mutableStateOf(false) }
Row(
modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.spacedBy(12.dp)
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
SessionTime(
modifier = Modifier.weight(1f),
@@ -350,7 +359,7 @@ fun FocusSessionsSetting(focusSessionMinutes: Int, onFocusSessionMinutesChange:
currentValue = focusSessionMinutes.toString(),
onValueChange = {
onFocusSessionMinutesChange(it)
- }
+ },
)
SessionTime(
modifier = Modifier.weight(1f),
@@ -358,7 +367,7 @@ fun FocusSessionsSetting(focusSessionMinutes: Int, onFocusSessionMinutesChange:
currentValue = shortBreakMinutes.toString(),
onValueChange = {
onShortBreakMinutesChange(it)
- }
+ },
)
SessionTime(
modifier = Modifier.weight(1f),
@@ -366,7 +375,7 @@ fun FocusSessionsSetting(focusSessionMinutes: Int, onFocusSessionMinutesChange:
currentValue = longBreakMinutes.toString(),
onValueChange = {
onLongBreakMinutesChange(it)
- }
+ },
)
}
Spacer(modifier = Modifier.height(12.dp))
@@ -375,7 +384,7 @@ fun FocusSessionsSetting(focusSessionMinutes: Int, onFocusSessionMinutesChange:
checked = autoStartBreaks,
onCheckedChange = {
autoStartBreaks = it
- }
+ },
)
Spacer(modifier = Modifier.height(12.dp))
AutoStartSession(
@@ -383,14 +392,20 @@ fun FocusSessionsSetting(focusSessionMinutes: Int, onFocusSessionMinutesChange:
checked = autoStartFocusSession,
onCheckedChange = {
autoStartFocusSession = it
- }
+ },
)
- }
+ },
)
}
@Composable
-fun TimeSetting(onExpand: (String) -> Unit, expanded: (String) -> Boolean, hourFormats: List, selectedHourFormat: Int, onHourFormatChange: (Int) -> Unit) {
+fun TimeSetting(
+ onExpand: (String) -> Unit,
+ expanded: (String) -> Boolean,
+ hourFormats: List,
+ selectedHourFormat: Int,
+ onHourFormatChange: (Int) -> Unit,
+) {
SettingCard(
onExpand = {
onExpand("Time")
@@ -406,9 +421,9 @@ fun TimeSetting(onExpand: (String) -> Unit, expanded: (String) -> Boolean, hourF
onSelectOption = {
onHourFormatChange(it.timeFormat())
onExpand("Time")
- }
+ },
)
- }
+ },
)
}
@@ -436,7 +451,7 @@ fun SoundSetting(onExpand: (String) -> Unit, expanded: (String) -> Boolean) {
selectedOption = selectedAlarmSound,
onSelectOption = {
selectedAlarmSound = it
- }
+ },
)
Slider(
value = alarmSliderPosition,
@@ -444,8 +459,8 @@ fun SoundSetting(onExpand: (String) -> Unit, expanded: (String) -> Boolean) {
onValueChange = { alarmSliderPosition = it },
colors = SliderDefaults.colors(
inactiveTickColor = MaterialTheme.colorScheme.secondary,
- inactiveTrackColor = MaterialTheme.colorScheme.secondary
- )
+ inactiveTrackColor = MaterialTheme.colorScheme.secondary,
+ ),
)
Spacer(modifier = Modifier.height(16.dp))
SoundSelection(
@@ -454,7 +469,7 @@ fun SoundSetting(onExpand: (String) -> Unit, expanded: (String) -> Boolean) {
selectedOption = selectedTickingSound,
onSelectOption = {
selectedTickingSound = it
- }
+ },
)
Slider(
value = tickingSliderPosition,
@@ -462,10 +477,10 @@ fun SoundSetting(onExpand: (String) -> Unit, expanded: (String) -> Boolean) {
onValueChange = { tickingSliderPosition = it },
colors = SliderDefaults.colors(
inactiveTickColor = MaterialTheme.colorScheme.secondary,
- inactiveTrackColor = MaterialTheme.colorScheme.secondary
- )
+ inactiveTrackColor = MaterialTheme.colorScheme.secondary,
+ ),
)
- }
+ },
)
}
@@ -482,7 +497,7 @@ fun ThemeSetting(
currentShortBreakColor: Long,
currentLongBreakColor: Long,
currentSessionColor: Long,
- onSelectColor: (Long) -> Unit
+ onSelectColor: (Long) -> Unit,
) {
SettingCard(
onExpand = {
@@ -501,13 +516,13 @@ fun ThemeSetting(
onSelectColor = {
onShowColorDialog(false)
onSelectColor(it)
- }
+ },
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
Text(text = "Sessions Color Scheme")
ColorsSelection(
@@ -525,7 +540,7 @@ fun ThemeSetting(
},
currentSessionColor = currentSessionColor,
currentShortBreakColor = currentShortBreakColor,
- currentLongBreakColor = currentLongBreakColor
+ currentLongBreakColor = currentLongBreakColor,
)
}
Spacer(modifier = Modifier.height(16.dp))
@@ -540,14 +555,19 @@ fun ThemeSetting(
checked = darkTheme,
onCheckedChange = {
onDarkThemeChange(it)
- }
+ },
)
- }
+ },
)
}
@Composable
-fun NotificationsSetting(onExpand: (String) -> Unit, expanded: (String) -> Boolean, remindersOn: Boolean, onRemindersChange: (Boolean) -> Unit) {
+fun NotificationsSetting(
+ onExpand: (String) -> Unit,
+ expanded: (String) -> Boolean,
+ remindersOn: Boolean,
+ onRemindersChange: (Boolean) -> Unit,
+) {
SettingCard(
onExpand = {
onExpand("Notifications")
@@ -559,22 +579,27 @@ fun NotificationsSetting(onExpand: (String) -> Unit, expanded: (String) -> Boole
AutoStartSession(
title = "Reminders",
checked = remindersOn,
- onCheckedChange = onRemindersChange
+ onCheckedChange = onRemindersChange,
)
- }
+ },
)
}
@Composable
-private fun SoundSelection(options: List, title: String, selectedOption: String, onSelectOption: (String) -> Unit) {
+private fun SoundSelection(
+ options: List,
+ title: String,
+ selectedOption: String,
+ onSelectOption: (String) -> Unit,
+) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
Text(
modifier = Modifier.fillMaxWidth(.5f),
- text = title
+ text = title,
)
BloomDropDown(
modifier = Modifier
@@ -583,7 +608,7 @@ private fun SoundSelection(options: List, title: String, selectedOption:
selectedOption = TextFieldState(text = selectedOption),
onOptionSelected = {
onSelectOption(it)
- }
+ },
)
}
}
@@ -593,67 +618,79 @@ fun AutoStartSession(title: String, checked: Boolean, onCheckedChange: (Boolean)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
Text(text = title)
Switch(
checked = checked,
- onCheckedChange = onCheckedChange
+ onCheckedChange = onCheckedChange,
)
}
}
@Composable
-fun SessionTime(modifier: Modifier = Modifier, title: String, currentValue: String, onValueChange: (String) -> Unit) {
+fun SessionTime(
+ modifier: Modifier = Modifier,
+ title: String,
+ currentValue: String,
+ onValueChange: (String) -> Unit,
+) {
BloomInputTextField(
modifier = modifier,
textStyle = MaterialTheme.typography.bodyMedium.copy(
- textAlign = TextAlign.Start
+ textAlign = TextAlign.Start,
),
label = {
Text(
text = title,
style = MaterialTheme.typography.labelLarge.copy(
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
},
value = TextFieldState(currentValue),
onValueChange = onValueChange,
keyboardOptions = KeyboardOptions.Default.copy(
- keyboardType = KeyboardType.Number
- )
+ keyboardType = KeyboardType.Number,
+ ),
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun SettingCard(title: String, icon: ImageVector, modifier: Modifier = Modifier, content: @Composable () -> Unit, onExpand: () -> Unit, expanded: Boolean) {
+fun SettingCard(
+ title: String,
+ icon: ImageVector,
+ modifier: Modifier = Modifier,
+ content: @Composable () -> Unit,
+ onExpand: () -> Unit,
+ expanded: Boolean,
+) {
Card(
modifier = modifier,
onClick = {
onExpand()
- }
+ },
) {
Column(
- modifier = modifier.padding(16.dp)
+ modifier = modifier.padding(16.dp),
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(12.dp)
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Icon(
imageVector = icon,
- contentDescription = title
+ contentDescription = title,
)
Text(
text = title,
- style = MaterialTheme.typography.titleLarge
+ style = MaterialTheme.typography.titleLarge,
)
}
@@ -664,7 +701,7 @@ fun SettingCard(title: String, icon: ImageVector, modifier: Modifier = Modifier,
} else {
Icons.Rounded.KeyboardArrowDown
},
- contentDescription = null
+ contentDescription = null,
)
}
}
@@ -679,22 +716,29 @@ fun SettingCard(title: String, icon: ImageVector, modifier: Modifier = Modifier,
}
@Composable
-fun ColorsSelection(onSelectSessionColor: (Long) -> Unit, onSelectShortBreakColor: (Long) -> Unit, onSelectLongBreakColor: (Long) -> Unit, currentSessionColor: Long, currentShortBreakColor: Long, currentLongBreakColor: Long) {
+fun ColorsSelection(
+ onSelectSessionColor: (Long) -> Unit,
+ onSelectShortBreakColor: (Long) -> Unit,
+ onSelectLongBreakColor: (Long) -> Unit,
+ currentSessionColor: Long,
+ currentShortBreakColor: Long,
+ currentLongBreakColor: Long,
+) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
ColorCard(
color = currentSessionColor,
- onClick = onSelectSessionColor
+ onClick = onSelectSessionColor,
)
ColorCard(
color = currentShortBreakColor,
- onClick = onSelectShortBreakColor
+ onClick = onSelectShortBreakColor,
)
ColorCard(
color = currentLongBreakColor,
- onClick = onSelectLongBreakColor
+ onClick = onSelectLongBreakColor,
)
}
}
@@ -708,12 +752,17 @@ fun ColorCard(modifier: Modifier = Modifier, color: Long, onClick: (Long) -> Uni
.background(Color(color))
.clickable {
onClick(color)
- }
+ },
)
}
@Composable
-fun ColorsDialog(modifier: Modifier = Modifier, onDismiss: () -> Unit, onSelectColor: (Long) -> Unit, title: String) {
+fun ColorsDialog(
+ modifier: Modifier = Modifier,
+ onDismiss: () -> Unit,
+ onSelectColor: (Long) -> Unit,
+ title: String,
+) {
AlertDialog(
modifier = modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.large,
@@ -725,14 +774,14 @@ fun ColorsDialog(modifier: Modifier = Modifier, onDismiss: () -> Unit, onSelectC
modifier = Modifier.fillMaxWidth(),
text = title,
style = MaterialTheme.typography.titleMedium.copy(
- textAlign = TextAlign.Center
- )
+ textAlign = TextAlign.Center,
+ ),
)
},
text = {
LazyVerticalGrid(
columns = GridCells.Fixed(4),
- verticalArrangement = Arrangement.spacedBy(8.dp)
+ verticalArrangement = Arrangement.spacedBy(8.dp),
) {
items(sessionColors) {
ColorCard(
@@ -740,13 +789,13 @@ fun ColorsDialog(modifier: Modifier = Modifier, onDismiss: () -> Unit, onSelectC
.padding(horizontal = 4.dp)
.size(48.dp),
color = it,
- onClick = onSelectColor
+ onClick = onSelectColor,
)
}
}
},
dismissButton = {},
- confirmButton = {}
+ confirmButton = {},
)
}
@@ -762,7 +811,7 @@ private val sessionColors = listOf(
LightGreen,
Yellow,
LightBlue,
- Pink
+ Pink,
)
/**
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/settings/SettingsScreenModel.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/settings/SettingsScreenModel.kt
index aa72c77..9db73f9 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/settings/SettingsScreenModel.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/settings/SettingsScreenModel.kt
@@ -17,7 +17,7 @@ package com.joelkanyi.focusbloom.feature.settings
import androidx.compose.runtime.mutableStateListOf
import cafe.adriel.voyager.core.model.ScreenModel
-import cafe.adriel.voyager.core.model.coroutineScope
+import cafe.adriel.voyager.core.model.screenModelScope
import com.joelkanyi.focusbloom.core.domain.repository.settings.SettingsRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -28,7 +28,7 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
class SettingsScreenModel(
- private val settingsRepository: SettingsRepository
+ private val settingsRepository: SettingsRepository,
) : ScreenModel {
private val _selectedColorCardTitle = MutableStateFlow("")
val selectedColorCardTitle = _selectedColorCardTitle.asStateFlow()
@@ -50,13 +50,13 @@ class SettingsScreenModel(
val appTheme: StateFlow = settingsRepository.getAppTheme()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
fun setAppTheme(appTheme: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveAppTheme(appTheme)
}
}
@@ -66,13 +66,13 @@ class SettingsScreenModel(
it
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
fun setSessionTime(sessionTime: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveSessionTime(sessionTime)
}
}
@@ -80,13 +80,13 @@ class SettingsScreenModel(
val shortBreakTime = settingsRepository.getShortBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
fun setShortBreakTime(shortBreakTime: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveShortBreakTime(shortBreakTime)
}
}
@@ -94,13 +94,13 @@ class SettingsScreenModel(
val longBreakTime = settingsRepository.getLongBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
fun setLongBreakTime(longBreakTime: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveLongBreakTime(longBreakTime)
}
}
@@ -108,31 +108,31 @@ class SettingsScreenModel(
val timeFormat = settingsRepository.getHourFormat()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
fun setHourFormat(timeFormat: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveHourFormat(timeFormat)
}
}
fun setShortBreakColor(color: Long) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveShortBreakColor(color)
}
}
fun setLongBreakColor(color: Long) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveLongBreakColor(color)
}
}
fun setFocusColor(color: Long) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.saveFocusColor(color)
}
}
@@ -148,37 +148,37 @@ class SettingsScreenModel(
it
}
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val longBreakColor = settingsRepository.longBreakColor()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val focusColor = settingsRepository.focusColor()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val remindersOn = settingsRepository.remindersOn()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = false
+ initialValue = false,
)
fun setReminders(value: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.toggleReminder(value)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/AllStatisticsScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/AllStatisticsScreen.kt
index b4b39fe..1088bc8 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/AllStatisticsScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/AllStatisticsScreen.kt
@@ -45,6 +45,7 @@ import com.joelkanyi.focusbloom.core.presentation.component.BloomTopAppBar
import com.joelkanyi.focusbloom.core.utils.prettyFormat
import com.joelkanyi.focusbloom.platform.StatusBarColors
import kotlinx.datetime.LocalDate
+import org.koin.compose.rememberKoinInject
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
@@ -52,10 +53,10 @@ class AllStatisticsScreen : Screen, KoinComponent {
@Composable
override fun Content() {
- val screenModel = get()
+ val screenModel = rememberKoinInject()
StatusBarColors(
statusBarColor = MaterialTheme.colorScheme.background,
- navBarColor = MaterialTheme.colorScheme.background
+ navBarColor = MaterialTheme.colorScheme.background,
)
val navigator = LocalNavigator.currentOrThrow
val hourFormat = screenModel.hourFormat.collectAsState().value ?: 24
@@ -84,7 +85,7 @@ class AllStatisticsScreen : Screen, KoinComponent {
},
onClickCancel = {
screenModel.openTaskOptions(it)
- }
+ },
)
}
}
@@ -101,7 +102,7 @@ fun AllStatisticsScreenContent(
onClickDelete: (task: Task) -> Unit,
onClickCancel: (task: Task) -> Unit,
showTaskOption: (task: Task) -> Boolean,
- onShowTaskOption: (task: Task) -> Unit
+ onShowTaskOption: (task: Task) -> Unit,
) {
Scaffold(
topBar = {
@@ -111,20 +112,20 @@ fun AllStatisticsScreenContent(
IconButton(onClick = onClickNavigateBack) {
Icon(
imageVector = Icons.Outlined.ArrowBack,
- contentDescription = "Back"
+ contentDescription = "Back",
)
}
- }
+ },
) {
Text(text = "Tasks History")
}
- }
+ },
) { paddingValues ->
LazyColumn(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize(),
- contentPadding = PaddingValues(horizontal = 16.dp)
+ contentPadding = PaddingValues(horizontal = 16.dp),
) {
tasks.forEach { (date, tasks) ->
stickyHeader {
@@ -136,13 +137,13 @@ fun AllStatisticsScreenContent(
text = date.prettyFormat(),
style = MaterialTheme.typography.titleMedium.copy(
fontWeight = FontWeight.Bold,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
items(
items = tasks,
- key = { it.id }
+ key = { it.id },
) {
HistoryCard(
modifier = Modifier
@@ -156,7 +157,7 @@ fun AllStatisticsScreenContent(
onClickDelete = onClickDelete,
onClickCancel = onClickCancel,
showTaskOption = showTaskOption,
- onShowTaskOption = onShowTaskOption
+ onShowTaskOption = onShowTaskOption,
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/StatisticsScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/StatisticsScreen.kt
index b1c1d52..0ce6d1e 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/StatisticsScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/StatisticsScreen.kt
@@ -64,10 +64,10 @@ import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import com.joelkanyi.focusbloom.core.domain.model.Task
import com.joelkanyi.focusbloom.core.presentation.component.BloomTopAppBar
-import com.joelkanyi.focusbloom.core.utils.LocalAppNavigator
import com.joelkanyi.focusbloom.core.utils.calculateEndTime
import com.joelkanyi.focusbloom.core.utils.completedTasks
import com.joelkanyi.focusbloom.core.utils.durationInMinutes
@@ -79,24 +79,26 @@ import com.joelkanyi.focusbloom.core.utils.taskIcon
import com.joelkanyi.focusbloom.feature.statistics.component.BarChart
import com.joelkanyi.focusbloom.feature.statistics.component.TickPositionState
import com.joelkanyi.focusbloom.platform.StatusBarColors
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.redo
import io.github.koalaplot.core.ChartLayout
import io.github.koalaplot.core.util.ExperimentalKoalaPlotApi
import io.github.koalaplot.core.xychart.TickPosition
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
-import org.koin.compose.rememberKoinInject
+import org.koin.compose.koinInject
@OptIn(ExperimentalFoundationApi::class)
@Composable
-fun StatisticsScreen() {
- val screenModel: StatisticsScreenModel = rememberKoinInject()
-
+fun StatisticsScreen(
+ screenModel: StatisticsScreenModel = koinInject(),
+) {
StatusBarColors(
statusBarColor = MaterialTheme.colorScheme.background,
- navBarColor = MaterialTheme.colorScheme.background
+ navBarColor = MaterialTheme.colorScheme.background,
)
- val navigator = LocalAppNavigator.currentOrThrow
+ val navigator = LocalNavigator.currentOrThrow
val tasksHistory = screenModel.tasks.collectAsState().value
val lastFiftyTwoWeeks = getLast52Weeks().asReversed()
val hourFormat = screenModel.hourFormat.collectAsState().value ?: 24
@@ -109,18 +111,18 @@ fun StatisticsScreen() {
initialPageOffsetFraction = 0f,
pageCount = {
lastFiftyTwoWeeks.size
- }
+ },
)
val selectedWeek = lastFiftyTwoWeeks[pagerState.currentPage].first
val selectedWeekTasks = tasksHistory.completedTasks(
- lastFiftyTwoWeeks[pagerState.currentPage].second
+ lastFiftyTwoWeeks[pagerState.currentPage].second,
).map { it.toFloat() }
val tickPositionState by remember {
mutableStateOf(
TickPositionState(
TickPosition.Outside,
- TickPosition.Outside
- )
+ TickPosition.Outside,
+ ),
)
}
@@ -135,7 +137,7 @@ fun StatisticsScreen() {
selectedWeekTasks = selectedWeekTasks,
tasksHistory = tasksHistory,
onClickSeeAllTasks = {
- navigator.push(AllStatisticsScreen())
+ navigator.parent?.push(AllStatisticsScreen())
},
onClickThisWeek = {
coroutineScope.launch {
@@ -163,7 +165,7 @@ fun StatisticsScreen() {
},
onClickCancel = {
screenModel.openTaskOptions(it)
- }
+ },
)
}
@@ -171,7 +173,6 @@ fun StatisticsScreen() {
ExperimentalKoalaPlotApi::class,
ExperimentalMaterial3Api::class,
ExperimentalFoundationApi::class,
- ExperimentalResourceApi::class
)
@Composable
fun StatisticsScreenContent(
@@ -191,7 +192,7 @@ fun StatisticsScreenContent(
onClickDelete: (task: Task) -> Unit,
onClickCancel: (task: Task) -> Unit,
showTaskOption: (task: Task) -> Boolean,
- onShowTaskOption: (task: Task) -> Unit
+ onShowTaskOption: (task: Task) -> Unit,
) {
Scaffold(
topBar = {
@@ -203,64 +204,64 @@ fun StatisticsScreenContent(
text = "Your Statistics",
style = MaterialTheme.typography.displaySmall.copy(
fontSize = 18.sp,
- fontWeight = FontWeight.Bold
- )
+ fontWeight = FontWeight.Bold,
+ ),
)
},
actions = {
AnimatedVisibility(selectedWeek != "This Week") {
TextButton(
- onClick = onClickThisWeek
+ onClick = onClickThisWeek,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(4.dp)
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
Icon(
modifier = Modifier.size(18.dp),
- painter = painterResource("redo.xml"),
- contentDescription = "This Week"
+ painter = painterResource(Res.drawable.redo),
+ contentDescription = "This Week",
)
Text(
text = "This Week",
style = MaterialTheme.typography.labelLarge.copy(
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.primary,
- textDecoration = TextDecoration.Underline
- )
+ textDecoration = TextDecoration.Underline,
+ ),
)
}
}
}
- }
+ },
)
- }
+ },
) { paddingValues ->
LazyColumn(
modifier = Modifier.padding(paddingValues),
- contentPadding = PaddingValues(horizontal = 16.dp)
+ contentPadding = PaddingValues(horizontal = 16.dp),
) {
item {
WeeksController(
onClickPreviousWeek = onClickPreviousWeek,
selectedWeek = selectedWeek,
- onClickNextWeek = onClickNextWeek
+ onClickNextWeek = onClickNextWeek,
)
}
item {
HorizontalPager(
state = pagerState,
modifier = Modifier
- .fillMaxWidth()
+ .fillMaxWidth(),
) {
ChartLayout(
modifier = Modifier
.fillMaxWidth()
- .sizeIn(maxHeight = 300.dp)
+ .sizeIn(maxHeight = 300.dp),
) {
BarChart(
tickPositionState = tickPositionState,
- entries = selectedWeekTasks
+ entries = selectedWeekTasks,
)
}
}
@@ -271,13 +272,13 @@ fun StatisticsScreenContent(
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = "Your History",
style = MaterialTheme.typography.titleLarge.copy(
- fontWeight = FontWeight.Bold
- )
+ fontWeight = FontWeight.Bold,
+ ),
)
if (tasksHistory.size > 3) {
TextButton(onClick = onClickSeeAllTasks) {
@@ -286,8 +287,8 @@ fun StatisticsScreenContent(
style = MaterialTheme.typography.labelLarge.copy(
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.primary,
- fontSize = 16.sp
- )
+ fontSize = 16.sp,
+ ),
)
}
}
@@ -304,13 +305,13 @@ fun StatisticsScreenContent(
style = MaterialTheme.typography.titleMedium.copy(
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
- textAlign = TextAlign.End
- )
+ textAlign = TextAlign.End,
+ ),
)
}
items(
items = tasks,
- key = { it.id }
+ key = { it.id },
) {
HistoryCard(
modifier = Modifier
@@ -324,7 +325,7 @@ fun StatisticsScreenContent(
onClickDelete = onClickDelete,
onClickCancel = onClickCancel,
showTaskOption = showTaskOption,
- onShowTaskOption = onShowTaskOption
+ onShowTaskOption = onShowTaskOption,
)
}
}
@@ -333,27 +334,31 @@ fun StatisticsScreenContent(
}
@Composable
-private fun WeeksController(onClickPreviousWeek: () -> Unit, selectedWeek: String, onClickNextWeek: () -> Unit) {
+private fun WeeksController(
+ onClickPreviousWeek: () -> Unit,
+ selectedWeek: String,
+ onClickNextWeek: () -> Unit,
+) {
Row(
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
IconButton(
modifier = Modifier.size(24.dp),
- onClick = onClickPreviousWeek
+ onClick = onClickPreviousWeek,
) {
Icon(
imageVector = Icons.Default.KeyboardDoubleArrowLeft,
- contentDescription = "Previous Week"
+ contentDescription = "Previous Week",
)
}
Text(
text = selectedWeek,
style = MaterialTheme.typography.titleLarge.copy(
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
IconButton(
modifier = Modifier.size(24.dp),
@@ -361,7 +366,7 @@ private fun WeeksController(onClickPreviousWeek: () -> Unit, selectedWeek: Strin
if (selectedWeek != "This Week") {
onClickNextWeek()
}
- }
+ },
) {
Icon(
imageVector = Icons.Default.KeyboardDoubleArrowRight,
@@ -370,7 +375,7 @@ private fun WeeksController(onClickPreviousWeek: () -> Unit, selectedWeek: Strin
MaterialTheme.colorScheme.onBackground
} else {
MaterialTheme.colorScheme.onBackground.copy(alpha = 0.3f)
- }
+ },
)
}
}
@@ -378,15 +383,26 @@ private fun WeeksController(onClickPreviousWeek: () -> Unit, selectedWeek: Strin
@OptIn(ExperimentalResourceApi::class)
@Composable
-fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sessionTime: Int, shortBreakTime: Int, longBreakTime: Int, onClickCancel: (task: Task) -> Unit, onClickDelete: (task: Task) -> Unit, showTaskOption: (task: Task) -> Boolean, onShowTaskOption: (task: Task) -> Unit) {
+fun HistoryCard(
+ task: Task,
+ modifier: Modifier = Modifier,
+ hourFormat: Int,
+ sessionTime: Int,
+ shortBreakTime: Int,
+ longBreakTime: Int,
+ onClickCancel: (task: Task) -> Unit,
+ onClickDelete: (task: Task) -> Unit,
+ showTaskOption: (task: Task) -> Boolean,
+ onShowTaskOption: (task: Task) -> Unit,
+) {
Column {
Card(
- modifier = modifier
+ modifier = modifier,
) {
Row(
modifier = Modifier.padding(12.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
Box(
modifier = Modifier
@@ -394,9 +410,9 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
.clip(MaterialTheme.shapes.large)
.background(
color = Color(task.type.taskColor()),
- shape = MaterialTheme.shapes.medium
+ shape = MaterialTheme.shapes.medium,
),
- contentAlignment = Alignment.Center
+ contentAlignment = Alignment.Center,
) {
Icon(
modifier = Modifier
@@ -404,27 +420,27 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
.size(24.dp),
painter = painterResource(task.type.taskIcon()),
contentDescription = "Task Icon",
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
}
Column(
modifier = Modifier.fillMaxWidth(),
- verticalArrangement = Arrangement.spacedBy(4.dp)
+ verticalArrangement = Arrangement.spacedBy(4.dp),
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
Text(
modifier = Modifier.fillMaxWidth(.8f),
text = task.name,
style = MaterialTheme.typography.titleSmall.copy(
fontWeight = FontWeight.SemiBold,
- fontSize = 14.sp
+ fontSize = 14.sp,
),
maxLines = 2,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
)
Icon(
modifier = Modifier
@@ -433,7 +449,7 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
onShowTaskOption(task)
},
imageVector = Icons.Default.MoreVert,
- contentDescription = "More Options"
+ contentDescription = "More Options",
)
}
if (task.description != null) {
@@ -441,13 +457,13 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
text = task.description,
style = MaterialTheme.typography.bodyMedium,
maxLines = 3,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
)
}
Spacer(modifier = Modifier.height(8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = "${
@@ -455,13 +471,13 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
focusSessions = task.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
)
} minutes",
style = MaterialTheme.typography.displaySmall.copy(
fontSize = 12.sp,
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
Text(
prettyTimeDifference(
@@ -470,14 +486,14 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
focusSessions = task.focusSessions,
sessionTime = sessionTime,
shortBreakTime = shortBreakTime,
- longBreakTime = longBreakTime
+ longBreakTime = longBreakTime,
),
- timeFormat = hourFormat
+ timeFormat = hourFormat,
),
style = MaterialTheme.typography.displaySmall.copy(
fontSize = 12.sp,
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
}
}
@@ -489,7 +505,7 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
) {
TextButton(onClick = {
onClickCancel(task)
@@ -497,8 +513,8 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
Text(
text = "Cancel",
style = MaterialTheme.typography.labelLarge.copy(
- fontWeight = FontWeight.SemiBold
- )
+ fontWeight = FontWeight.SemiBold,
+ ),
)
}
Spacer(modifier = Modifier.width(16.dp))
@@ -509,8 +525,8 @@ fun HistoryCard(task: Task, modifier: Modifier = Modifier, hourFormat: Int, sess
text = "Delete",
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.labelLarge.copy(
- fontWeight = FontWeight.ExtraBold
- )
+ fontWeight = FontWeight.ExtraBold,
+ ),
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/StatisticsScreenModel.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/StatisticsScreenModel.kt
index 74dde16..a3cfe65 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/StatisticsScreenModel.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/StatisticsScreenModel.kt
@@ -17,7 +17,7 @@ package com.joelkanyi.focusbloom.feature.statistics
import androidx.compose.runtime.mutableStateListOf
import cafe.adriel.voyager.core.model.ScreenModel
-import cafe.adriel.voyager.core.model.coroutineScope
+import cafe.adriel.voyager.core.model.screenModelScope
import com.joelkanyi.focusbloom.core.domain.model.Task
import com.joelkanyi.focusbloom.core.domain.repository.settings.SettingsRepository
import com.joelkanyi.focusbloom.core.domain.repository.tasks.TasksRepository
@@ -28,16 +28,16 @@ import kotlinx.coroutines.launch
class StatisticsScreenModel(
private val tasksRepository: TasksRepository,
- settingsRepository: SettingsRepository
+ settingsRepository: SettingsRepository,
) : ScreenModel {
val hourFormat = settingsRepository.getHourFormat()
.map {
it
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val sessionTime = settingsRepository.getSessionTime()
@@ -45,23 +45,23 @@ class StatisticsScreenModel(
it
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val shortBreakTime = settingsRepository.getShortBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val longBreakTime = settingsRepository.getLongBreakTime()
.map { it }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val tasks = tasksRepository.getTasks()
@@ -72,13 +72,13 @@ class StatisticsScreenModel(
}
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = emptyList()
+ initialValue = emptyList(),
)
fun deleteTask(task: Task) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.deleteTask(task.id)
}
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/component/StatisticsChart.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/component/StatisticsChart.kt
index 7d1c9f8..db40395 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/component/StatisticsChart.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/statistics/component/StatisticsChart.kt
@@ -54,7 +54,7 @@ fun AxisTitle(title: String, modifier: Modifier = Modifier) {
title,
color = MaterialTheme.colorScheme.onBackground,
style = MaterialTheme.typography.titleMedium,
- modifier = modifier
+ modifier = modifier,
)
}
@@ -66,7 +66,7 @@ fun AxisLabel(label: String, modifier: Modifier = Modifier) {
style = MaterialTheme.typography.bodySmall,
modifier = modifier,
overflow = TextOverflow.Ellipsis,
- maxLines = 1
+ maxLines = 1,
)
}
@@ -77,8 +77,8 @@ fun barChartEntries(fibonacci: List): List> {
DefaultBarChartEntry(
xValue = (index + 1).toFloat(),
yMin = 0f,
- yMax = fl
- )
+ yMax = fl,
+ ),
)
}
}
@@ -91,7 +91,7 @@ fun BarChart(tickPositionState: TickPositionState, entries: List) {
val xAxisRange = 0.5f..7.5f
ChartLayout(
modifier = paddingMod,
- title = { }
+ title = { },
) {
XYChart(
xAxisModel = LinearAxisModel(
@@ -99,16 +99,16 @@ fun BarChart(tickPositionState: TickPositionState, entries: List) {
minimumMajorTickIncrement = 1f,
minimumMajorTickSpacing = 10.dp,
zoomRangeLimit = 3f,
- minorTickCount = 0
+ minorTickCount = 0,
),
yAxisModel = LinearAxisModel(
yAxisRange,
minimumMajorTickIncrement = 1f,
- minorTickCount = 0
+ minorTickCount = 0,
),
xAxisStyle = rememberAxisStyle(
tickPosition = tickPositionState.horizontalAxis,
- color = Color.LightGray
+ color = Color.LightGray,
),
xAxisLabels = {
AxisLabel(
@@ -122,13 +122,13 @@ fun BarChart(tickPositionState: TickPositionState, entries: List) {
7f -> "Sun"
else -> ""
},
- Modifier.padding(top = 2.dp)
+ Modifier.padding(top = 2.dp),
)
},
xAxisTitle = {
AxisTitle(
"Day of the Week",
- modifier = Modifier.padding(top = 8.dp)
+ modifier = Modifier.padding(top = 8.dp),
)
},
yAxisStyle = rememberAxisStyle(tickPosition = tickPositionState.verticalAxis),
@@ -139,25 +139,25 @@ fun BarChart(tickPositionState: TickPositionState, entries: List) {
AxisTitle(
"Tasks Completed",
modifier = Modifier.rotateVertically(VerticalRotation.COUNTER_CLOCKWISE)
- .padding(bottom = padding)
+ .padding(bottom = padding),
)
},
- verticalMajorGridLineStyle = null
+ verticalMajorGridLineStyle = null,
) {
VerticalBarChart(
series = listOf(
barChartEntries(
- fibonacci = entries
- )
+ fibonacci = entries,
+ ),
),
bar = { _, _, value ->
DefaultVerticalBar(
brush = SolidColor(MaterialTheme.colorScheme.primary),
- modifier = Modifier.fillMaxWidth(BarWidth)
+ modifier = Modifier.fillMaxWidth(BarWidth),
) {
HoverSurface { Text(value.yMax.toString()) }
}
- }
+ },
)
}
}
@@ -165,7 +165,7 @@ fun BarChart(tickPositionState: TickPositionState, entries: List) {
data class TickPositionState(
val verticalAxis: TickPosition,
- val horizontalAxis: TickPosition
+ val horizontalAxis: TickPosition,
)
@Composable
@@ -174,7 +174,7 @@ fun HoverSurface(modifier: Modifier = Modifier, content: @Composable () -> Unit)
shadowElevation = 2.dp,
shape = MaterialTheme.shapes.medium,
color = Color.LightGray,
- modifier = modifier.padding(padding)
+ modifier = modifier.padding(padding),
) {
Box(modifier = Modifier.padding(padding)) {
content()
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/taskprogress/TaskProgressScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/taskprogress/TaskProgressScreen.kt
index 08b42eb..5f2381c 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/taskprogress/TaskProgressScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/taskprogress/TaskProgressScreen.kt
@@ -76,6 +76,8 @@ import com.joelkanyi.focusbloom.core.utils.toMinutes
import com.joelkanyi.focusbloom.core.utils.toPercentage
import com.joelkanyi.focusbloom.core.utils.toTimer
import com.joelkanyi.focusbloom.platform.StatusBarColors
+import focusbloom.shared.generated.resources.Res
+import focusbloom.shared.generated.resources.ic_complete
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jetbrains.compose.resources.ExperimentalResourceApi
@@ -84,7 +86,7 @@ import org.koin.core.component.KoinComponent
import org.koin.core.component.get
data class TaskProgressScreen(
- val taskId: Int
+ val taskId: Int,
) : Screen, KoinComponent {
@Composable
@@ -108,7 +110,7 @@ data class TaskProgressScreen(
Color(SessionColor)
} else {
Color(
- focusColor
+ focusColor,
)
}
}
@@ -118,7 +120,7 @@ data class TaskProgressScreen(
Color(LongBreakColor)
} else {
Color(
- longBreakColor
+ longBreakColor,
)
}
}
@@ -128,14 +130,14 @@ data class TaskProgressScreen(
Color(ShortBreakColor)
} else {
Color(
- shortBreakColor
+ shortBreakColor,
)
}
}
}
StatusBarColors(
statusBarColor = containerColor,
- navBarColor = containerColor
+ navBarColor = containerColor,
)
LaunchedEffect(key1 = Unit) {
screenModel.getRemindersStatus()
@@ -160,7 +162,7 @@ data class TaskProgressScreen(
onConfirm = {
Timer.reset()
navigator.pop()
- }
+ },
)
}
@@ -203,7 +205,7 @@ data class TaskProgressScreen(
},
executeTasks = {
screenModel.executeTasks()
- }
+ },
)
screenModel.resetAllTasksToInactive()
screenModel.updateActiveTask(taskId, true)
@@ -213,7 +215,7 @@ data class TaskProgressScreen(
// screenModel.setTime(task?.focusTime ?: 20)
}
}
- }
+ },
)
}
}
@@ -232,7 +234,7 @@ fun FocusTimeScreenContent(
onClickNavigateBack: () -> Unit,
onClickAction: (state: TimerState) -> Unit,
onClickNext: () -> Unit,
- onClickReset: () -> Unit
+ onClickReset: () -> Unit,
) {
Scaffold(
containerColor = containerColor,
@@ -247,48 +249,48 @@ fun FocusTimeScreenContent(
Icon(
imageVector = Icons.Outlined.ArrowBack,
contentDescription = "Add Task Back Button",
- tint = MaterialTheme.colorScheme.onPrimary
+ tint = MaterialTheme.colorScheme.onPrimary,
)
}
},
colors = TopAppBarDefaults.topAppBarColors(
- containerColor = containerColor
- )
+ containerColor = containerColor,
+ ),
)
- }
+ },
) { paddingValues ->
Box(
- modifier = Modifier.padding(paddingValues).fillMaxSize()
+ modifier = Modifier.padding(paddingValues).fillMaxSize(),
) {
if (task == null) {
Text(
modifier = Modifier.align(Alignment.Center),
- text = "Task not found"
+ text = "Task not found",
)
} else {
LazyColumn(
- modifier = Modifier.padding(PaddingValues(horizontal = 16.dp))
+ modifier = Modifier.padding(PaddingValues(horizontal = 16.dp)),
) {
item {
Card(
- modifier = Modifier.fillMaxWidth()
+ modifier = Modifier.fillMaxWidth(),
) {
Column(
modifier = Modifier
.fillMaxWidth()
- .padding(12.dp)
+ .padding(12.dp),
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
modifier = Modifier.fillMaxWidth(.85f),
text = task.name,
style = MaterialTheme.typography.titleSmall,
maxLines = 3,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
)
Text(
@@ -296,19 +298,19 @@ fun FocusTimeScreenContent(
withStyle(
style = SpanStyle(
fontWeight = FontWeight.SemiBold,
- fontSize = 18.sp
- )
+ fontSize = 18.sp,
+ ),
) {
append("${task.currentCycle}")
}
append("/${task.focusSessions}")
- }
+ },
)
}
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceBetween
+ horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = "Total: ${
@@ -316,17 +318,17 @@ fun FocusTimeScreenContent(
sessionTime = focusTime.toMinutes(),
shortBreakTime = shortBreakTime.toMinutes(),
longBreakTime = longBreakTime.toMinutes(),
- focusSessions = task.focusSessions
+ focusSessions = task.focusSessions,
)
} minutes",
- style = MaterialTheme.typography.bodySmall
+ style = MaterialTheme.typography.bodySmall,
)
Text(
text = when (task.current.sessionType()) {
SessionType.Focus -> "${focusTime.toMinutes()} min"
SessionType.ShortBreak -> "${shortBreakTime.toMinutes()} min"
SessionType.LongBreak -> "${longBreakTime.toMinutes()} min"
- }
+ },
)
}
}
@@ -337,7 +339,7 @@ fun FocusTimeScreenContent(
Spacer(modifier = Modifier.height(32.dp))
Row(
modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.Center
+ horizontalArrangement = Arrangement.Center,
) {
TaskProgress(
percentage = timerValue.toPercentage(
@@ -345,12 +347,12 @@ fun FocusTimeScreenContent(
SessionType.Focus -> focusTime
SessionType.ShortBreak -> shortBreakTime
SessionType.LongBreak -> longBreakTime
- }
+ },
),
radius = 40.dp,
content = timerValue.toTimer(),
mainColor = MaterialTheme.colorScheme.primary,
- counterColor = MaterialTheme.colorScheme.onPrimary
+ counterColor = MaterialTheme.colorScheme.onPrimary,
)
}
}
@@ -365,9 +367,9 @@ fun FocusTimeScreenContent(
SessionType.LongBreak -> "Long Break"
},
style = MaterialTheme.typography.displaySmall.copy(
- color = MaterialTheme.colorScheme.onPrimary
+ color = MaterialTheme.colorScheme.onPrimary,
),
- textAlign = TextAlign.Center
+ textAlign = TextAlign.Center,
)
}
@@ -378,7 +380,7 @@ fun FocusTimeScreenContent(
state = timerState,
onClickReset = onClickReset,
onClickNext = onClickNext,
- onClickAction = onClickAction
+ onClickAction = onClickAction,
)
}
}
@@ -389,15 +391,21 @@ fun FocusTimeScreenContent(
@OptIn(ExperimentalResourceApi::class)
@Composable
-fun SuccessfulCompletionOfTask(modifier: Modifier = Modifier, title: String, message: String, onConfirm: () -> Unit) {
+fun SuccessfulCompletionOfTask(
+ modifier: Modifier = Modifier,
+ title: String,
+ message: String,
+ onConfirm: () -> Unit,
+) {
AlertDialog(
modifier = modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.large,
icon = {
Image(
modifier = Modifier.size(48.dp),
- painter = painterResource("ic_complete.xml"),
- contentDescription = "Task Completed"
+ painter = painterResource(
+ Res.drawable.ic_complete),
+ contentDescription = "Task Completed",
)
},
containerColor = MaterialTheme.colorScheme.background,
@@ -407,8 +415,8 @@ fun SuccessfulCompletionOfTask(modifier: Modifier = Modifier, title: String, mes
modifier = Modifier.fillMaxWidth(),
text = title,
style = MaterialTheme.typography.titleMedium.copy(
- textAlign = TextAlign.Center
- )
+ textAlign = TextAlign.Center,
+ ),
)
},
text = {
@@ -416,21 +424,21 @@ fun SuccessfulCompletionOfTask(modifier: Modifier = Modifier, title: String, mes
modifier = Modifier.fillMaxWidth(),
text = message,
style = MaterialTheme.typography.bodyMedium.copy(
- textAlign = TextAlign.Center
- )
+ textAlign = TextAlign.Center,
+ ),
)
},
dismissButton = {},
confirmButton = {
Button(
modifier = Modifier.fillMaxWidth(),
- onClick = onConfirm
+ onClick = onConfirm,
) {
Text(
text = "OK",
- style = MaterialTheme.typography.titleSmall
+ style = MaterialTheme.typography.titleSmall,
)
}
- }
+ },
)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/taskprogress/TaskProgressScreenModel.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/taskprogress/TaskProgressScreenModel.kt
index eab87b9..9598ecf 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/taskprogress/TaskProgressScreenModel.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/feature/taskprogress/TaskProgressScreenModel.kt
@@ -16,7 +16,7 @@
package com.joelkanyi.focusbloom.feature.taskprogress
import cafe.adriel.voyager.core.model.ScreenModel
-import cafe.adriel.voyager.core.model.coroutineScope
+import cafe.adriel.voyager.core.model.screenModelScope
import com.joelkanyi.focusbloom.core.domain.model.SessionType
import com.joelkanyi.focusbloom.core.domain.model.Task
import com.joelkanyi.focusbloom.core.domain.repository.settings.SettingsRepository
@@ -36,30 +36,30 @@ import kotlinx.coroutines.launch
class TaskProgressScreenModel(
private val settingsRepository: SettingsRepository,
private val tasksRepository: TasksRepository,
- private val notificationManager: NotificationsManager
+ private val notificationManager: NotificationsManager,
) : ScreenModel {
val shortBreakColor = settingsRepository.shortBreakColor()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val longBreakColor = settingsRepository.longBreakColor()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val focusColor = settingsRepository.focusColor()
.map { it }
.stateIn(
- coroutineScope,
+ screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val focusTime = settingsRepository.getSessionTime()
@@ -67,31 +67,31 @@ class TaskProgressScreenModel(
it?.toMillis() ?: (25).toMillis()
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val shortBreakTime = settingsRepository.getShortBreakTime()
.map {
it?.toMillis() ?: (5).toMillis()
}
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
val longBreakTime = settingsRepository.getLongBreakTime()
.map { it?.toMillis() ?: (15).toMillis() }
.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(5_000),
- initialValue = null
+ initialValue = null,
)
private val _remindersOn = MutableStateFlow(null)
- val remindersOn = _remindersOn.asStateFlow()
+ private val remindersOn = _remindersOn.asStateFlow()
fun getRemindersStatus() {
- coroutineScope.launch {
+ screenModelScope.launch {
settingsRepository.remindersOn().collectLatest {
_remindersOn.value = it == 1
}
@@ -101,7 +101,7 @@ class TaskProgressScreenModel(
private val _task = MutableStateFlow(null)
val task = _task.asStateFlow()
fun getTask(taskId: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.getTask(taskId).collectLatest {
_task.value = it
}
@@ -114,7 +114,7 @@ class TaskProgressScreenModel(
* @param consumedTime the consumed time of the focus
*/
private fun updateConsumedFocusTime(taskId: Int, consumedTime: Long) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateConsumedFocusTime(taskId, consumedTime)
}
}
@@ -125,7 +125,7 @@ class TaskProgressScreenModel(
* @param consumedTime the consumed time of the short break
*/
private fun updateConsumedShortBreakTime(taskId: Int, consumedTime: Long) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateConsumedShortBreakTime(taskId, consumedTime)
}
}
@@ -136,7 +136,7 @@ class TaskProgressScreenModel(
* @param consumedTime the consumed time of the long break
*/
private fun updateConsumedLongBreakTime(taskId: Int, consumedTime: Long) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateConsumedLongBreakTime(taskId, consumedTime)
}
}
@@ -147,13 +147,13 @@ class TaskProgressScreenModel(
* @param inProgressTask the in progress task
*/
private fun updateInProgressTask(taskId: Int, inProgressTask: Boolean) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTaskInProgress(taskId, inProgressTask)
}
}
fun updateActiveTask(taskId: Int, activeTask: Boolean) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTaskActive(id = taskId, active = activeTask)
}
}
@@ -164,13 +164,13 @@ class TaskProgressScreenModel(
* @param completedTask the completed task
*/
private fun updateCompletedTask(taskId: Int, completedTask: Boolean) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTaskCompleted(taskId, completedTask)
}
}
fun resetAllTasksToInactive() {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateAllTasksActiveStatusToInactive()
}
}
@@ -181,7 +181,7 @@ class TaskProgressScreenModel(
* @param currentCycle the current cycle of the task
*/
private fun updateCurrentCycle(taskId: Int, currentCycle: Int) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateTaskCycleNumber(taskId, currentCycle)
}
}
@@ -192,7 +192,7 @@ class TaskProgressScreenModel(
* @param currentSession the current session of the task
*/
private fun updateCurrentSession(taskId: Int, currentSession: String) {
- coroutineScope.launch {
+ screenModelScope.launch {
tasksRepository.updateCurrentSessionName(taskId, currentSession)
}
}
@@ -201,23 +201,23 @@ class TaskProgressScreenModel(
when (task.value?.current) {
"Focus" -> updateConsumedFocusTime(
task.value?.id ?: -1,
- Timer.tickingTime.value
+ Timer.tickingTime.value,
)
"ShortBreak" -> updateConsumedShortBreakTime(
task.value?.id ?: -1,
- Timer.tickingTime.value
+ Timer.tickingTime.value,
)
"LongBreak" -> updateConsumedLongBreakTime(
task.value?.id ?: -1,
- Timer.tickingTime.value
+ Timer.tickingTime.value,
)
}
}
fun executeTasks() {
- coroutineScope.launch {
+ screenModelScope.launch {
if (task.value?.currentCycle?.equals(0) == true) {
println("executeTasks: first cycle")
updateCurrentCycle(task.value?.id ?: 0, 1)
@@ -230,7 +230,7 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
} else {
when (task.value?.current) {
@@ -241,7 +241,7 @@ class TaskProgressScreenModel(
title = "[TASK] ${task.value?.name}",
description = "${
task.value?.currentCycle?.formattedNumber()
- } Focus Session Completed, going for a long break"
+ } Focus Session Completed, going for a long break",
)
}
@@ -254,13 +254,13 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
} else {
if (remindersOn.value == true) {
notificationManager.showNotification(
title = "[TASK] ${task.value?.name}",
- description = "${task.value?.currentCycle?.formattedNumber()} focus session completed, going for a short break"
+ description = "${task.value?.currentCycle?.formattedNumber()} focus session completed, going for a short break",
)
}
@@ -273,7 +273,7 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
}
}
@@ -284,16 +284,16 @@ class TaskProgressScreenModel(
title = "[TASK] ${task.value?.name}",
description = "Short Break Completed, going for the ${
task.value?.currentCycle?.plus(
- 1
+ 1,
)?.formattedNumber()
- } focus session"
+ } focus session",
)
}
updateCurrentSession(task.value?.id ?: 0, "Focus")
updateCurrentCycle(
task.value?.id ?: 0,
- task.value?.currentCycle?.plus(1) ?: (0 + 1)
+ task.value?.currentCycle?.plus(1) ?: (0 + 1),
)
updateInProgressTask(task.value?.id ?: 0, true)
Timer.setTickingTime(focusTime.value ?: 0L)
@@ -303,7 +303,7 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
}
@@ -311,7 +311,7 @@ class TaskProgressScreenModel(
if (remindersOn.value == true) {
notificationManager.showNotification(
title = "[TASK] ${task.value?.name}",
- description = "Good Job, you have completed this task \uD83C\uDF89\uD83C\uDF89"
+ description = "Good Job, you have completed this task \uD83C\uDF89\uD83C\uDF89",
)
}
@@ -328,7 +328,7 @@ class TaskProgressScreenModel(
}
fun moveToNextSessionOfTheTask() {
- coroutineScope.launch {
+ screenModelScope.launch {
when (task.value?.current.sessionType()) {
SessionType.Focus -> {
if (task.value?.currentCycle == task.value?.focusSessions) {
@@ -341,7 +341,7 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
} else {
updateCurrentSession(task.value?.id ?: 0, "ShortBreak")
@@ -353,7 +353,7 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
}
}
@@ -371,7 +371,7 @@ class TaskProgressScreenModel(
updateCurrentSession(task.value?.id ?: 0, "Focus")
updateCurrentCycle(
task.value?.id ?: 0,
- task.value?.currentCycle?.plus(1) ?: (0 + 1)
+ task.value?.currentCycle?.plus(1) ?: (0 + 1),
)
updateInProgressTask(task.value?.id ?: 0, true)
Timer.setTickingTime(focusTime.value ?: 0L)
@@ -381,7 +381,7 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
}
}
@@ -389,7 +389,7 @@ class TaskProgressScreenModel(
}
fun resetCurrentSessionOfTheTask() {
- coroutineScope.launch {
+ screenModelScope.launch {
when (task.value?.current.sessionType()) {
SessionType.Focus -> {
updateCurrentSession(task.value?.id ?: 0, "Focus")
@@ -401,7 +401,7 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
}
@@ -424,15 +424,10 @@ class TaskProgressScreenModel(
},
executeTasks = {
executeTasks()
- }
+ },
)
}
}
}
}
}
-
-sealed class ReminderState {
- data object Loading : ReminderState()
- data class Success(val reminderOn: Boolean) : ReminderState()
-}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/main/MainScreen.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/main/MainScreen.kt
index 7b8ffb2..e6ed7c5 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/main/MainScreen.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/main/MainScreen.kt
@@ -56,7 +56,7 @@ class MainScreen : Screen {
val useNavRail = windowSizeClass.widthSizeClass > WindowWidthSizeClass.Compact
TabNavigator(
- BloomTab.HomeTab
+ BloomTab.HomeTab,
) {
val tabNavigator = LocalTabNavigator.current
@@ -69,8 +69,8 @@ class MainScreen : Screen {
BloomTab.CalendarTab,
BloomTab.AddTaskTab(),
BloomTab.StatisticsTab,
- BloomTab.SettingsTab
- )
+ BloomTab.SettingsTab,
+ ),
)
CurrentScreen()
}
@@ -79,7 +79,7 @@ class MainScreen : Screen {
content = { innerPadding ->
Box(
modifier = Modifier
- .padding(innerPadding)
+ .padding(innerPadding),
) {
CurrentScreen()
}
@@ -95,28 +95,28 @@ class MainScreen : Screen {
tabNavigator.current = BloomTab.AddTaskTab()
},
elevation = FloatingActionButtonDefaults.elevation(
- defaultElevation = 0.dp
+ defaultElevation = 0.dp,
),
- shape = CircleShape
+ shape = CircleShape,
) {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = "",
tint = MaterialTheme.colorScheme.onPrimary,
- modifier = Modifier.size(24.dp)
+ modifier = Modifier.size(24.dp),
)
}
},
bottomBar = {
BottomNavigation(
- backgroundColor = MaterialTheme.colorScheme.background
+ backgroundColor = MaterialTheme.colorScheme.background,
) {
TabNavigationItem(BloomTab.HomeTab)
TabNavigationItem(BloomTab.CalendarTab)
TabNavigationItem(BloomTab.StatisticsTab)
TabNavigationItem(BloomTab.SettingsTab)
}
- }
+ },
)
}
}
@@ -136,7 +136,7 @@ private fun RowScope.TabNavigationItem(tab: Tab) {
(2u).toUShort() -> 24.dp
(3u).toUShort() -> 0.dp
else -> 0.dp
- }
+ },
),
selected = tabNavigator.current == tab,
onClick = { tabNavigator.current = tab },
@@ -153,9 +153,9 @@ private fun RowScope.TabNavigationItem(tab: Tab) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onBackground
- }
+ },
)
}
- }
+ },
)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/main/MainViewModel.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/main/MainViewModel.kt
index 187c22b..fcec337 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/main/MainViewModel.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/main/MainViewModel.kt
@@ -16,7 +16,7 @@
package com.joelkanyi.focusbloom.main
import cafe.adriel.voyager.core.model.ScreenModel
-import cafe.adriel.voyager.core.model.coroutineScope
+import cafe.adriel.voyager.core.model.screenModelScope
import com.joelkanyi.focusbloom.core.domain.repository.settings.SettingsRepository
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -24,22 +24,22 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
class MainViewModel(
- settingsRepository: SettingsRepository
+ settingsRepository: SettingsRepository,
) : ScreenModel {
val appTheme: StateFlow = settingsRepository.getAppTheme().map { it }.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = null,
)
val onBoardingCompleted: StateFlow =
settingsRepository.getUsername().map {
OnBoardingState.Success(it.isNullOrEmpty().not())
}.stateIn(
- scope = coroutineScope,
+ scope = screenModelScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = OnBoardingState.Loading
+ initialValue = OnBoardingState.Loading,
)
}
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/platform/Font.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/platform/Font.kt
deleted file mode 100644
index 08037ec..0000000
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/platform/Font.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2023 Joel Kanyi.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.joelkanyi.focusbloom.platform
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.text.font.Font
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontWeight
-
-@Composable
-expect fun font(name: String, res: String, weight: FontWeight, style: FontStyle): Font
diff --git a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.kt b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.kt
index 342665a..874fec7 100644
--- a/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.kt
+++ b/shared/src/commonMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.kt
@@ -18,6 +18,6 @@ package com.joelkanyi.focusbloom.platform
expect class NotificationsManager {
fun showNotification(
title: String,
- description: String
+ description: String,
)
}
diff --git a/shared/src/commonMain/sqldelight/database/task.sq b/shared/src/commonMain/sqldelight/database/task.sq
index 9806c5a..2bd256f 100644
--- a/shared/src/commonMain/sqldelight/database/task.sq
+++ b/shared/src/commonMain/sqldelight/database/task.sq
@@ -5,7 +5,7 @@ import kotlin.String;
-CREATE TABLE taskEntity (
+CREATE TABLE IF NOT EXISTS taskEntity (
id INTEGER AS Int NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT,
diff --git a/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt b/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
index 7aa7299..ab703a9 100644
--- a/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
+++ b/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
@@ -18,11 +18,9 @@ package com.joelkanyi.focusbloom.di
import com.joelkanyi.focusbloom.platform.DatabaseDriverFactory
import com.joelkanyi.focusbloom.platform.MultiplatformSettingsWrapper
import com.joelkanyi.focusbloom.platform.NotificationsManager
-import com.russhwolf.settings.ExperimentalSettingsApi
import org.koin.core.module.Module
import org.koin.dsl.module
-@OptIn(ExperimentalSettingsApi::class)
actual fun platformModule(): Module = module {
single { MultiplatformSettingsWrapper().createSettings() }
single { DatabaseDriverFactory() }
diff --git a/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/Font.ios.kt b/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/Font.ios.kt
deleted file mode 100644
index 4224e30..0000000
--- a/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/Font.ios.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2023 Joel Kanyi.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.joelkanyi.focusbloom.platform
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.text.font.Font
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontWeight
-import kotlinx.coroutines.runBlocking
-import org.jetbrains.compose.resources.ExperimentalResourceApi
-import org.jetbrains.compose.resources.resource
-
-private val cache: MutableMap = mutableMapOf()
-
-@OptIn(ExperimentalResourceApi::class)
-@Composable
-actual fun font(name: String, res: String, weight: FontWeight, style: FontStyle): Font {
- return cache.getOrPut(res) {
- val byteArray = runBlocking { resource("font/$res.ttf").readBytes() }
- androidx.compose.ui.text.platform.Font(res, byteArray, weight, style)
- }
-}
diff --git a/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.ios.kt b/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.ios.kt
index 7110d60..1d91cfc 100644
--- a/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.ios.kt
+++ b/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.ios.kt
@@ -46,7 +46,7 @@ actual class NotificationsManager {
override fun userNotificationCenter(
center: UNUserNotificationCenter,
didReceiveNotificationResponse: UNNotificationResponse,
- withCompletionHandler: () -> Unit
+ withCompletionHandler: () -> Unit,
) {
withCompletionHandler()
}
@@ -54,7 +54,7 @@ actual class NotificationsManager {
override fun userNotificationCenter(
center: UNUserNotificationCenter,
willPresentNotification: UNNotification,
- withCompletionHandler: (UNNotificationPresentationOptions) -> Unit
+ withCompletionHandler: (UNNotificationPresentationOptions) -> Unit,
) {
withCompletionHandler(UNNotificationPresentationOptionAlert)
}
diff --git a/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/StatusBarColors.ios.kt b/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/StatusBarColors.ios.kt
index 98f0f3c..7f23bd2 100644
--- a/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/StatusBarColors.ios.kt
+++ b/shared/src/iosMain/kotlin/com/joelkanyi/focusbloom/platform/StatusBarColors.ios.kt
@@ -37,9 +37,7 @@ private fun statusBarView() = remember {
val tag =
3848245L // https://stackoverflow.com/questions/56651245/how-to-change-the-status-bar-background-color-and-text-color-on-ios-13
- keyWindow?.viewWithTag(tag)?.let {
- it
- } ?: run {
+ keyWindow?.viewWithTag(tag) ?: run {
val height =
keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?: zeroValue()
val statusBarView = UIView(frame = height)
@@ -63,5 +61,5 @@ private fun Color.toUIColor(): UIColor = UIColor(
red = this.red.toDouble(),
green = this.green.toDouble(),
blue = this.blue.toDouble(),
- alpha = this.alpha.toDouble()
+ alpha = this.alpha.toDouble(),
)
diff --git a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
index 7aa7299..ab703a9 100644
--- a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
+++ b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/di/Module.kt
@@ -18,11 +18,9 @@ package com.joelkanyi.focusbloom.di
import com.joelkanyi.focusbloom.platform.DatabaseDriverFactory
import com.joelkanyi.focusbloom.platform.MultiplatformSettingsWrapper
import com.joelkanyi.focusbloom.platform.NotificationsManager
-import com.russhwolf.settings.ExperimentalSettingsApi
import org.koin.core.module.Module
import org.koin.dsl.module
-@OptIn(ExperimentalSettingsApi::class)
actual fun platformModule(): Module = module {
single { MultiplatformSettingsWrapper().createSettings() }
single { DatabaseDriverFactory() }
diff --git a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/notification/linux/LinuxNotificationProvider.kt b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/notification/linux/LinuxNotificationProvider.kt
index 931c94c..65fa65c 100644
--- a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/notification/linux/LinuxNotificationProvider.kt
+++ b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/notification/linux/LinuxNotificationProvider.kt
@@ -224,7 +224,7 @@ object LinuxNotificationProvider : NotificationProvider {
@Suppress("FunctionName")
private fun LibNotify.notify_notification_set_desktop_entry(
notification: Pointer,
- desktopEntry: String
+ desktopEntry: String,
) {
val string = g_variant_new_string(desktopEntry)
notify_notification_set_hint(notification, "desktop-entry", string) // NON-NLS
@@ -233,7 +233,7 @@ object LinuxNotificationProvider : NotificationProvider {
@Suppress("FunctionName")
private fun LibNotify.notify_notification_set_suppress_sound(
notification: Pointer,
- suppressSound: Boolean
+ suppressSound: Boolean,
) {
val bool = g_variant_new_boolean(suppressSound)
notify_notification_set_hint(notification, "suppress-sound", bool) // NON-NLS
diff --git a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/notification/windows/Toast4jNotificationProvider.kt b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/notification/windows/Toast4jNotificationProvider.kt
index 1cfdf72..06a29cf 100644
--- a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/notification/windows/Toast4jNotificationProvider.kt
+++ b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/notification/windows/Toast4jNotificationProvider.kt
@@ -57,7 +57,7 @@ object Toast4jNotificationProvider : NotificationProvider {
ToastBuilder(WinToastTemplate.WinToastTemplateType.ToastText01).setSilent()
.setLine1(title)
.setLine2(description)
- .build()
+ .build(),
)
}
}
diff --git a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/DatabaseDriverFactory.jvm.kt b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/DatabaseDriverFactory.jvm.kt
index 68738db..7f6bccb 100644
--- a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/DatabaseDriverFactory.jvm.kt
+++ b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/DatabaseDriverFactory.jvm.kt
@@ -18,10 +18,45 @@ package com.joelkanyi.focusbloom.platform
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
import com.joelkanyi.focusbloom.database.BloomDatabase
+import java.io.File
actual class DatabaseDriverFactory {
actual fun createDriver(): SqlDriver {
- return JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY)
- .also { BloomDatabase.Schema.create(it) }
+ return JdbcSqliteDriver(
+ url = "jdbc:sqlite:${databaseFile.absolutePath}",
+ ).also { db ->
+ BloomDatabase.Schema.create(db)
+ }
}
+
+ private val databaseFile: File
+ get() = File(appDir.also { if (!it.exists()) it.mkdirs() }, "bloom.db")
+
+ private val appDir: File
+ get() {
+ val os = System.getProperty("os.name").lowercase()
+ return when {
+ os.contains("win") -> {
+ File(
+ System.getenv("AppData"),
+ "bloom/db"
+ ) // "C:\Users\AppData\Roaming\bloom\db"
+ }
+
+ os.contains("nix") || os.contains("nux") || os.contains("aix") -> {
+ File(
+ System.getProperty("user.home"), ".bloom"
+ ) // "/home//.bloom"
+ }
+
+ os.contains("mac") -> {
+ File(
+ System.getProperty("user.home"),
+ "Library/Application Support/bloom"
+ ) // "/Users//Library/Application Support/bloom"
+ }
+
+ else -> error("Unsupported operating system")
+ }
+ }
}
diff --git a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/Font.jvm.kt b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/Font.jvm.kt
deleted file mode 100644
index da929a3..0000000
--- a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/Font.jvm.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2023 Joel Kanyi.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.joelkanyi.focusbloom.platform
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.text.font.Font
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontWeight
-
-@Composable
-actual fun font(name: String, res: String, weight: FontWeight, style: FontStyle): Font = androidx.compose.ui.text.platform.Font("font/$res.ttf", weight, style)
diff --git a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.jvm.kt b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.jvm.kt
index 88a9355..ad14c6f 100644
--- a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.jvm.kt
+++ b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/platform/NotificationsManager.jvm.kt
@@ -28,21 +28,21 @@ actual class NotificationsManager {
hostOs.startsWith("Windows") -> {
Toast4jNotificationProvider.sendNotification(
title = title,
- description = description
+ description = description,
)
}
hostOs.startsWith("Mac") -> {
MacOsNotificationProvider.sendNotification(
title = title,
- description = description
+ description = description,
)
}
hostOs.startsWith("Linux") -> {
LinuxNotificationProvider.sendNotification(
title = title,
- description = description
+ description = description,
)
}
diff --git a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/utils/AudioUtils.kt b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/utils/AudioUtils.kt
index 14c0f36..759f6bd 100644
--- a/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/utils/AudioUtils.kt
+++ b/shared/src/jvmMain/kotlin/com/joelkanyi/focusbloom/utils/AudioUtils.kt
@@ -24,7 +24,8 @@ object AudioUtils {
fun loadAudioFromResource(name: String): Clip? {
val resourceStream = getResourceAsStream(name) ?: return null
- val bufferedStream = BufferedInputStream(resourceStream) // add buffer for mark/reset support
+ val bufferedStream =
+ BufferedInputStream(resourceStream) // add buffer for mark/reset support
val audioInputStream = AudioSystem.getAudioInputStream(bufferedStream)
val sound = AudioSystem.getClip()
sound.open(audioInputStream)