- components/plan/PlanChangeSheet.tsx — upgrade/downgrade briefing per pricing-tiers.md §4
(fetches GET /api/plan/change-preview; gains/keeps/changes; recovery-safety line;
billing hint w/o purchase button; CTA row, no 'are you sure?' interstitial)
- debug.tsx: PlanOverrideToggle routes every flip through PlanChangeSheet first
- devices.tsx + protectedDevices.ts: 'degraded' status (red, inline 'protection expired —
remove the profile yourself' hint, no green checkmark); maxProtectedDevices limit hint
- mail.tsx + MailAccountCard.tsx + useMailStatus.ts: over-limit banner + paused-account
greyed-out + PausedBadge (all defensive — only shows if backend sends the field)
- blocker.tsx: free-tier transparency hint ('Grundschutz aktiv — voller Schutz: Pro/Legend')
+ custom-domain over-limit banner
- locales: plan.change.* + plan_limit.* (de + en)
tsc clean. Backend side (GET /api/plan/change-preview, paused/degraded fields) in progress
in parallel — UI built defensively to work before it lands.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Alle <Pressable style={({pressed}) => ({...})}> ersetzt — style-Funktion
droppt auf Android (New Arch) intermittierend width/height, führt zu 0×0
unsichtbaren Elementen. TouchableOpacity mit activeOpacity ist stabil.
Außerdem übrige Pressables (plain style) aus components/ und app/
migriert sowie zwei überschüssige </View>-Tags in chat.tsx + RoomCard.tsx
entfernt die TS-Fehler verursacht haben.
64 Dateien, typecheck sauber.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Memory feedback_known_ui_layout_bugs.md Pattern 5: Pressable with
style={({pressed}) => ({...})} is layout-poison in some RN-render-paths,
button collapses to 0-height and renders invisible. Windows-button right
below worked because it uses static style={{...}}.
TouchableOpacity gets same press-feedback via activeOpacity prop.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Profile (rebreak-native-ui):
- New hook hooks/useProfileData.ts (143 LOC, 4 hooks):
useSocialStats, useApprovedDomains, useCooldownHistory, useSosInsights
- app/profile/index.tsx: alle DUMMY_* constants entfernt → live data via hooks
- PATCH /api/profile/me/demographics nun wired in onChange (war TODO-only)
- DELETE /api/profile/me/demographics für revoke-consent
- POST /api/profile/me/diga-banner-dismiss
Devices (rebreak-native-ui):
- New app/devices.tsx push-page: slot-counter, progress-bar, device-list mit
trash-button (gesperrt für isCurrent)
- New lib/deviceId.ts: persistent device-ID via expo-application
(getIosIdForVendorAsync / getAndroidId) mit AsyncStorage-UUID-fallback
- New stores/devices.ts: Zustand store (loadDevices, removeDevice, ensureRegistered)
- lib/api.ts: x-device-id + x-platform headers bei jedem Backend-Call
(skipDeviceHeader option für Bootstrap-register)
- app/settings.tsx: Geräte-Row aktiv (push to /devices) statt soon-flagged
- locales: 14 neue settings.devices_* keys DE+EN
Backend-Status: alle Devices-Endpoints existieren (GET /api/devices, POST /register,
DELETE /:id). Pending: GET /api/profile/me/demographics für reload-state-fetch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>