## Protection Pre-Explainer: External Pointer Vorher: Pulse-Ring absolute-positioniert IM Screenshot — Position musste per-locale fine-tuned werden weil Apple-Dialog-Höhe variiert (DE/EN/FR/AR haben unterschiedliche Text-Längen → Dialog hat verschiedene Höhen → Erlauben-Button rutscht). Jetzt: animierter Pfeil + Label-Pill UNTER dem Screenshot. Dimensions- agnostic, funktioniert in allen 4 Sprachen ohne Locale-spezifische Magie. - ScreenshotPointer komplett refactored: caret-up + bouncing pill mit Button-Label-Text (z.B. 'Tippe "Erlauben"' / 'Tap "Allow"' / etc.) - onboardingAssets.ts: getPointerPosition deprecated/entfernt - ProtectionSlide nutzt neue API mit buttonLabelKey - 4 Locales: dialog_button_allow + dialog_button_continue - tap_marker_hint refined (kein "roter Marker"-Ref mehr) ## i18n-aware Screenshots en/fr/ar Permission-Dialog-Screenshots zur Map ergänzt. Resolver fällt auf de zurück wenn andere Sprache fehlt. ## Dynamic Sizing ProtectionSlide nutzt useWindowDimensions: height: min(320, max(200, screenH * 0.32)) → passt auf iPhone SE (213px) bis Pro Max (320px capped) ohne Scroll. OnboardingShell ScrollView-Padding reduziert (16→12 top, 24→16 bottom). ProtectionSlide-Spacing tightened. ## Blocker: lockedIn Fix Bug: `lockedIn = appDeletionLockActive` ignorierte URL-Filter-State — wenn User nur FC aktivierte (ohne URL-Filter), zeigte App grünen "Schutz aktiv"-Banner obwohl URL-Filter aus war. Fix: lockedIn = urlFilter && appDeletionLock → Beide müssen wirklich aktiv sein für den grünen Banner. ## LayerSwitchCard: lockedHint Prop Optional Hint-Text der unter dem active Layer angezeigt wird, z.B. "System-gesperrt. Nur in iOS-Einstellungen → Bildschirmzeit → Verwaltung durch ReBreak deaktivierbar.". Wird für iOS App-Lock-Card genutzt. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
58 lines
2.3 KiB
TypeScript
58 lines
2.3 KiB
TypeScript
/**
|
|
* iOS Permission-Dialog-Screenshots für den Onboarding-Pre-Explainer.
|
|
*
|
|
* Pro Sprache liegen die Screenshots in `assets/onboarding/<lang>/`. Falls
|
|
* eine Sprache nicht (oder noch nicht) verfügbar ist, fällt der Resolver auf
|
|
* `de` zurück.
|
|
*
|
|
* Diese Maps explizit mit `require(...)` deklarieren — RN/Metro kann keine
|
|
* dynamischen Pfade auflösen.
|
|
*/
|
|
|
|
type Dialog = 'url_filter' | 'screen_time';
|
|
type Lang = 'de' | 'en' | 'fr' | 'ar';
|
|
|
|
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
const URL_FILTER_DE = require('../assets/onboarding/de/url_filter_permission.jpeg');
|
|
const URL_FILTER_EN = require('../assets/onboarding/en/url_filter_permission.jpeg');
|
|
const URL_FILTER_FR = require('../assets/onboarding/fr/url_filter_permission.jpeg');
|
|
const URL_FILTER_AR = require('../assets/onboarding/ar/url_filter_permission.jpeg');
|
|
|
|
const SCREEN_TIME_DE = require('../assets/onboarding/de/screen_time_permission.jpeg');
|
|
const SCREEN_TIME_EN = require('../assets/onboarding/en/screen_time_permission.jpeg');
|
|
const SCREEN_TIME_FR = require('../assets/onboarding/fr/screen_time_permission.jpeg');
|
|
const SCREEN_TIME_AR = require('../assets/onboarding/ar/screen_time_permission.jpeg');
|
|
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
|
|
const SCREENSHOTS: Record<Dialog, Partial<Record<Lang, number>>> = {
|
|
url_filter: {
|
|
de: URL_FILTER_DE,
|
|
en: URL_FILTER_EN,
|
|
fr: URL_FILTER_FR,
|
|
ar: URL_FILTER_AR,
|
|
},
|
|
screen_time: {
|
|
de: SCREEN_TIME_DE,
|
|
en: SCREEN_TIME_EN,
|
|
fr: SCREEN_TIME_FR,
|
|
ar: SCREEN_TIME_AR,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Resolves the right screenshot for the current language, with de-fallback.
|
|
* Returns the result of `require(...)` (an opaque module-handle for Metro).
|
|
*/
|
|
export function getPermissionScreenshot(dialog: Dialog, lang: string): number {
|
|
const normalized = (
|
|
lang === 'de' || lang === 'en' || lang === 'fr' || lang === 'ar' ? lang : 'de'
|
|
) as Lang;
|
|
const map = SCREENSHOTS[dialog];
|
|
return map[normalized] ?? map.de!;
|
|
}
|
|
|
|
// (Deprecated) getPointerPosition entfernt — der Pointer wird jetzt extern
|
|
// UNTER dem Screenshot gerendert (ScreenshotPointer-Komponente), nicht mehr
|
|
// per-percent overlayed. Damit entfällt die Notwendigkeit pixel-genaue
|
|
// Positionen pro Locale + Dialog zu pflegen — siehe ScreenshotPointer.tsx.
|