Commit Graph

29 Commits

Author SHA1 Message Date
dae677acd8 feat(send): migrate the Confirm-Send modal to the reference design
Presentation-only migration of RenderSendConfirmPopup (the confirm-before-broadcast
popup) — a fund-moving modal:
- struct-form BeginOverlayDialog(OverlayDialogSpec{BlurFloat, cardWidth popupW,
  idSuffix confirmsend}) replacing the legacy positional overload; p_open stays
  nullptr (the popup keeps its own Escape + Cancel handling)
- TR() the one hardcoded status string in the synchronous live-revalidation guard
  ("Cannot send now …") -> new send_cannot_send_now key, 8 langs (em-dash preserved)

The fund path is byte-for-byte unchanged: the live re-validation guard, the
app->sendTransaction call + its success/failure callback, the lite-locked
requestLiteUnlock branch, the s_sending/s_show_confirm state, the Escape handler,
and the FROM/TO cards + fee-tier/summary rendering.

Verified: build + ctest + hygiene clean; a 2-lens adversarial review
(fund-path-untouched / ui-i18n) returned zero findings, with the fund-path lens
proving the send path diffs byte-for-byte identical to HEAD.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 17:58:11 -05:00
e7a3f90102 feat(ui): float all modals card-less like Manage Portfolio
Drop the glass card + boxed title bar from every dialog so content floats
directly on the blur backdrop under a plain h6 heading — the Manage-Portfolio
look — unifying the whole modal system on one visual language (reverses the
earlier card-for-small / float-for-large split).

- Framework: the positional BeginOverlayDialog overload (used by all ~34 card
  dialogs) now defaults to floatingContent + plainHeading (draw_helpers.h). The
  9 spec-form BlurFloat dialogs are unchanged; any dialog can still opt back to a
  card via an explicit OverlayStyle::GlassCard spec. Authored widths are kept
  (floating never resizes), so width-coupled layouts are unaffected.
- Dedup: the framework h6 title made each dialog's own repeated title heading
  redundant. Removed the duplicate body heading from Import/Export key, Backup,
  daemon update, seed backup, seed migration, Defender-blocked (app.cpp),
  Wallets, and the send-confirm popup.
- Close paths: dropping the title-bar close X is covered — every dialog has a
  footer button and/or the framework's outside-click dismiss (all pass p_open);
  send-confirm keeps Esc + Confirm/Cancel.

Verified via the headless full UI sweep on dark + light: 17 modal surfaces float
card-less with a single clean heading, nothing clipped, close controls present.
Build clean, ctest passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 21:57:04 -05:00
6c19fac6f5 fix(ui): DPI-scale hand-drawn overlays + freeze sweep demo state
Hand-drawn absolute geometry (dl->AddText offsets, SetNextWindowSize,
explicit ImVec2 button widths, SameLine strides) is immune to the app's
DPI machinery (font-atlas rebuild + ScaleAllSizes), so several overlays
rendered native-size (tiny) on HiDPI / Windows 150% displays. Multiply the
raw logical-px geometry by Layout::dpiScale():

- seed_display: content-aware, DPI-scaled seed-grid column stride (a raw
  130px stride let words collide with the next column's index at 150%)
- lock screen: card/logo/input/unlock-button + all vertical offsets
- migrate-to-seed + seed-backup dialogs: button widths
- send-confirm: confirm/cancel button widths
- about dialog: value-column x, edition inset, link/close button widths
- chat conversation list: row height + padding (fixes the preview clip)

Also freeze demo state during the full UI sweep: guard App::update() on
capture_mode_ so a running daemon's refresh can't clobber the injected
demo state (it blanked Send/Receive/History with a CDB error mid-sweep).

Verified on Windows 4K@150% and locally at font_scale=1.5 (same
dpiScale()==1.5 code path). Adds a DPI-scaling convention note to CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 18:58:54 -05:00
a86cb8f0f3 feat(debug): full UI screenshot sweep — captures modals/dialogs/flows/states
The existing sweep only captures tabs. This adds a "Full UI sweep" (DEBUG
OPTIONS) that also drives every normally-hidden surface into view and captures
it under every skin, so all the UI a normal sweep misses can be reviewed at
once.

- The capture unit becomes a "surface" (SweepTarget: a base tab, optionally
  with a setup()/teardown() that forces a modal / multi-step flow / state
  overlay on top). Tabs are surfaces with a null setup. The existing tab sweep
  is folded into the same state machine (one code path). All sweep logic +
  the catalog + demo data move into a new src/app_sweep.cpp.
- Runs OFFLINE against injected demo data (installDemoWalletData snapshots then
  restores the real state_ — WalletState isn't copy-assignable, so a targeted
  field snapshot is used) and fires NO live op: capture_mode_ guards the
  seed-backup RPC, auto-lock, and the migration pumps; the async-firing dialogs
  are neutralized by pre-setting their state (fetch_started_ + demo phrase;
  seed_migration_step_ set directly). Verified: 0 RPC/secret/send calls.
- Catalog (v1): tabs + the bool-flag modals (import/export key, backup,
  seed-backup, about, settings) + the 6 migrate-to-seed steps + 4 wizard steps
  + lock/warmup/not-ready overlays + the send-confirm popup (via a new
  ui::SweepShowSendConfirm debug hook, since its state is send_tab-static).
- Overlay/blur surfaces settle 8 frames (blur backdrop freeze); setup re-runs
  each frame (OpenPopup popups must re-fire). updateScreenshotSweep now runs
  before the first-run-wizard early-return in render() so the sweep advances
  while a wizard step is shown. main.cpp drops vsync during a sweep so it isn't
  throttled to the compositor's unfocused rate. Output:
  <config>/screenshots-full/<surface>/<skin>.png + index.md.
- DRAGONX_FULL_SWEEP=1 runs the sweep headlessly then quits (CI / verification).

Verified end-to-end under WSLg: 288 PNGs (9 skins x 32 surfaces), all 1200x720,
[Sweep] done, clean quit, no daemon. Byte-identity across runs holds only for
static skins on data-free surfaces — the rest vary by animated theme effects /
live price / relative timestamps (expected for a review tool, not a bug).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 16:57:54 -05:00
ddd53dc006 feat(send): add a shared contact picker to the recipient field
Phase 0c. The Send recipient field only offered Paste and a tx-history
suggestion list — no way to pick a saved contact. Add a compact contacts
icon button next to Paste that opens a picker popup over the App-owned
address book; selecting a contact fills the recipient (re-validated next
frame).

- New header-only src/ui/windows/contact_picker.h: ContactPickerPopup(id,
  book, outBuf, outSz) — a reusable popup listing contacts ([Z]/[T] tag +
  label + short address) that copies the chosen address into the caller's
  buffer. Kept out of the material layer so the design-system headers stay
  free of data/ deps; reserved for Chat "new conversation" later.
- send_tab: shrink the recipient input to make room for the icon button
  (ICON_MD_CONTACTS), wire the popup to app->addressBook(). Coexists with the
  existing Paste + suggestion affordances.
- i18n: send_contacts_button tooltip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 17:04:58 -05:00
658c0f355b fix(ui): validate and clamp dialog input
Tighten input handling across several dialogs so bad/edge input can't
produce a doomed request or a confusing display:

- app_security: passphrase strength meter now factors character-class
  diversity — an all-one-class string downgrades one tier so "aaaaaaaa"
  no longer scores as high as a mixed one.
- block_info: clamp the height field to the chain tip and hide/deny
  "Next" at the tip (was only yielding a raw RPC error).
- address_label: trim surrounding whitespace before saving; a
  whitespace-only label clears it (mirrors clearing the icon).
- send_tab: re-clamp the amount when a Max send has its fee bumped in the
  confirm popup (kept the total within budget) and NUL-terminate the
  strncpy'd address/memo when a payment URI overwrites the form.
- settings_page: reject an empty/whitespace-only lite wallet path before
  dispatching an unusable open/restore request.
- peers_tab: guard ExtractIP against an empty address.
- transaction_details: disable "View in explorer" when the configured
  explorer URL is empty/whitespace so we never open a garbage link.
- app: seed-backup "Skip" now requires a second, deliberate click with a
  fund-loss warning before it dismisses.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 15:08:59 -05:00
dd9bc0bd2b fix: Tier-2 involved mediums — send confirm re-validation + console JSON errors
- Send: re-validate against LIVE state at the "Confirm & Send" click (connected,
  not syncing, amount > 0, total <= available). The confirm dialog persists
  across frames, so a balance drop / sync restart / fee bump after Review could
  otherwise broadcast a now-invalid transaction; it now shows a clear message
  instead of sending.
- Console: a malformed JSON argument ({...}/[...] that fails to parse) was
  silently sent to the daemon as a plain string. Now the command fails with a
  clear "Argument N is not valid JSON" line instead of being silently mangled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 14:00:16 -05:00
b2a8c4487e fix: Tier-2 quick mediums — view-only guard, memo counter, updater/close guards
- Send: block Review from a view-only source (no spending key) with a tooltip,
  instead of failing at submit; label the memo counter as bytes and warn in
  colour once the field hits its cap (Sapling memos are byte-limited).
- Shield: show "No shielded (z) address yet — create one on the Receive tab
  first" when the destination combo is empty, instead of an empty dropdown.
- Updater dialogs (xmrig/daemon): suppress the window X during an active
  download/verify/extract so closing can't orphan/block on the worker — the
  in-dialog Cancel is the way to abort.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 13:54:55 -05:00
65bb98cd09 fix: Tier-2 mediums — input trims, confirmations, amount normalization
More robustness fixes from the audit (the import-key pattern, lower severity):

- Trim pasted input before use/validation: network add-server URL/label,
  lite-wallet key import (+ block empty), validate-address, address-book entry.
- Confirmations for destructive/irreversible actions:
  - Address-book Delete now needs a confirming second click (no undo).
  - Console `stop` needs a confirming second `stop` (it shuts down the node).
  - Wizard "Skip" encryption needs a confirming second click (keys stored
    unencrypted).
- Send amount: normalize to 8dp (satoshi precision) on both the DRGX and USD
  inputs so digits past 8dp aren't silently dropped between the preview/review
  and what's actually sent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 13:18:57 -05:00
7249d11899 feat(ui): clamp recent-activity lists to the 4 most recent
The overview "Recent Transactions" and the send tab "Recent Sends" lists showed
every matching transaction in a scroll region. Cap them at the 4 most recent
(state.transactions is sorted newest-first, so a simple head-limit). The receive
"Recent Received" list gets the same clamp in the Tier-1 robustness commit
(same file as the QR fix).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 12:53:46 -05:00
1c5bc0d4d6 fix(theme): per-skin legibility polish from the sweep review
Address the high-severity, systemic legibility issues found in the per-skin
screenshot review (verified across all 9 skins):

- Status pills (history): "Confirmed" text was 55%-alpha (dim); make it full
  opacity, and give status/shield pills a visible tinted fill (a48) + 1px border
  (a90) so they stop vanishing on dark-red / near-white / gradient skins.
- Console light theming: light skins now use a near-white terminal surface, and
  the log text/JsonBrace colors switch to the dark defaults in light themes (the
  schema colors are dark-terminal-authored — honor them only in dark themes) so
  text isn't pale-on-white.
- Dark-skin muted text: bump --on-surface-medium 0.85 / --on-surface-disabled
  0.58 on dragonx/dark/color-pop-dark/obsidian (obsidian addresses were ~1.1:1).
- Disabled Send button: the disabled fill was hardcoded white (invisible on
  light skins) — use a dark overlay in light themes.
- Light-skin inputs: stronger frame fill + border color and a 1px frame border
  for light themes so fields (and buttons) have defined boundaries on white/
  pastel surfaces.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 23:33:48 -05:00
de11850c74 refactor(audit): batch 4 — UI design-system helpers + i18n
Mechanical, behavior-preserving consolidations from the audit. Rendering
extractions were kept byte-equivalent; sites that couldn't be made identical
were left as-is (noted below).

Shared helpers:
- util::truncateMiddle(s,maxLen) / (s,front,back) in text_format.h — replaces
  6 file-local middle-ellipsis truncators + several inline substr sites
  (send/receive/transactions/balance_recent_tx/explorer + app.cpp + 3 dialogs).
  Carries the maxLen<=3 guard, fixing the latent unsigned-underflow copies.
- material::LoadingDots() in draw_helpers.h — one animated-ellipsis source for
  8 copy-pasted spinner sites (identical GetTime()*3 phase preserved).
- Reuse the existing FormatHashrate() in explorer_tab + peers_tab (dropped two
  inline hashrate ladders).
- material::DrawButtonGlassOverlay() — the glass-fill/rim/tactile overlay block
  shared by TactileButton / TactileSmallButton / schema TactileButton.
- material::CollapsibleHeader() — the invisible-button + label + chevron idiom
  (3 of 5 settings_page sites; RPC/Debug headers skipped — non-identical).
- material::GlassCardScope (RAII) — the ChannelsSplit/Indent/DrawGlassPanel/
  ChannelsMerge card scaffold (5 settings_page cards; About/send/receive skipped
  — different padding / logo interleaving).
- material::DialogWarningHeader()/DialogConfirmFooter() — warning header +
  50/50 Cancel/danger footer across the confirm dialogs; button height moved
  from a hardcoded 40px into ui.toml (components.overlay-dialog.confirm-btn-height).
- File-local enterLowSpec()/exitLowSpec() collapse the 3 low-spec snapshot copies.

i18n: wrapped hardcoded English in the shared balance render paths and the
whole Lite lifecycle/security section in TR(), with English defaults added to
loadBuiltinEnglish() (res/lang/*.json left for the translation tooling — TR
falls back to English, so output is unchanged).

Full-node + Lite build clean; ctest 1/1; hygiene clean. These are rendering
changes — the Settings page (cards/headers/confirm dialogs), all tactile
buttons, and the Lite settings section warrant a screenshot check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 17:29:12 -05:00
f8150434d4 fix(audit): batch 1 — latent unlock/path/rescan correctness bugs
Four correctness fixes surfaced by the codebase audit:

1. Lite address-book path bug: AddressBook::getDefaultPath() hardcoded
   "ObsidianDragon" while Settings::getDefaultPath() uses DRAGONX_APP_NAME,
   so the Lite build wrote addressbook.json into the full-node app's config
   dir instead of ObsidianDragonLite/. Now uses DRAGONX_APP_NAME on all
   platforms (no macOS path change — the getConfigDir consolidation, which
   would move the macOS dir, is deferred).

2. PIN-unlock lockout bypass: the PIN path duplicated unlockWallet's
   success/lockout logic and its RPC-error branch bumped the attempt counter
   but skipped the escalating-lockout math entirely — a PIN user hitting an
   RPC error escaped the lockout curve. Extracted App::applyUnlockSuccess()
   and App::applyUnlockFailure() and routed all unlock paths (passphrase,
   PIN vault-fail, PIN RPC-fail) through them, so the lockout curve now
   applies uniformly. (noVault stays a mode-switch, not a failed attempt.)

3. Witness/rescan reset drift: the ~11-line rescan+witness completion reset
   was copy-pasted at four sites (app.cpp x2, app_network.cpp x2); adding a
   witness field and missing a copy would leave stale progress. Folded into
   App::resetWitnessRescanProgress(). Left the distinct phase-transition
   reset in App::update() untouched (it sets witness_phase, not 0).

4. Truncation underflow: send_tab/receive_tab's size_t TruncateAddress
   copies computed (maxLen - 3) without guarding maxLen <= 3, which wraps
   and throws std::out_of_range on short inputs. Added the guard.

Full-node + Lite build clean; ctest 1/1; source-hygiene clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 15:54:36 -05:00
2e8e214689 refactor(ui): app-wide compact, translucent tooltips
Add material::Tooltip / BeginTooltip / EndTooltip wrappers (tooltip_style.h)
that scope a small window padding (8x4, dpi-scaled) and ~85% opacity to
tooltips only, then route the tooltip call sites through them. Menus and combo
dropdowns are untouched (they keep the global opaque PopupBg).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 21:26:52 -05:00
e40962cdf2 perf(ui): dedupe time-ago + allocation-free case-insensitive filter (audit #1-3)
Per-frame hot paths in the immediate-mode UI were allocating needlessly:

- Address filtering in the balance tab rebuilt a std::string filter per address AND
  containsIgnoreCase() lower-cased two fresh copies per call — ~6×N allocations/frame
  on large wallets. New util::containsIgnoreCase(string_view, string_view) is
  allocation-free, and the filter is now built once outside the loop.
- Four duplicated "time ago" implementations (balance_tab_helpers, balance_recent_tx,
  send_tab, transactions_tab) are consolidated into util::formatTimeAgo (localized long
  form) + util::formatTimeAgoShort (compact "5s ago"), preserving each call site's exact
  display style. Both use snprintf, no per-row string concatenation.
- The send-tab address-suggestion scan (a walk over the whole tx list) is memoized on the
  typed text + tx count, so it no longer recomputes every frame while the user pauses.

New src/util/text_format.{h,cpp}; the two existing containsIgnoreCase/timeAgo definitions
now delegate to it. Added to both the app and test targets (test target also gains i18n.cpp,
which text_format's localized path needs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 13:54:27 -05:00
070a516f4e fix(send): validate recipient address checksums (Base58Check + Bech32)
The send screen labelled any prefix+length match as a "Valid" address, so a
mistyped address that still matched the pattern passed the gate. Add pure,
offline checksum validation — Base58Check (transparent R-addresses) and Bech32
(Sapling zs-addresses) — and require it in the validity check. Both verifiers are
version-byte/HRP agnostic (the HRP is taken from the string, the Base58 checksum
is chain-independent), so a correct implementation never rejects a genuine
address while catching transcription errors. Works for both build variants
(no daemon round-trip), unit-tested against standard BIP173 / Base58Check vectors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:43:34 -05:00
6ed80d2d79 fix(send): result-driven status styling + full-precision USD preview
The transaction-status overlay decided error vs. success styling by searching the
status string for "Error"/"Failed" — so under a non-English locale a failed send
rendered as a green success. Drive it from the existing s_status_success flag
instead. Also show the USD-mode DRGX preview at 8 dp so it matches the confirm
panel and the amount actually sent (was 4 dp).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:25:43 -05:00
8f22db5eea fix(send): resolve source balance by address, not list index
GetAvailableBalance() read state.addresses[s_selected_from_idx], but the index
desyncs from s_from_address (the value actually debited) after an address-list
refresh, and is left at -1 when the source is chosen from another tab's "Send
from this address" — which made the sufficiency check see a 0 balance and wrongly
block a valid send. Look the balance up by matching the source address string.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:18:16 -05:00
3799330bb0 fix(ui): show real data and consistent values across tabs
- Market chart now plots the real accumulated price_history instead of a
  rand()-generated curve; the hover tooltip no longer claims a specific "Xh ago"
  price and the x-axis only labels the truthful "Now" point. Falls back to the
  existing empty state until there are >=2 real samples.
- Transactions summary cards exclude autoshield legs (same txid send + receive-to-z)
  so a shield isn't double-counted into both Sent and Received, matching the list.
- Send/Receive sync banners use verification_progress like every other surface,
  instead of the blocks/headers ratio that over-reports during early sync.
- Fix printf format/type mismatches: %.0f<-int (market % shielded), %d<-size_t
  (peer counts), %ld<-int64_t (peer byte counters, wrong on Windows).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:17:42 -05:00
d52d3d1b7f feat(lite): send-time unlock prompt for locked encrypted wallets
When the user confirms a send on a locked encrypted lite wallet, show an unlock
modal (passphrase -> unlockWallet) instead of letting the backend reject it with
"Wallet is locked". After unlocking, the user re-confirms the send (the form is
preserved). Balances remain viewable while locked; only spending needs unlock.

- send_tab: the Confirm-and-send button routes to App::requestLiteUnlock() when
  getWalletState().isLocked(), else sends as before.
- App::renderLiteUnlockPrompt(): centered modal, passphrase (Enter submits),
  Unlock/Cancel; the passphrase buffer is sodium-zeroed after every path.

Full-node unaffected (gated on liteWallet()/isLocked()). Builds clean, launches
clean, tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 18:22:15 -05:00
235504657d polish(lite): lite-appropriate wording for no-wallet/connection states
In lite builds there is no daemon, and isConnected() now tracks the lite wallet,
so the full-node "not connected / waiting for daemon" wording was misleading when
no wallet is open. Add two strings (lite_no_wallet, lite_no_wallet_short; English
built-ins, so other languages fall back until translated) and use them in lite:

- receive/send address preview + receive empty-state overlay + send "can't send"
  tooltip + transactions empty state -> "No wallet open [— create or open one in
  Settings]" instead of daemon wording.
- Status bar: the red indicator shows "No wallet open" (not "Disconnected") in
  lite; the P2P peer count is skipped (lite has no peers); and the redundant
  full-node connection-detail line is suppressed (connection_status_ set to
  "Connected"/"" from the lite wallet state).

Full-node wording unchanged (all gated on isLiteBuild()). Build + run clean
(no RPC noise), tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:11:41 -05:00
975743f754 feat(wallet): persist history and surface pending sends
Add an encrypted SQLite transaction history cache with cached tip metadata and
per-address shielded scan progress so startup and full refreshes avoid
re-scanning every z-address while still invalidating on wallet/address/rescan
changes.

Improve wallet history loading by paging transparent transactions, preserving
cached shielded and sent rows, keeping recent/unconfirmed activity visible, and
classifying mining-address receives. Show z_sendmany opid sends immediately in
History and Overview, pin pending rows through refreshes, and apply optimistic
address/balance debits until opids resolve.

Add timestamped RPC console tracing by source/method without logging params or
results, reduce redundant refresh/RPC calls, and cache Explorer recent block
summaries in SQLite.

Expand focused tests for transaction cache encryption, scan-progress
persistence/invalidation, history preservation, operation-status parsing,
pending send visibility, and Explorer/RPC refresh behavior.
2026-05-05 03:22:14 -05:00
9edab31728 Refactor app services and stabilize refresh/UI flows
- Add refresh scheduler and network refresh service boundaries for typed
  refresh results, ordered RPC collectors, applicators, and price parsing.
- Add daemon lifecycle and wallet security workflow helpers while preserving
  App-owned command RPC, decrypt, cancellation, and UI handoff behavior.
- Split balance, console, mining, amount formatting, and async task logic into
  focused modules with expanded Phase 4 test coverage.
- Fix market price loading by triggering price refresh immediately, avoiding
  queue-pressure drops, tracking loading/error state, and adding translations.
- Polish send, explorer, peers, settings, theme/schema, and related tab UI.
- Replace checked-in generated language headers with build-generated resources.
- Document the cleanup audit, UI static-state guidance, and architecture updates.
2026-04-29 12:47:57 -05:00
ee8a08e569 feat(addresses): improve address labeling and view-only handling
- Add expanded address icon picker with search, bottom-aligned actions, and improved modal sizing
- Embed a pickaxe icon font subset and wire it into typography/address icon rendering
- Track view-only shielded addresses and prevent sends from non-spendable z-addresses
- Improve address transfer dialog sizing, max amount handling, and text clipping
- Tune main header layout values in ui.toml
- Update README, codebase overview, and third-party license documentation
2026-04-27 13:54:28 -05:00
aa26ab5fbd fix: sidebar nav text overflow for long translations
- Add text scaling for section labels (TOOLS, ADVANCED) in sidebar
- Separate explorer_section key from explorer nav label to fix ALL CAPS
- Shorten long sidebar translations: es/pt settings, pt overview, ru tools/advanced
- Fix explorer translations from ALL CAPS to proper case in all languages
2026-04-12 18:45:48 -05:00
ddca8b2e43 v1.2.0: UX audit — security fixes, accessibility, and polish
Security (P0):
- Fix sidebar remaining interactive behind lock screen
- Extend auto-lock idle detection to include active widget interactions
- Distinguish missing PIN vault from wrong PIN; auto-switch to passphrase

Blocking UX (P1):
- Add 15s timeout for encryption state check to prevent indefinite loading
- Show restart reason in loading overlay after wallet encryption
- Add Force Quit button on shutdown screen after 10s
- Warn user if embedded daemon fails to start during wizard completion

Polish (P2):
- Use configured explorer URL in Receive tab instead of hardcoded URL
- Increase request memo buffer from 256 to 512 bytes to match Send tab
- Extend notification duration to 5s for critical operations (tx sent,
  wallet encrypted, key import, backup, export)
- Add Reduce Motion accessibility setting (disables page fade + balance lerp)
- Show estimated remaining time during mining thread benchmark
- Add staleness indicator to market price data (warning after 5 min)

New i18n keys: incorrect_pin, incorrect_passphrase, pin_not_set,
restarting_after_encryption, force_quit, reduce_motion, tt_reduce_motion,
ago, wizard_daemon_start_failed
2026-04-04 19:10:58 -05:00
2c5a658ea5 feat: Full UI internationalization, pool hashrate stats, and layout caching
- Replace all hardcoded English strings with TR() translation keys across
  every tab, dialog, and component (~20 UI files)
- Expand all 8 language files (de, es, fr, ja, ko, pt, ru, zh) with
  complete translations (~37k lines added)
- Improve i18n loader with exe-relative path fallback and English base
  fallback for missing keys
- Add pool-side hashrate polling via pool stats API in xmrig_manager
- Introduce Layout::beginFrame() per-frame caching and refresh balance
  layout config only on schema generation change
- Offload daemon output parsing to worker thread
- Add CJK subset fallback font for Chinese/Japanese/Korean glyphs
2026-03-11 00:40:50 -05:00
1a5c4e8744 feat: blockchain rescan via daemon restart + status bar progress
- Fix z_importwallet to use full path instead of filename only
- Add rescanBlockchain() method that restarts daemon with -rescan flag
- Track rescan progress via daemon output parsing and getrescaninfo RPC
- Display rescan progress in status bar with animated indicator when starting
- Improve dark theme card contrast: lighter surface-variant, tinted borders, stronger rim-light
2026-02-28 15:06:35 -06:00
3aee55b49c ObsidianDragon - DragonX ImGui Wallet
Full-node GUI wallet for DragonX cryptocurrency.
Built with Dear ImGui, SDL3, and OpenGL3/DX11.

Features:
- Send/receive shielded and transparent transactions
- Autoshield with merged transaction display
- Built-in CPU mining (xmrig)
- Peer management and network monitoring
- Wallet encryption with PIN lock
- QR code generation for receive addresses
- Transaction history with pagination
- Console for direct RPC commands
- Cross-platform (Linux, Windows)
2026-02-27 00:26:01 -06:00