Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -377,10 +377,10 @@ private fun DaoOverviewCard(

Spacer(modifier = Modifier.height(4.dp))

Text(
text = "APC ~${String.format("%.2f", overview.currentApc)}%",
com.rjnr.pocketnode.ui.screens.dao.components.ApcLabel(
apc = overview.currentApc,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
color = MaterialTheme.colorScheme.onSurfaceVariant,
)

Spacer(modifier = Modifier.height(8.dp))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.rjnr.pocketnode.ui.screens.dao.components

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.Info
import com.composables.icons.lucide.Lucide

/**
* APC label with a tap-to-explain affordance. Reused by both the DAO
* overview header and the per-deposit cards so the explanation lives
* in one place.
*
* Why a tooltip exists: Pocket Node shows *realized* APC (the actual
* compensation accrued on this specific deposit divided by elapsed
* time), while the Neuron desktop wallet shows *theoretical* APC (a
* forward-looking projection from CKB tokenomics). Users who compare
* the two numbers will see different values and reasonably assume one
* is wrong. The tooltip explains the difference so the user can act
* on the right mental model.
*/
@Composable
fun ApcLabel(
apc: Double,
style: androidx.compose.ui.text.TextStyle = MaterialTheme.typography.bodySmall,
color: androidx.compose.ui.graphics.Color = MaterialTheme.colorScheme.onSurfaceVariant,
prefix: String = "APC",
modifier: Modifier = Modifier,
) {
var showInfo by remember { mutableStateOf(false) }

Row(
modifier = modifier.clickable { showInfo = true },
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
Text(
text = "$prefix ~${"%.2f".format(apc)}%",
style = style,
color = color,
textDecoration = TextDecoration.Underline,
)
Icon(
imageVector = Lucide.Info,
contentDescription = "What is APC?",
tint = color,
modifier = Modifier.size(12.dp),
)
}

if (showInfo) {
AlertDialog(
onDismissRequest = { showInfo = false },
title = { Text("About this APC") },
text = {
Text(
text = "This number is the realized annual compensation rate: " +
"the actual CKB earned on this deposit divided by the time " +
"it has been deposited.\n\n" +
"It may differ from the APC shown by other CKB wallets such " +
"as Neuron. Neuron displays a theoretical APC computed from " +
"the protocol's tokenomics — a forward-looking projection " +
"assuming idealised conditions. Realized APC tracks what " +
"your specific deposit has earned, which fluctuates with " +
"actual on-chain participation.\n\n" +
"Both numbers are valid. The realized number is the truth " +
"about your deposit; the theoretical number is an estimate " +
"of what a new deposit might earn.",
style = MaterialTheme.typography.bodyMedium,
)
},
confirmButton = {
TextButton(onClick = { showInfo = false }) {
Text("Got it")
Comment on lines +69 to +89
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Extract hard-coded strings to string resources.

The dialog title, explanation text, and button label are hard-coded in English, while the rest of the codebase uses stringResource(R.string.*) for i18n. This breaks localization and violates the DRY principle established elsewhere in the project.

♻️ Suggested extraction to res/values/strings.xml

Add to res/values/strings.xml:

<string name="dao_apc_dialog_title">About this APC</string>
<string name="dao_apc_dialog_explanation">This number is the realized annual compensation rate: the actual CKB earned on this deposit divided by the time it has been deposited.\n\nIt may differ from the APC shown by other CKB wallets such as Neuron. Neuron displays a theoretical APC computed from the protocol\'s tokenomics — a forward-looking projection assuming idealised conditions. Realized APC tracks what your specific deposit has earned, which fluctuates with actual on-chain participation.\n\nBoth numbers are valid. The realized number is the truth about your deposit; the theoretical number is an estimate of what a new deposit might earn.</string>
<string name="dao_apc_dialog_confirm">Got it</string>

Then update the code:

+import androidx.compose.ui.res.stringResource
+import com.rjnr.pocketnode.R
+
 `@Composable`
 fun ApcLabel(
     ...
 ) {
     ...
     if (showInfo) {
         AlertDialog(
             onDismissRequest = { showInfo = false },
-            title = { Text("About this APC") },
+            title = { Text(stringResource(R.string.dao_apc_dialog_title)) },
             text = {
                 Text(
-                    text = "This number is the realized annual compensation rate: " +
-                        "the actual CKB earned on this deposit divided by the time " +
-                        ...
+                    text = stringResource(R.string.dao_apc_dialog_explanation),
                     style = MaterialTheme.typography.bodyMedium,
                 )
             },
             confirmButton = {
-                TextButton(onClick = { showInfo = false }) {
-                    Text("Got it")
-                }
+                TextButton(onClick = { showInfo = false }) {
+                    Text(stringResource(R.string.dao_apc_dialog_confirm))
+                }
             },
         )
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@android/app/src/main/java/com/rjnr/pocketnode/ui/screens/dao/components/ApcLabel.kt`
around lines 69 - 89, Replace the hard-coded English strings in the ApcLabel
dialog with string resources: move the title "About this APC", the long
explanation paragraph, and the confirm button label "Got it" into
res/values/strings.xml (e.g. dao_apc_dialog_title, dao_apc_dialog_explanation,
dao_apc_dialog_confirm) and update the composable usages in ApcLabel (the title
lambda, the text lambda where Text(...) uses the long explanation, and the
confirmButton/Text) to call stringResource(R.string.<name>) so the dialog uses
localized strings instead of inline literals.

}
},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ fun DaoDepositCard(
)
if (deposit.apc > 0.0) {
Spacer(modifier = Modifier.width(8.dp))
Text(
text = "APC \u2248 ${"%.2f".format(deposit.apc)}%",
ApcLabel(
apc = deposit.apc,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
Expand Down
Loading