From 2c1eecd1f785301c2fe61af56867fb707acb1398 Mon Sep 17 00:00:00 2001 From: chahinebrini Date: Sun, 7 Jun 2026 22:40:25 +0200 Subject: [PATCH] =?UTF-8?q?feat(native):=20ger=C3=A4te-spezifische=20PNG-I?= =?UTF-8?q?cons=20(iphone/android/macbook/computer)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit deviceImage()-Helper mappt Plattform→assets/devices/*.png; ersetzt Ionicons in Geräte-Rows, MagicSheet und Detail-Sheet. Co-Authored-By: Claude Opus 4.8 --- apps/rebreak-native/NEXT_RELEASE.md | 1 + apps/rebreak-native/app/devices.tsx | 30 ++++++++-------- .../components/devices/DeviceDetailSheet.tsx | 6 ++-- .../components/devices/MagicSheet.tsx | 14 ++++---- .../components/devices/deviceIcon.ts | 35 +++++++++++++++++++ 5 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 apps/rebreak-native/components/devices/deviceIcon.ts diff --git a/apps/rebreak-native/NEXT_RELEASE.md b/apps/rebreak-native/NEXT_RELEASE.md index 858f041..18940e9 100644 --- a/apps/rebreak-native/NEXT_RELEASE.md +++ b/apps/rebreak-native/NEXT_RELEASE.md @@ -7,6 +7,7 @@ - Onboarding now sets up the full protection using the exact same guided, gated step flow as the protection screen (single source of truth) — Android: VPN → Device Administrator → Accessibility (strict order: the tamper lock has to come last, otherwise it would block the device-admin screen); iOS: App Lock → Screen Time passcode → content filter. Previously the device-admin / screen-time hardening steps only existed in the protection screen after onboarding. ## Changed +- Device list now shows device-specific icons (iPhone / Android / MacBook / PC) instead of generic outlines - Stationary protection (Mac/Windows) now runs exclusively via Rebreak Magic — the manual offline profile download has been removed. The offline profile would have shipped the removal password in plain text inside the file (bypass risk); with Magic the lock password stays server-side and is never shown to the user. - Mac DNS profile hardened with `ProhibitDisablement` — the filter can no longer be toggled off in System Settings. diff --git a/apps/rebreak-native/app/devices.tsx b/apps/rebreak-native/app/devices.tsx index cf10e9d..854b8db 100644 --- a/apps/rebreak-native/app/devices.tsx +++ b/apps/rebreak-native/app/devices.tsx @@ -1,6 +1,7 @@ import { ActivityIndicator, Alert, + Image, Platform, ScrollView, Text, @@ -33,21 +34,10 @@ import { AppHeader } from '../components/AppHeader'; import { MagicSheet } from '../components/devices/MagicSheet'; import { DeviceProgressBar } from '../components/devices/DeviceProgressBar'; import { DeviceDetailSheet, type DeviceDetail } from '../components/devices/DeviceDetailSheet'; +import { deviceImage } from '../components/devices/deviceIcon'; // ─── Helpers ───────────────────────────────────────────────────────────────── -function mobileIcon(platform: string): React.ComponentProps['name'] { - if (platform === 'ios') return 'logo-apple'; - if (platform === 'android') return 'logo-android'; - return 'phone-portrait-outline'; -} - -function protectedDeviceIcon(platform: string): React.ComponentProps['name'] { - if (platform === 'mac') return 'laptop-outline'; - if (platform === 'windows') return 'desktop-outline'; - return 'globe-outline'; -} - function formatLastSeen(iso: string, t: (k: string, o?: any) => string): string { const ms = Date.now() - new Date(iso).getTime(); const min = Math.floor(ms / 60_000); @@ -193,7 +183,7 @@ function MobileDeviceRow({ function openDetail() { onOpenDetail({ name: deviceName, - icon: mobileIcon(device.platform), + icon: deviceImage(device.platform, device.model), platform: device.platform, createdAt: device.createdAt, lastSeenAt: device.lastSeenAt, @@ -229,7 +219,11 @@ function MobileDeviceRow({ justifyContent: 'center', }} > - + @@ -364,7 +358,7 @@ function ProtectedDeviceRow({ function openDetail() { onOpenDetail({ name: device.label, - icon: protectedDeviceIcon(device.platform), + icon: deviceImage(device.platform), platform: device.platform, createdAt: device.createdAt, lastSeenAt: null, @@ -423,7 +417,11 @@ function ProtectedDeviceRow({ justifyContent: 'center', }} > - + diff --git a/apps/rebreak-native/components/devices/DeviceDetailSheet.tsx b/apps/rebreak-native/components/devices/DeviceDetailSheet.tsx index 0545d00..3afd9cc 100644 --- a/apps/rebreak-native/components/devices/DeviceDetailSheet.tsx +++ b/apps/rebreak-native/components/devices/DeviceDetailSheet.tsx @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import { Text, View } from 'react-native'; +import { Image, type ImageSourcePropType, Text, View } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { useTranslation } from 'react-i18next'; import { useColors } from '../../lib/theme'; @@ -14,7 +14,7 @@ const DAY_MS = 86_400_000; export type DeviceDetail = { name: string; - icon: React.ComponentProps['name']; + icon: ImageSourcePropType; platform: string; /** ISO — Bindungs-/Verbindungsdatum */ createdAt: string; @@ -106,7 +106,7 @@ export function DeviceDetailSheet({ justifyContent: 'center', }} > - + - diff --git a/apps/rebreak-native/components/devices/deviceIcon.ts b/apps/rebreak-native/components/devices/deviceIcon.ts new file mode 100644 index 0000000..33589f0 --- /dev/null +++ b/apps/rebreak-native/components/devices/deviceIcon.ts @@ -0,0 +1,35 @@ +import type { ImageSourcePropType } from 'react-native'; + +/** + * Geräte-spezifische PNG-Icons (apps/rebreak-native/assets/devices). + * React Native braucht statische require()-Pfade — daher das feste Mapping. + */ +const ICONS = { + iphone: require('../../assets/devices/iphone.png'), + android: require('../../assets/devices/android.png'), + tablet: require('../../assets/devices/tablet.png'), + macbook: require('../../assets/devices/macbook.png'), + laptop: require('../../assets/devices/laptop.png'), + computer: require('../../assets/devices/computer.png'), +} as const; + +/** + * Wählt das passende Geräte-PNG anhand Plattform (+ optional Modell-String). + * Fällt auf `laptop` zurück (generischer Desktop). + */ +export function deviceImage( + platform?: string | null, + model?: string | null, +): ImageSourcePropType { + const p = (platform ?? '').toLowerCase(); + const m = (model ?? '').toLowerCase(); + + if (p.startsWith('ipad') || m.includes('ipad') || p.includes('tablet')) return ICONS.tablet; + if (p.startsWith('ios') || p.startsWith('iphone') || m.includes('iphone')) return ICONS.iphone; + if (p.startsWith('android')) return ICONS.android; + if (p.startsWith('mac') || p === 'darwin' || m.includes('macbook') || m.includes('mac')) { + return ICONS.macbook; + } + if (p.startsWith('win') || m.includes('windows')) return ICONS.computer; + return ICONS.laptop; +}