Skip to content

feat: redesign tools menu#1479

Merged
HashEngineering merged 9 commits intomasterfrom
feat/update-tools-menu
Apr 20, 2026
Merged

feat: redesign tools menu#1479
HashEngineering merged 9 commits intomasterfrom
feat/update-tools-menu

Conversation

@HashEngineering
Copy link
Copy Markdown
Collaborator

@HashEngineering HashEngineering commented Apr 13, 2026

Issue being fixed or feature implemented

Related PR's and Dependencies

Screenshots / Videos

How Has This Been Tested?

  • QA (Mobile Team)

Checklist:

  • I have performed a self-review of my own code and added comments where necessary
  • I have added or updated relevant unit/integration/functional/e2e tests

Summary by CodeRabbit

  • New Features

    • New Compose-based Tools screen with tool actions and previews
    • Dash-styled toggle switch for on/off controls
    • Multiple new icons (CSV export, fingerprint, import key, address book, ZenLedger, etc.)
  • Improvements

    • Redesigned Tools and Settings screens migrated to Compose with refreshed layout and visuals
    • Menu/item styling adjusted (larger radii, spacing, optional info button, trailing button styles)
    • Typography and heading alignment tweaked for readability; CoinJoin status display logic refined
  • Localization

    • Minor string capitalization/styling updates (CSV export, extended public key, tools labels)

@HashEngineering HashEngineering self-assigned this Apr 13, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

📝 Walkthrough

Walkthrough

Centralizes icon access via MyImages, adds a DashSwitch composable, updates several UI components and previews to use MyImages, adjusts Menu/MenuItem visuals and parameters, migrates Tools/Settings fragments to Compose with a new ToolsScreen and ToolsUIState, and adds/removes multiple drawable and layout resources.

Changes

Cohort / File(s) Summary
Icon Resource Centralization
common/src/main/java/org/dash/wallet/common/ui/components/MyImages.kt, common/src/main/java/org/dash/wallet/common/ui/components/DashButton.kt, common/src/main/java/org/dash/wallet/common/ui/components/FeatureList.kt, common/src/main/java/org/dash/wallet/common/ui/components/FeatureTopText.kt, common/src/main/java/org/dash/wallet/common/ui/components/Template.kt, common/src/main/java/org/dash/wallet/common/ui/components/TopNavBase.kt
Added MyImages exposing composable ImageVector properties and replaced direct ImageVector.vectorResource(...) and resource imports across previews and nav helpers with MyImages.*.
New Switch & Component Tweaks
common/src/main/java/org/dash/wallet/common/ui/components/DashToggle.kt, common/src/main/java/org/dash/wallet/common/ui/components/Menu.kt, common/src/main/java/org/dash/wallet/common/ui/components/MenuItem.kt, common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt
Introduced DashSwitch composable (animated thumb, toggleable). Increased menu/container corner radii and adjusted spacings; MenuItem gains onInfoClick and trailingButtonStyle params and now uses DashSwitch. Updated two typography font weights.
Compose Migration: Tools & Settings
wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt, wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt, wallet/res/layout/fragment_tools.xml (deleted), wallet/res/layout/fragment_settings.xml (deleted)
Removed XML layouts; migrated ToolsFragment to Compose (now provides callbacks into new ToolsScreen); SettingsFragment switches to ComposeView with explicit dispose strategy.
New Tools Screen & State
wallet/src/de/schildbach/wallet/ui/more/ToolsScreen.kt, wallet/src/de/schildbach/wallet/ui/more/ToolsViewModel.kt
Added ToolsScreen composable overloads and preview; replaced isSyncing StateFlow with uiState: StateFlow<ToolsUIState> (isLoading, isSyncing, hasUsername) and updated ViewModel init to update _uiState.
Dialogs & Compose View Refinements
wallet/src/de/schildbach/wallet/ui/compose_views/ExportCSVDialog.kt, .../ExtendedPublicKeyDialog.kt, .../ZenLedgerDialog.kt, wallet/src/de/schildbach/wallet/ui/more/TransactionMetadataSettingsFragment.kt, common/src/main/java/org/dash/wallet/common/ui/components/DashButton.kt
Replaced inlined title/body with FeatureTopText, adjusted typography/paddings, set ComposeView disposal strategy in fragments, and updated DashButton previews to use MyImages icons.
MenuItem & Menu Visuals
common/src/main/java/org/dash/wallet/common/ui/components/MenuItem.kt, common/src/main/java/org/dash/wallet/common/ui/components/Menu.kt
Adjusted container radii, paddings, spacing, icon sizing, and column arrangement; added optional info icon click handling and trailing button style override.
Drawable Resources Added/Removed
common/src/main/res/drawable/ic_nav_bar_close.xml, .../ic_popup_close_circle.xml, .../ic_change_pin.xml, wallet/res/drawable/ic_autohide_balance.xml, ic_csv_export.xml, ic_fingerprint_blue.xml, ic_import_private_key.xml, ic_menu_address_book.xml, ic_menu_credits.xml, ic_menu_csv_export.xml, ic_menu_extended_public_key.xml, ic_menu_import_private_key.xml, ic_menu_masternode_keys.xml, ic_menu_network_monitor.xml, ic_view_rec_phrase.xml, ic_zenledger.xml, deleted wallet/res/drawable/ic_credits.xml
Added ~16 new vector drawables (most filled #008DE4, one #11D7A3) and removed ic_credits.xml.
Strings & Minor Logic Adjustments
wallet/res/values/strings.xml, wallet/res/values/strings-extra.xml, wallet/src/de/schildbach/wallet/ui/more/SettingsScreen.kt, common/src/main/java/org/dash/wallet/common/ui/dialogs/OffsetDialogFragment.kt
Standardized string capitalization and wording (e.g., extended public key text, CSV export). Adjusted CoinJoin off-condition to exclude FINISHING. Replaced dialog collapse setup to use an ImageButton with drawable and dismiss handler.

Sequence Diagram(s)

sequenceDiagram
    participant Fragment as ToolsFragment
    participant UI as ToolsScreen
    participant ViewModel as ToolsViewModel
    participant DAO as blockchainStateDao

    Fragment->>UI: mount ToolsScreen with callbacks
    UI->>ViewModel: collect uiState (collectAsState)
    ViewModel->>DAO: observeState() (onEach)
    DAO-->>ViewModel: emit blockchain state
    ViewModel-->>UI: update uiState (isSyncing / hasUsername)
    UI->>Fragment: user taps item (e.g., CSV export)
    Fragment->>ViewModel: perform action / navigate
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • abaranouski

Poem

🐰 I hopped new icons into MyImages with glee,

DashSwitch bounces, now sleek as can be.
From XML burrows to Compose bright air,
Drawables gleam and screens dance with flair! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: redesign tools menu' directly and clearly summarizes the main change: a comprehensive redesign of the tools menu interface from view-binding to Compose-based implementation with new UI components and updated styling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/update-tools-menu

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (5)
common/src/main/res/drawable/ic_change_pin.xml (1)

8-8: Prefer color resource over hardcoded hex in vector fill

Use a color resource (or theme-based tint at usage site) instead of #008DE4 to keep dark/light theming and branding updates centralized.

Proposed change
-      android:fillColor="#008DE4"/>
+      android:fillColor="@color/dash_blue"/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@common/src/main/res/drawable/ic_change_pin.xml` at line 8, Replace the
hardcoded hex fillColor in the vector drawable by referencing a color resource
or theme attribute instead of "#008DE4"; create or reuse an appropriate color
resource (e.g., color/ic_change_pin or a theme attribute like
?attr/colorPrimaryVariant) and update the android:fillColor on ic_change_pin.xml
to point to that resource so theming/dark mode and branding changes are
centralized.
wallet/res/drawable/ic_view_rec_phrase.xml (1)

7-8: Consider using a color resource reference instead of a hardcoded hex value.

The fillColor uses a hardcoded color value #008DE4. For better maintainability and theming support, consider defining this color in colors.xml and referencing it here using @color/your_color_name. This approach:

  • Ensures color consistency across the app
  • Supports theme switching (light/dark mode)
  • Makes future color updates easier
♻️ Proposed refactor

First, add the color to your colors.xml file:

<color name="icon_blue">#008DE4</color>

Then update the drawable:

-      android:fillColor="#008DE4"/>
+      android:fillColor="@color/icon_blue"/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wallet/res/drawable/ic_view_rec_phrase.xml` around lines 7 - 8, Replace the
hardcoded fillColor in the vector drawable by creating a color resource (e.g.,
add <color name="icon_blue">#008DE4</color> to colors.xml) and update the
android:fillColor attribute in ic_view_rec_phrase.xml to reference that resource
(android:fillColor="@color/icon_blue") so the Path's fillColor uses the new
color resource instead of the literal hex.
common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt (1)

257-262: Validate FontWeight(750) mapping for the Inter family.

Using FontWeight(750) at Line 261 can render inconsistently if the font set doesn’t include a matching weight. Consider sticking to a known shipped weight (e.g., 700) or adding an explicit heavier Inter variant and mapping it directly.

Suggested adjustment
 val HeadlineSmallBold = TextStyle(
     fontSize = 24.sp,
     lineHeight = 32.sp,
     fontFamily = interBold,
-    fontWeight = FontWeight(750)
+    fontWeight = FontWeight(700)
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt` around
lines 257 - 262, The TextStyle HeadlineSmallBold in MyTheme.kt uses
FontWeight(750) which may not map to an available Inter weight; replace the
ad-hoc 750 with a shipped weight (e.g., use the w700/w800 constant or
FontWeight(700)) or add and reference an explicit heavier Inter font resource
(e.g., interExtraBold) and switch interBold to that variant; alternatively, if
you must keep 750 ensure the Inter font family includes a matching
FontWeight(750) entry so the mapping is deterministic.
wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt (1)

79-84: Prefer registering viewLifecycleOwner observers in onViewCreated().

setupTransactionMetadataObservers() is called at Line 82 during onCreateView. Moving this to onViewCreated() keeps view-lifecycle observer setup in the canonical lifecycle callback and avoids edge-case timing ambiguity.

Proposed lifecycle-safe placement
 override fun onCreateView(
     inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
 ): View {
-    setupTransactionMetadataObservers()
-
     return ComposeView(requireContext()).apply {
         setContent {
             SettingsScreen(
                 ...
             )
         }
     }
 }
+
+override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+    super.onViewCreated(view, savedInstanceState)
+    setupTransactionMetadataObservers()
+}

Also applies to: 145-159

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt` around lines 79 - 84,
The observer registration call setupTransactionMetadataObservers() (and any
other view-lifecycle observer setup done in onCreateView(), e.g., the block
noted around lines 145-159) should be moved from onCreateView to onViewCreated
so observers are bound to viewLifecycleOwner; remove the
setupTransactionMetadataObservers() invocation from onCreateView() and call it
in override fun onViewCreated(view: View, savedInstanceState: Bundle?) using
viewLifecycleOwner when observing LiveData/Flow to ensure lifecycle-safe binding
and avoid timing edges.
wallet/src/de/schildbach/wallet/ui/compose_views/ExportCSVDialog.kt (1)

166-167: Avoid composing localized body copy with hardcoded "\n\n" in code.

Building the paragraph body via string concatenation limits translator control over ordering and formatting. Prefer a single localized resource for the full body text.

Proposed adjustment
-            text = "${stringResource(R.string.report_transaction_history_body_1)}\n\n${stringResource(R.string.report_transaction_history_body_2)}",
+            text = stringResource(R.string.report_transaction_history_body),

Also add report_transaction_history_body in resources with the intended paragraph break.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wallet/src/de/schildbach/wallet/ui/compose_views/ExportCSVDialog.kt` around
lines 166 - 167, In ExportCSVDialog.kt replace the concatenated body using
stringResource(R.string.report_transaction_history_body_1) + "\n\n" +
stringResource(R.string.report_transaction_history_body_2) with a single
stringResource call (e.g.
stringResource(R.string.report_transaction_history_body)) to avoid hardcoded
paragraph breaks; update the Compose call (where text = ... and TextAlign.Start
is used) to use that single resource and add a new localized resource key
report_transaction_history_body containing the full paragraph with the intended
break so translators control ordering/formatting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@common/src/main/java/org/dash/wallet/common/ui/components/DashToggle.kt`:
- Around line 86-95: The Box modifier currently uses Modifier.clickable which
exposes only generic button semantics; replace that clickable(...) with
Modifier.toggleable(value = checked, role = Role.Switch, enabled = enabled,
interactionSource = remember { MutableInteractionSource() }, indication = null,
onValueChange = { onCheckedChange?.invoke(it) }) so TalkBack/VoiceOver receive
proper toggle semantics and state; update imports to include
androidx.compose.foundation.selection.toggleable and
androidx.compose.ui.semantics.Role (or appropriate Role import) and ensure you
keep minimumInteractiveComponentSize() and contentAlignment unchanged.

In `@wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt`:
- Around line 168-172: The code in ToolsFragment.kt currently logs the full xpub
in the onCopy handler (log.info("xpub copied to clipboard: {}",
viewModel.xpub)), which exposes sensitive wallet metadata; update the onCopy
lambda (the block that calls viewModel.copyXpubToClipboard()) to remove the raw
xpub from logs—either log a generic message like "xpub copied to clipboard" or,
if you need some traceability, log only a masked/partial value (e.g., first/last
N chars) computed from viewModel.xpub before logging—do not write the full xpub
to logs.
- Around line 66-84: The ComposeView in ToolsFragment.onCreateView currently
uses the default composition strategy; update the ComposeView creation to set an
explicit lifecycle-aware composition strategy (call setViewCompositionStrategy
with ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) before
invoking setContent so the composition is disposed when the fragment view is
destroyed, preventing leaked collectors/callbacks.

In `@wallet/src/de/schildbach/wallet/ui/more/ToolsScreen.kt`:
- Around line 134-138: The inner scrollable Column in ToolsScreen.kt uses
Modifier.fillMaxSize(), which causes it to request the full height and can
produce layout overflow; replace that call with Modifier.weight(1f) (keeping the
verticalScroll(rememberScrollState()) and other modifiers) so the Column only
consumes the remaining space between NavBarBack/TopIntro and avoids overflow.
Locate the Column with verticalScroll(...) and change its Modifier chain to use
weight(1f) instead of fillMaxSize().

In `@wallet/src/de/schildbach/wallet/ui/more/ToolsViewModel.kt`:
- Around line 101-103: The flow returned by blockchainStateDao.observeState() is
not being collected so the onEach block never runs; fix by collecting the flow
(e.g., append a terminal operator such as .launchIn(viewModelScope) or use
viewModelScope.launch { blockchainStateDao.observeState().onEach { ...
}.collect() }) so that the onEach updates _uiState.value with
uiState.value.copy(isSyncing = it?.isSynced() != true) and the isSyncing flag
reflects actual sync state; target the pipeline starting at
blockchainStateDao.observeState() and the onEach that updates _uiState/uiState.

---

Nitpick comments:
In `@common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt`:
- Around line 257-262: The TextStyle HeadlineSmallBold in MyTheme.kt uses
FontWeight(750) which may not map to an available Inter weight; replace the
ad-hoc 750 with a shipped weight (e.g., use the w700/w800 constant or
FontWeight(700)) or add and reference an explicit heavier Inter font resource
(e.g., interExtraBold) and switch interBold to that variant; alternatively, if
you must keep 750 ensure the Inter font family includes a matching
FontWeight(750) entry so the mapping is deterministic.

In `@common/src/main/res/drawable/ic_change_pin.xml`:
- Line 8: Replace the hardcoded hex fillColor in the vector drawable by
referencing a color resource or theme attribute instead of "#008DE4"; create or
reuse an appropriate color resource (e.g., color/ic_change_pin or a theme
attribute like ?attr/colorPrimaryVariant) and update the android:fillColor on
ic_change_pin.xml to point to that resource so theming/dark mode and branding
changes are centralized.

In `@wallet/res/drawable/ic_view_rec_phrase.xml`:
- Around line 7-8: Replace the hardcoded fillColor in the vector drawable by
creating a color resource (e.g., add <color name="icon_blue">#008DE4</color> to
colors.xml) and update the android:fillColor attribute in ic_view_rec_phrase.xml
to reference that resource (android:fillColor="@color/icon_blue") so the Path's
fillColor uses the new color resource instead of the literal hex.

In `@wallet/src/de/schildbach/wallet/ui/compose_views/ExportCSVDialog.kt`:
- Around line 166-167: In ExportCSVDialog.kt replace the concatenated body using
stringResource(R.string.report_transaction_history_body_1) + "\n\n" +
stringResource(R.string.report_transaction_history_body_2) with a single
stringResource call (e.g.
stringResource(R.string.report_transaction_history_body)) to avoid hardcoded
paragraph breaks; update the Compose call (where text = ... and TextAlign.Start
is used) to use that single resource and add a new localized resource key
report_transaction_history_body containing the full paragraph with the intended
break so translators control ordering/formatting.

In `@wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt`:
- Around line 79-84: The observer registration call
setupTransactionMetadataObservers() (and any other view-lifecycle observer setup
done in onCreateView(), e.g., the block noted around lines 145-159) should be
moved from onCreateView to onViewCreated so observers are bound to
viewLifecycleOwner; remove the setupTransactionMetadataObservers() invocation
from onCreateView() and call it in override fun onViewCreated(view: View,
savedInstanceState: Bundle?) using viewLifecycleOwner when observing
LiveData/Flow to ensure lifecycle-safe binding and avoid timing edges.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d47800d3-e406-4a32-989d-209b6a408ea3

📥 Commits

Reviewing files that changed from the base of the PR and between 02a2203 and 19095df.

📒 Files selected for processing (40)
  • common/src/main/java/org/dash/wallet/common/ui/components/DashButton.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/DashToggle.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/FeatureList.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/FeatureTopText.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/Menu.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/MenuItem.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/MyImages.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/Template.kt
  • common/src/main/java/org/dash/wallet/common/ui/components/TopNavBase.kt
  • common/src/main/java/org/dash/wallet/common/ui/dialogs/OffsetDialogFragment.kt
  • common/src/main/res/drawable/ic_change_pin.xml
  • common/src/main/res/drawable/ic_nav_bar_close.xml
  • common/src/main/res/drawable/ic_popup_close_circle.xml
  • wallet/res/drawable/ic_autohide_balance.xml
  • wallet/res/drawable/ic_credits.xml
  • wallet/res/drawable/ic_csv_export.xml
  • wallet/res/drawable/ic_fingerprint_blue.xml
  • wallet/res/drawable/ic_import_private_key.xml
  • wallet/res/drawable/ic_menu_address_book.xml
  • wallet/res/drawable/ic_menu_credits.xml
  • wallet/res/drawable/ic_menu_csv_export.xml
  • wallet/res/drawable/ic_menu_extended_public_key.xml
  • wallet/res/drawable/ic_menu_import_private_key.xml
  • wallet/res/drawable/ic_menu_masternode_keys.xml
  • wallet/res/drawable/ic_menu_network_monitor.xml
  • wallet/res/drawable/ic_view_rec_phrase.xml
  • wallet/res/drawable/ic_zenledger.xml
  • wallet/res/layout/fragment_settings.xml
  • wallet/res/layout/fragment_tools.xml
  • wallet/res/values/strings-extra.xml
  • wallet/res/values/strings.xml
  • wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/ExportCSVDialog.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/ExtendedPublicKeyDialog.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/ZenLedgerDialog.kt
  • wallet/src/de/schildbach/wallet/ui/more/SettingsScreen.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsScreen.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsViewModel.kt
💤 Files with no reviewable changes (3)
  • wallet/res/drawable/ic_credits.xml
  • wallet/res/layout/fragment_settings.xml
  • wallet/res/layout/fragment_tools.xml

Comment thread wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt
Comment thread wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt
Comment thread wallet/src/de/schildbach/wallet/ui/more/ToolsScreen.kt
Comment thread wallet/src/de/schildbach/wallet/ui/more/ToolsViewModel.kt Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt (1)

80-85: ⚠️ Potential issue | 🔴 Critical

Move transaction metadata observer setup out of onCreateView().

setupTransactionMetadataObservers() accesses viewLifecycleOwner at lines 153–154, but it is called from onCreateView() at line 83. This violates the Android Fragment lifecycle contract and will throw IllegalStateException because the view lifecycle owner is not available until onViewCreated() is called.

Suggested fix
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
     ): View {
-        setupTransactionMetadataObservers()
-
         return ComposeView(requireContext()).apply {
             setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
             setContent {
                 SettingsScreen(
@@
         }
     }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+        setupTransactionMetadataObservers()
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt` around lines 80 - 85,
The call to setupTransactionMetadataObservers() is made from onCreateView() but
it uses viewLifecycleOwner (in setupTransactionMetadataObservers()), which isn't
available until the view is created; move the observer setup call into
onViewCreated() (override onViewCreated and call
setupTransactionMetadataObservers() there) so
setupTransactionMetadataObservers() runs with a valid viewLifecycleOwner and
avoid the IllegalStateException.
♻️ Duplicate comments (1)
wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt (1)

166-174: ⚠️ Potential issue | 🟠 Major

Remove the raw xpub from logs.

This callback still writes the full extended public key to logs. That is sensitive wallet metadata and should not end up in logcat or exported diagnostics.

Suggested fix
             onCopy = {
                 viewModel.copyXpubToClipboard()
                 Toast(requireContext()).toast(R.string.copied)
-                log.info("xpub copied to clipboard: {}", viewModel.xpub)
+                log.info("xpub copied to clipboard")
             },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt` around lines 166 -
174, In handleExtendedPublicKey's onCopy callback (inside
createExtendedPublicKeyDialog) you're logging the full extended public key via
log.info with viewModel.xpub; remove that raw xpub from logs and either drop the
log call entirely or replace it with a non-sensitive indicator (e.g., log only a
redacted substring, suffix like "xpub copied (redacted)", or a hash/fingerprint)
so the full viewModel.xpub is never written to logcat or exported diagnostics.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt`:
- Around line 80-85: The call to setupTransactionMetadataObservers() is made
from onCreateView() but it uses viewLifecycleOwner (in
setupTransactionMetadataObservers()), which isn't available until the view is
created; move the observer setup call into onViewCreated() (override
onViewCreated and call setupTransactionMetadataObservers() there) so
setupTransactionMetadataObservers() runs with a valid viewLifecycleOwner and
avoid the IllegalStateException.

---

Duplicate comments:
In `@wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt`:
- Around line 166-174: In handleExtendedPublicKey's onCopy callback (inside
createExtendedPublicKeyDialog) you're logging the full extended public key via
log.info with viewModel.xpub; remove that raw xpub from logs and either drop the
log call entirely or replace it with a non-sensitive indicator (e.g., log only a
redacted substring, suffix like "xpub copied (redacted)", or a hash/fingerprint)
so the full viewModel.xpub is never written to logcat or exported diagnostics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46c89323-08ae-4223-8352-b80b4cf1c870

📥 Commits

Reviewing files that changed from the base of the PR and between 19095df and 278373f.

📒 Files selected for processing (6)
  • common/src/main/java/org/dash/wallet/common/ui/components/DashToggle.kt
  • wallet/src/de/schildbach/wallet/ui/SettingsFragment.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsScreen.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsViewModel.kt
  • wallet/src/de/schildbach/wallet/ui/more/TransactionMetadataSettingsFragment.kt
🚧 Files skipped from review as they are similar to previous changes (3)
  • common/src/main/java/org/dash/wallet/common/ui/components/DashToggle.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsViewModel.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsScreen.kt

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt (1)

166-196: ⚠️ Potential issue | 🟠 Major

Do not log the raw xpub from the share flow.

onShare still routes the full extended public key into createAndLaunchShareIntent(), which logs it on Line 195. That leaks sensitive wallet metadata even though the copy path was already sanitized.

Suggested fix
     private fun createAndLaunchShareIntent(xpub: String) {
         val intent = Intent(Intent.ACTION_SEND)
         intent.type = "text/plain"
         intent.putExtra(Intent.EXTRA_TEXT, xpub)
         intent.putExtra(
             Intent.EXTRA_SUBJECT,
             getString(R.string.extended_public_key_fragment_title)
         )
         startActivity(
             Intent.createChooser(
                 intent,
                 getString(R.string.extended_public_key_fragment_share)
             )
         )
-        log.info("xpub shared via intent: {}", xpub)
+        log.info("xpub shared via intent")
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt` around lines 166 -
196, The share flow currently passes the full xpub into
createAndLaunchShareIntent(xpub: String) and then logs it in log.info("xpub
shared via intent: {}", xpub), leaking sensitive data; update
handleExtendedPublicKey/createAndLaunchShareIntent so the raw xpub is not logged
(either remove the log or replace it with a non-sensitive message such as
logging that an xpub was shared without including the key), and ensure onShare
does not pass the raw xpub into any logger or persistent store—use a
masked/placeholder value or no-value logging instead while retaining the intent
construction and startActivity behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt`:
- Around line 166-196: The share flow currently passes the full xpub into
createAndLaunchShareIntent(xpub: String) and then logs it in log.info("xpub
shared via intent: {}", xpub), leaking sensitive data; update
handleExtendedPublicKey/createAndLaunchShareIntent so the raw xpub is not logged
(either remove the log or replace it with a non-sensitive message such as
logging that an xpub was shared without including the key), and ensure onShare
does not pass the raw xpub into any logger or persistent store—use a
masked/placeholder value or no-value logging instead while retaining the intent
construction and startActivity behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d4ad5c69-25de-43cd-946b-ac9eadb6fc49

📥 Commits

Reviewing files that changed from the base of the PR and between 278373f and c619deb.

📒 Files selected for processing (6)
  • wallet/src/de/schildbach/wallet/ui/compose_views/ComposeBottomSheet.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/CreateInstantUsernameDialog.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/ExtendedPublicKeyDialog.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/ImportPrivateKeyDialog.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/WalletCreationDateInfoDialog.kt
  • wallet/src/de/schildbach/wallet/ui/more/ToolsFragment.kt
💤 Files with no reviewable changes (3)
  • wallet/src/de/schildbach/wallet/ui/compose_views/WalletCreationDateInfoDialog.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/CreateInstantUsernameDialog.kt
  • wallet/src/de/schildbach/wallet/ui/compose_views/ImportPrivateKeyDialog.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • wallet/src/de/schildbach/wallet/ui/compose_views/ExtendedPublicKeyDialog.kt

@HashEngineering HashEngineering merged commit 3ff9e10 into master Apr 20, 2026
3 checks passed
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