Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
f0b8637
Init watch app module
hieuwu Dec 19, 2024
85f55d7
Implement quick pair item
hieuwu Dec 21, 2024
604e0e2
Update quick pair class
hieuwu Dec 22, 2024
9566b52
Update composables
hieuwu Dec 22, 2024
21c8768
Tweak UI
hieuwu Dec 22, 2024
f7f7979
Tweak spacing
hieuwu Dec 25, 2024
67d3215
Display empty and quick pairs list
hieuwu Dec 25, 2024
7726f4e
Display empty and quick pairs list
hieuwu Dec 25, 2024
1bbef9a
Create viewmodel with fake data
hieuwu Dec 25, 2024
52a9aaf
Create option item
hieuwu Dec 26, 2024
c63aa8e
Implement add quick pair screen
hieuwu Dec 26, 2024
63fbd61
Create viewmodel
hieuwu Dec 26, 2024
eb9dd00
Implement options screen
hieuwu Dec 28, 2024
e0996f4
Improve list effect
hieuwu Jan 7, 2025
ae36e64
Extract composable and improve imports
hieuwu Jan 7, 2025
0c5a42a
Improve list effect
hieuwu Jan 7, 2025
3f29554
Set up navigation
hieuwu Jan 7, 2025
03e816f
Tweak UI
hieuwu Jan 7, 2025
2531ec5
Create UI
hieuwu Mar 29, 2025
8579c03
Merge branch 'main' into feature/watchapp-quick-pairs
hieuwu Sep 6, 2025
58290f3
Create options screen
hieuwu Sep 6, 2025
eacf309
Add new pair screens
hieuwu Sep 6, 2025
dc5aaaa
Add composables
hieuwu Sep 6, 2025
29bddf6
Refactor so that class be free from di code
hieuwu Sep 6, 2025
c7020b1
Setup hilt for di
hieuwu Sep 6, 2025
9fbff91
Set up di and db
hieuwu Sep 6, 2025
5f6cde7
Set up di and db
hieuwu Sep 6, 2025
6d99793
Clone di graph
hieuwu Sep 6, 2025
e8255bd
Set up hilt
hieuwu Sep 6, 2025
d595fb6
Init data
hieuwu Sep 6, 2025
80b9a52
Set up compose viewmodel
hieuwu Sep 6, 2025
778d74e
Implement search screen
hieuwu Sep 6, 2025
57be820
Fix wrong annotation
hieuwu Sep 6, 2025
cb9d96b
Configure build
hieuwu May 9, 2026
64ae30e
Set up navigation and build config for json file
hieuwu May 9, 2026
631cbff
Theming and shared components
hieuwu May 9, 2026
29c3a0b
Refacor and implement add quick pairs screen
hieuwu May 9, 2026
088452e
Implement quick pairs screen
hieuwu May 9, 2026
b9a15e0
Update option button
hieuwu May 9, 2026
b885b13
Search screen
hieuwu May 9, 2026
8a6be74
Inject dao
hieuwu May 9, 2026
0da9392
Add options screen
hieuwu May 10, 2026
a0836a7
Implement watch face to load quick pairs
hieuwu May 10, 2026
371ed55
Implement watch face to load quick pairs
hieuwu May 10, 2026
6ea3b58
Implement watch face
hieuwu May 10, 2026
7c98eb7
Implement update and delete
hieuwu May 10, 2026
0feb3e1
Implement update and delete
hieuwu May 10, 2026
e793077
Update options
hieuwu May 10, 2026
ccc7e72
Update UI
hieuwu May 10, 2026
3f6da88
Improve message and pin
hieuwu May 10, 2026
8a10d74
Update app name and app logo
hieuwu May 10, 2026
bfcd4cc
Update app name and app logo
hieuwu May 10, 2026
9d33340
Remove unused resources
hieuwu May 10, 2026
a1b4619
Merge branch 'main' into feature/watchapp-quick-pairs
hieuwu May 11, 2026
05a5ba2
Update after last refactoring
hieuwu May 11, 2026
6f83dd6
Update deps
hieuwu May 11, 2026
fef630a
Update deps and rename classees
hieuwu May 11, 2026
741bad8
Update deps and rename classees
hieuwu May 11, 2026
d337323
Improve deps
hieuwu May 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.9.1" apply false
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.ksp)
id("com.google.gms.google-services") version "4.4.2" apply false
id("com.google.firebase.crashlytics") version "3.0.1" apply false
id("org.jlleitschuh.gradle.ktlint") version "12.1.1"
id("com.google.dagger.hilt.android") version "2.56.2" apply false
}

allprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import dev.arkbuilders.rate.core.domain.model.CurrencyRate
import dev.arkbuilders.rate.core.domain.model.CurrencyType
import java.math.BigDecimal
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class CryptoRateResponseMapper @Inject constructor() {
fun map(response: List<CryptoRateResponse>) =
response.map {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ import dev.arkbuilders.rate.core.domain.model.CurrencyRate
import dev.arkbuilders.rate.core.domain.model.CurrencyType
import java.math.BigDecimal
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class FiatRateResponseMapper @Inject constructor() {
fun map(response: FiatRateResponse): List<CurrencyRate> =
response.rates.map { (code, rate) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import android.content.Context
import android.webkit.WebSettings
import okhttp3.OkHttpClient
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
Copy link
Copy Markdown
Collaborator Author

@hieuwu hieuwu May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These @Singleton annotations are added in RepoModule.
This is to avoid conflict of generated code used in watchapp, the watch version uses Hilt for DI

class OkHttpClientBuilder @Inject constructor(val context: Context) {
fun build(): OkHttpClient {
val agent = WebSettings.getDefaultUserAgent(context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import java.time.OffsetDateTime
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class TimestampRepoImpl @Inject constructor(private val dao: TimestampDao) : TimestampRepo {
override suspend fun rememberTimestamp(type: TimestampType) =
dao.insert(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import dev.arkbuilders.rate.core.data.network.api.CryptoAPI
import dev.arkbuilders.rate.core.domain.model.CurrencyRate
import dev.arkbuilders.rate.core.domain.model.CurrencyType
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class CryptoCurrencyDataSource @Inject constructor(
private val cryptoAPI: CryptoAPI,
private val cryptoRateResponseMapper: CryptoRateResponseMapper,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class CurrencyInfoDataSource @Inject constructor(
private val ctx: Context,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ import kotlinx.coroutines.withContext
import java.time.Duration
import java.time.OffsetDateTime
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class CurrencyRepoImpl @Inject constructor(
private val fiatDataSource: FiatCurrencyDataSource,
private val cryptoDataSource: CryptoCurrencyDataSource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.time.OffsetDateTime
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class FallbackRatesProvider @Inject constructor(
private val ctx: Context,
private val fiatRateResponseMapper: FiatRateResponseMapper,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import dev.arkbuilders.rate.core.data.network.api.FiatAPI
import dev.arkbuilders.rate.core.domain.model.CurrencyRate
import dev.arkbuilders.rate.core.domain.model.CurrencyType
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class FiatCurrencyDataSource @Inject constructor(
private val fiatAPI: FiatAPI,
private val fiatRateResponseMapper: FiatRateResponseMapper,
Expand Down
2 changes: 1 addition & 1 deletion core/db/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ dependencies {
ksp(libs.androidx.room.compiler)

testImplementation(libs.junit)
androidTestImplementation(libs.androidx.room.testing)
// androidTestImplementation(libs.androidx.room.testing)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.arkbuilders.rate.core.di.modules

import android.content.Context
import com.google.gson.GsonBuilder
import dagger.Module
import dagger.Provides
Expand All @@ -12,6 +13,12 @@ import javax.inject.Singleton

@Module
class ApiModule {
@Singleton
@Provides
fun okHttpClientBuilder(context: Context): OkHttpClientBuilder {
return OkHttpClientBuilder(context)
}

@Singleton
@Provides
fun cryptoAPI(clientBuilder: OkHttpClientBuilder): CryptoAPI {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ package dev.arkbuilders.rate.core.di.modules
import android.content.Context
import dagger.Module
import dagger.Provides
import dev.arkbuilders.rate.core.data.mapper.CryptoRateResponseMapper
import dev.arkbuilders.rate.core.data.mapper.FiatRateResponseMapper
import dev.arkbuilders.rate.core.data.network.NetworkStatusImpl
import dev.arkbuilders.rate.core.data.network.api.CryptoAPI
import dev.arkbuilders.rate.core.data.network.api.FiatAPI
import dev.arkbuilders.rate.core.data.preferences.PrefsImpl
import dev.arkbuilders.rate.core.data.repo.AnalyticsManagerImpl
import dev.arkbuilders.rate.core.data.repo.BuildConfigFieldsProviderImpl
Expand All @@ -18,6 +22,7 @@ import dev.arkbuilders.rate.core.data.repo.currency.FallbackRatesProvider
import dev.arkbuilders.rate.core.data.repo.currency.FiatCurrencyDataSource
import dev.arkbuilders.rate.core.data.repo.currency.LocalCurrencyDataSource
import dev.arkbuilders.rate.core.db.dao.CodeUseStatDao
import dev.arkbuilders.rate.core.db.dao.CurrencyRateDao
import dev.arkbuilders.rate.core.db.dao.GroupDao
import dev.arkbuilders.rate.core.db.dao.TimestampDao
import dev.arkbuilders.rate.core.domain.BuildConfigFieldsProvider
Expand All @@ -35,6 +40,22 @@ import javax.inject.Singleton

@Module
class RepoModule {
@Singleton
@Provides
fun provideFallbackRatesProvider(
context: Context,
fiatRateResponseMapper: FiatRateResponseMapper,
cryptoRateResponseMapper: CryptoRateResponseMapper,
buildConfigFieldsProvider: BuildConfigFieldsProvider,
): FallbackRatesProvider {
return FallbackRatesProvider(
context,
fiatRateResponseMapper,
cryptoRateResponseMapper,
buildConfigFieldsProvider,
)
}

@Singleton
@Provides
fun currencyRepo(
Expand Down Expand Up @@ -90,6 +111,30 @@ class RepoModule {
fun defaultGroupNameProvider(context: Context): DefaultGroupNameProvider =
DefaultGroupNameProviderImpl(context)

@Singleton
@Provides
fun fiatCurrencyDataSource(
fiatAPI: FiatAPI,
fiatRateResponseMapper: FiatRateResponseMapper,
): FiatCurrencyDataSource = FiatCurrencyDataSource(fiatAPI, fiatRateResponseMapper)

@Singleton
@Provides
fun cryptoCurrencyDataSource(
cryptoAPI: CryptoAPI,
cryptoRateResponseMapper: CryptoRateResponseMapper,
): CryptoCurrencyDataSource = CryptoCurrencyDataSource(cryptoAPI, cryptoRateResponseMapper)

@Singleton
@Provides
fun localCurrencyDataSource(dao: CurrencyRateDao): LocalCurrencyDataSource =
LocalCurrencyDataSource(dao)

@Singleton
@Provides
fun currencyInfoDataSource(context: Context): CurrencyInfoDataSource =
CurrencyInfoDataSource(context)

@Singleton
@Provides
fun inAppReviewManager(
Expand Down
13 changes: 13 additions & 0 deletions core/presentation/src/main/res/drawable/ic_update.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="21dp"
android:height="20dp"
android:viewportWidth="21"
android:viewportHeight="20">
<path
android:pathData="M12.167,18.333C12.167,18.333 12.874,18.232 15.803,15.303C18.732,12.374 18.732,7.625 15.803,4.696C14.766,3.658 13.499,2.988 12.167,2.686M12.167,18.333H17.167M12.167,18.333L12.167,13.333M8.833,1.666C8.833,1.666 8.126,1.767 5.197,4.696C2.268,7.625 2.268,12.374 5.197,15.303C6.234,16.34 7.501,17.011 8.833,17.313M8.833,1.666L3.833,1.666M8.833,1.666L8.833,6.666"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#384250"
android:strokeLineCap="round"/>
</vector>
2 changes: 2 additions & 0 deletions core/presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@
<string name="delete">Delete</string>
<string name="re_use">Re-use</string>
<string name="edit">Edit</string>
<string name="update">Update</string>

<string name="options">Options</string>
<string name="oops_request_time_out">Oops, request time out!</string>
<string name="check_connection_and_refresh">Please check your connection and refresh the page to try again.</string>
Expand Down
27 changes: 27 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
[versions]
composeNavigation = "1.3.0"
hilt = "2.56.2"
kotlin = "2.1.20"
agp = "8.1.4"
playServicesWearable = "18.2.0"
coreKtx = "1.15.0"
minSdk = "26"
compileSdk = "36"
ksp = "2.1.20-1.0.32"

arkAbout = "0.2.1"
androidApp = "8.9.1"
activityCompose = "1.10.1"
composeDestinationsVersion = "2.1.0"
arrowFxCoroutines = "1.2.1"
Expand Down Expand Up @@ -37,8 +41,14 @@ material = "1.12.0"
gson = "2.11.0"
reorderable = "2.4.3"
playReview = "2.0.2"
composeBom = "2023.08.00"
composeMaterial = "1.2.1"
composeFoundation = "1.2.1"
coreSplashscreen = "1.0.1"
watchface = "1.2.1"

[libraries]
androidx-compose-navigation = { module = "androidx.wear.compose:compose-navigation", version.ref = "composeNavigation" }
ark-about = { module = "dev.arkbuilders.components:about", version.ref = "arkAbout" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
Expand Down Expand Up @@ -69,6 +79,8 @@ dagger = { module = "com.google.dagger:dagger", version.ref = "dagger" }
dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" }
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }

hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" }
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
play-review = { group = "com.google.android.play", name = "review", version.ref = "playReview" }
play-review-ktx = { group = "com.google.android.play", name = "review-ktx", version.ref = "playReview" }

Expand All @@ -90,8 +102,23 @@ androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref =
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
reorderable = { group = "sh.calvin.reorderable", name = "reorderable", version.ref = "reorderable" }

play-services-wearable = { group = "com.google.android.gms", name = "play-services-wearable", version.ref = "playServicesWearable" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-material = { group = "androidx.wear.compose", name = "compose-material", version.ref = "composeMaterial" }
androidx-compose-foundation = { group = "androidx.wear.compose", name = "compose-foundation", version.ref = "composeFoundation" }
androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "coreSplashscreen" }
androidx-wear-watchface = { module = "androidx.wear.watchface:watchface", version.ref = "watchface" }
androidx-wear-watchface-complications-data = { module = "androidx.wear.watchface:watchface-complications-data", version.ref = "watchface" }
androidx-wear-watchface-complications-data-source = { module = "androidx.wear.watchface:watchface-complications-data-source", version.ref = "watchface" }
androidx-wear-watchface-complications-data-source-ktx = { module = "androidx.wear.watchface:watchface-complications-data-source-ktx", version.ref = "watchface" }
androidx-wear-watchface-complications-rendering = { module = "androidx.wear.watchface:watchface-complications-rendering", version.ref = "watchface" }
androidx-wear-watchface-editor = { module = "androidx.wear.watchface:watchface-editor", version.ref = "watchface" }
androidx-wear-watchface-style = { module = "androidx.wear.watchface:watchface-style", version.ref = "watchface" }

[plugins]
android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"}
android-application = { id = "com.android.application", version.ref = "androidApp"}
4 changes: 3 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import java.util.Properties

pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
gradlePluginPortal()
maven {
setUrl("https://jitpack.io")
}
Expand Down Expand Up @@ -54,6 +54,8 @@ include(":feature:quickwidget")
include(":feature:search")
include(":feature:settings")
include(":feature:onboarding")
include(":watchapp")


fun getLocalProps(): Properties {
val props = Properties()
Expand Down
1 change: 1 addition & 0 deletions watchapp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
Loading
Loading