Skip to content

Implement WatchApp version for quick calculation#163

Open
hieuwu wants to merge 59 commits into
mainfrom
feature/watchapp-quick-pairs
Open

Implement WatchApp version for quick calculation#163
hieuwu wants to merge 59 commits into
mainfrom
feature/watchapp-quick-pairs

Conversation

@hieuwu

@hieuwu hieuwu commented Sep 6, 2025

Copy link
Copy Markdown
Collaborator

📌 Description

Watchapp version for quick pairs

✅ Changes

Watch app built with compose for WearOS with basic functionalities:

  • Currency Converter: Bi-directional conversion between any two currencies.
  • Quick Pairs: A saved list of your most-used currency conversions.
  • Pair Pinning: Pin your top 4 pairs for priority display.
  • Custom Watch Face: View your pinned conversion rates directly on your watch face.
  • Complications: Show specific currency rates on other standard watch faces.
  • Currency Search: Find and select currencies with integrated country flags.

🎯 How to Test

See the video

📸 Screenshots / Demo (if applicable)

Currency.converter.watchapp.mp4

🔗 Related Tickets / Issues

N/A

@hieuwu hieuwu requested review from kirillt and mdrlzy May 11, 2026 09:42
# Conflicts:
#	gradle/libs.versions.toml
@hieuwu hieuwu changed the title [WIP] Watch app for quick pairs Implement WatchApp versionn for quick calculation May 11, 2026
@hieuwu hieuwu marked this pull request as ready for review May 11, 2026 10:00
import javax.inject.Inject
import javax.inject.Singleton

@Singleton

@hieuwu hieuwu May 11, 2026

Copy link
Copy Markdown
Collaborator Author

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

@hieuwu hieuwu changed the title Implement WatchApp versionn for quick calculation Implement WatchApp version for quick calculation May 11, 2026

@mdrlzy mdrlzy left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks great!

I have a couple of comments. We should add Orbit MVI and replace Hilt with Dagger to keep it consistent with the rest of the codebase.

The watch face UI could also be improved, but we can handle that in a separate PR once the design is ready.

Comment on lines +44 to +47
@Composable
fun CurrencyInputField(
label: String,
currencyCode: String,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unused code

Comment on lines +30 to +34
@Composable
fun OptionItem(
modifier: Modifier = Modifier,
icon: Painter,
text: String,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unused code

Comment on lines +19 to +22
@Composable
fun OptionsMenu(modifier: Modifier = Modifier) {
ScalingLazyColumn(
modifier = modifier.fillMaxSize(),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unused code

Comment on lines +27 to +31
@Composable
fun SwapButton(
onSwapClick: () -> Unit,
modifier: Modifier = Modifier
) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unused code

Comment on lines +28 to +32
@Composable
fun WearNumpad(
modifier: Modifier = Modifier,
amount: String,
onNumberClick: (Int) -> Unit,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unused code

Comment on lines +10 to +14
@HiltViewModel
class MainViewModel @Inject constructor(
private val currencyRepo: CurrencyRepo,
): ViewModel() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unused code

Comment on lines +50 to +75
if (showDeleteDialog) {
WearConfirmationDialog(
title = "Delete Pair",
message = "Are you sure you want to delete this pair?",
onConfirm = {
showDeleteDialog = false
viewModel.deletePair(onDeleted = {
onDeleteSuccess("Deleted Successfully")
})
},
onDismiss = {
showDeleteDialog = false
onDismiss()
},
isDestructive = true
)
}

if (showPinLimitDialog) {
WearInfoDialog(
title = "Pin Limit Reached",
message = "You can only pin up to 4 pairs. Please unpin another pair first.",
onDismiss = { viewModel.dismissPinLimitDialog() },
dismissText = "Ok got it"
)
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hardcoded strings

Comment on lines +83 to +88
if (state.isSaved) {
val message = if (state.editId != null) "Updated Successfully" else "Added Successfully"
LaunchedEffect(Unit) {
onNavigateToSuccess(message)
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hardcoded strings

Comment on lines +51 to +54
// Check limit
val pinnedCount = quickRepo.getAll().count { it.isPinned() }
if (pinnedCount >= 4) {
_showPinLimitDialog.value = true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We should discuss this. What is the motivation behind limiting pinned pairs?

Comment on lines +56 to +77
// Pin
val updated = pair.copy(pinnedDate = java.time.OffsetDateTime.now())
quickRepo.insert(updated)
WatchRefreshManager.refreshComplications(application)
onSuccess(true)
}
}
}
}

fun dismissPinLimitDialog() {
_showPinLimitDialog.value = false
}

fun deletePair(onDeleted: () -> Unit) {
viewModelScope.launch {
_quickPair.value?.let { p ->
quickRepo.delete(p.id)
onDeleted()
}
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we also call refreshComplications() after deleting pair?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants