Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
222231b
Extract theme into dedicated ThemeProvider with system appearance sup…
claude Jul 2, 2026
7387d56
Unify the app on the Bitcoin-orange brand palette
claude Jul 2, 2026
52c342f
Cut redundant work in the wallet data pipeline and home screen rendering
claude Jul 2, 2026
620da2d
Add AppButton primitive and adopt it on primary CTAs
claude Jul 3, 2026
514d930
Replace alert-based send confirmation with a native review sheet
claude Jul 3, 2026
83692ce
Present pickers and edit-wallet dialogs as native form sheets
claude Jul 3, 2026
6c32eb7
Move unlock PIN to SecureStore and remove dead code
claude Jul 3, 2026
ed3f58c
Document the revamp and record skill feedback entries
claude Jul 3, 2026
17a7375
Virtualize remaining unbounded lists and unify receive-screen feedback
claude Jul 3, 2026
68ae140
Split the wallet store into churn-domain contexts
claude Jul 3, 2026
6c62c91
Convert hot consumers to narrow store subscriptions
claude Jul 3, 2026
d7775d9
Cut per-address stats requests and stop nuking healthy caches
claude Jul 3, 2026
ce54535
Migrate all remaining legacy Animated code to Reanimated
claude Jul 3, 2026
ef80a1a
Replace TouchableOpacity app-wide with Pressable-based components
claude Jul 3, 2026
b6e88d2
Document the deferred-items pass and record skill feedback
claude Jul 3, 2026
2d4c039
Complete the narrow-hook migration and remove the compat useWallet
claude Jul 4, 2026
1e84f21
Fetch complete confirmed transaction history via Esplora pagination
claude Jul 4, 2026
159534f
Document the final remainder pass
claude Jul 4, 2026
23e1b5b
Remove unused getAddressTransactions import in wallet-service
claude Jul 7, 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
34 changes: 32 additions & 2 deletions .github/skills/frontend-design/SKILL_MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,39 @@ Action: [How SKILL.md should be updated, if at all]

---

**Awaiting first feedback entry...**
[2026-07-03] - SUCCESS - Impact: HIGH
Context: Brand/color unification pass across the whole app (light-mode
gradients, error boundary, toasts, skeletons, default wallet color) plus a
new transaction review sheet and shared button primitive.
Outcome: The app previously shipped two palettes at once — a Bitcoin-orange
theme in constants/themes.ts and a legacy cyan/coral set hardcoded in
components. Deriving every surface from theme tokens (and mirroring the
dark-branch gradient structure in light mode) made light and dark feel like
one product. System-appearance-driven theming (light/dark/system, default
system) replaced the manual-only toggle.
Learning: Hardcoded hex "hotspots" cluster in three places: loading/empty
fallbacks copy-pasted across screens, error/warning cards, and orphaned
"delight" components that were built against an older brand and never
imported. A grep for the legacy hex values is a fast completeness check.
Action: Emphasize "no raw hex where a theme token exists" and recommend a
single ScreenLoading-style fallback component per app.

When the frontend-design skill is used to create mobile UIs, outcomes should be recorded here. Track what works, what doesn't, and how mobile design thinking evolves.
---

[2026-07-03] - SUCCESS - Impact: MEDIUM
Context: Interaction-polish follow-up: unified press feedback across the
whole app and finished the animation-system consolidation.
Outcome: Two-tier press-feedback system — AppButton (spring scale +
haptics) for real CTAs, PressableOpacity (opacity dim) for rows and icon
buttons — gives every tap target consistent feedback without redesigning
bespoke layouts. Migrating the last legacy Animated code to Reanimated
means one animation vocabulary (shared values + withTiming/withSpring)
across splash, tab transitions, charts, and list rows.
Learning: A mechanical drop-in wrapper (PressableOpacity) converts a large
legacy surface safely; reserving the expressive primitive (AppButton) for
deliberate CTAs keeps visual hierarchy meaningful.
Action: Document the two-tier press-feedback convention as the default
pattern for new screens.

---

Expand Down
89 changes: 89 additions & 0 deletions .github/skills/react-native-skills/SKILL_MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# React Native Skills Memory

This file captures learnings and feedback from applying the react-native-skills rules. It serves as a living memory that informs future updates to SKILL.md (see AGENTS.md for the feedback loop).

## Feedback Log

### Template for New Entries
```
[YYYY-MM-DD] - [SUCCESS/FAILURE/PARTIAL] - [Impact: HIGH/MEDIUM/LOW]
Context: [What was being built/changed]
Outcome: [What happened]
Learning: [Insights gained]
Action: [How SKILL.md should be updated, if at all]
```

### Entries

---

[2026-07-03] - SUCCESS - Impact: HIGH
Context: App-wide visual + performance revamp (theme extraction, formSheet
modals, AppButton primitive, send-flow review sheet, list virtualization).
Outcome: Rules §9.3 (Pressable over TouchableOpacity) and §9.7 (native
formSheet modals) were directly applicable and produced noticeably better
UX: the new `components/AppButton.tsx` is Pressable-based with Reanimated
spring feedback, and five bare `animationType="slide"` JS modals (settings
currency/auto-lock/wallet pickers, home + manage-wallets edit dialogs) plus
the new send review sheet now use `presentationStyle="formSheet"`.
Learning: When converting a transparent JS overlay modal to formSheet, the
`transparent` prop and the manual dark overlay View must both be removed,
and the content container becomes the sheet root (flex: 1, themed
background). Selection rows benefit from a HapticService.light() call.
Legacy screens still use TouchableOpacity extensively; converting only
high-traffic CTAs first kept the diff reviewable.
Action: SKILL.md could add a short "converting existing JS modals to
formSheet" checklist (remove transparent + overlay wrapper; flex: 1 root;
onRequestClose still required for Android back).

---

[2026-07-03] - SUCCESS - Impact: HIGH
Context: Deferred-items pass — store re-render fix, N+1 request reduction,
legacy Animated migration, app-wide Pressable sweep.
Outcome: (1) Splitting a single-context "God store" into churn-domain
contexts (one context per already-memoized slice) delivered selector-like
subscriptions without moving any query/mutation logic — a much safer path
than a Zustand bridge, which would have introduced one-commit lag between
data slices. (2) Rule §9.3 was completed repo-wide via a drop-in
`PressableOpacity` (Pressable mimicking activeOpacity), converting 32 files
mechanically with zero type errors; only `createAnimatedComponent(TouchableOpacity)`
bases remain. (3) All legacy `Animated` code migrated to Reanimated —
notably, an unmemoized `useFocusEffect(fn)` (no useCallback) had been
replaying the tab entrance animation on every re-render while focused;
the Reanimated rewrite with a memoized callback fixed it.
Learning: For context-hook stores, publish each memoized slice through its
own context and keep the legacy hook as a compat shim; convert consumers
incrementally. Never place whole React Query objects in a slice memo's
value/deps — identity churns every render.
Action: Consider adding a rule about churn-domain context splitting for
large context stores, and a note that useFocusEffect callbacks must be
memoized.

---

[2026-07-04] - SUCCESS - Impact: MEDIUM
Context: Final remainder pass — completed the narrow-hook migration
(deleted the compat all-slices hook) and added Esplora confirmed-history
pagination to the data pipeline.
Outcome: Removing the combined hook after full conversion prevents new
code from silently reintroducing app-wide re-render fanout. Pagination
required a "raw page" mode in the fetch layer because the existing
cache-merge on /txs responses would have poisoned the continuation
cursor; raw requests also needed a distinct dedupe key.
Learning: When a fetch layer transparently merges cache into responses,
any cursor-based pagination built on top MUST bypass the merge for the
page it derives cursors from. An early-stop on "full page of already
cached items" is sound for append-only (prepend-only) histories.
Action: Worth a data-layer rule: pagination cursors must come from raw
provider responses, never cache-augmented ones.

---

## Pending SKILL.md Updates

- Consider a migration checklist for JS `<Modal transparent>` → `presentationStyle="formSheet"` (see 2026-07-03 entry).

## Changelog of Memory-Driven Updates

**None yet** - This is the initial version
21 changes: 6 additions & 15 deletions app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
import { lightTheme } from '@/constants/themes';
import { useWallet } from '@/hooks/wallet-store';
import { useTheme } from '@/hooks/theme-store';
import Ionicons from '@expo/vector-icons/Ionicons';
import { Icon, Label, NativeTabs, VectorIcon } from 'expo-router/unstable-native-tabs';
import React, { useEffect, useState } from 'react';
import React from 'react';
import { Platform } from 'react-native';

export default function TabLayout() {
// Use theme from WalletProvider context for consistency
// Fallback to lightTheme if context is not available yet
const walletContext = useWallet();
const theme = walletContext?.theme ?? lightTheme;
const [themeKey, setThemeKey] = useState(0);

// Force re-render when theme changes
useEffect(() => {
// Increment key to force NativeTabs remount with new theme
setThemeKey(prev => prev + 1);
}, [theme]);
const { theme, isDark } = useTheme();

return (
<NativeTabs
key={themeKey}
// NativeTabs needs a remount to fully re-apply colors, but only when the
// resolved appearance actually flips — not on every theme object change
key={isDark ? 'dark' : 'light'}
// Tint color for active tabs
tintColor={theme.colors.primary}
// Icon colors for default and selected states
Expand Down
Loading