import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:share_plus/share_plus.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../core/build_config.dart'; import '../../../core/design/tokens.dart'; import '../../../core/design/tripz_colors.dart'; import '../../../core/design/typography.dart'; import '../../../core/di.dart'; import '../../../core/l10n/l10n.dart'; import '../../../core/router.dart'; import '../../../core/session/session_cubit.dart'; import '../../../core/store_links.dart'; import '../../../core/ui/tripz_scaffold.dart'; import '../../profile/data/profile_repository.dart'; import '../cubit/settings_cubit.dart'; import '../cubit/settings_state.dart'; /// المظهر واللغة ومعلومات التطبيق — بأقسام كما في سيرو /// (`setting_page.dart`: General · Preferences · Support & Info) بدل قائمة /// مسطّحة بلا عناوين. /// /// تبديل اللغة **يقلب الاتجاه كاملاً** بلا إعادة تشغيل — `MaterialApp` /// يشتقّ RTL/LTR من الـlocale (docs/26 §4). class SettingsPage extends StatelessWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context) { final l10n = context.l10n; return BlocBuilder( builder: (context, state) { final cubit = context.read(); return TripzScaffold( title: l10n.settingsTitle, child: ListView( children: [ _SectionHeader(title: l10n.settingsSectionGeneral), Text(l10n.settingsTheme, style: context.texts.titleSmall), RadioGroup( groupValue: state.themeMode, onChanged: (v) => cubit.setThemeMode(v ?? ThemeMode.system), child: Column( children: [ RadioListTile( value: ThemeMode.system, contentPadding: EdgeInsets.zero, title: Text(l10n.settingsThemeSystem), ), RadioListTile( value: ThemeMode.light, contentPadding: EdgeInsets.zero, title: Text(l10n.settingsThemeLight), ), RadioListTile( value: ThemeMode.dark, contentPadding: EdgeInsets.zero, title: Text(l10n.settingsThemeDark), ), ], ), ), const SizedBox(height: Space.md), Text(l10n.settingsLanguage, style: context.texts.titleSmall), RadioGroup( groupValue: state.locale.languageCode, // اللغة تُحفظ محلياً **وتُرسل للخادم**: الإشعارات تُصاغ على // الخادم بلغة المستخدم المخزّنة عنده (`PATCH /users/me` // يقبل `language` — docs/38 §3)، فلغةٌ محليّة وحدها تعني // واجهةً عربية وإشعاراتٍ إنجليزية. onChanged: (v) => _setLanguage(context, v ?? 'ar'), child: Column( children: [ RadioListTile( value: 'ar', contentPadding: EdgeInsets.zero, title: Text(l10n.settingsLanguageArabic), ), RadioListTile( value: 'en', contentPadding: EdgeInsets.zero, title: Text(l10n.settingsLanguageEnglish), ), ], ), ), _SectionHeader(title: l10n.settingsSectionSupport), _Tile( icon: Icons.help_outline_rounded, title: l10n.menuSupport, subtitle: l10n.settingsSupportLead, onTap: () => context.push(Routes.support), ), _Tile( icon: Icons.share_outlined, title: l10n.menuShare, subtitle: l10n.settingsShareLead, onTap: () => SharePlus.instance.share( ShareParams(text: l10n.shareMessagePlain(StoreLinks.thisApp)), ), ), _Tile( icon: Icons.shield_outlined, title: l10n.menuPrivacy, onTap: () async { final uri = Uri.tryParse(BuildConfig.privacyUrl); if (uri == null) return; await launchUrl(uri, mode: LaunchMode.externalApplication); }, ), const _VersionTile(), ], ), ); }, ); } /// فشل الخادم **لا يمنع** تبديل اللغة محلياً: الواجهة تستجيب فوراً، /// والمزامنة تُعاد عند التبديل التالي. عكسه يعني زرّاً لا يستجيب بلا شبكة. static Future _setLanguage(BuildContext context, String code) async { await context.read().setLocale(Locale(code)); try { final user = await sl().update(language: code); sl().onProfileCompleted(user); } catch (_) { // المزامنة أفضل-جهد — لا رسالة خطأ على تبديل نجح محلياً. } } } class _SectionHeader extends StatelessWidget { const _SectionHeader({required this.title}); final String title; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(top: Space.lg, bottom: Space.xs), child: Text( title, style: context.texts.labelMedium?.copyWith( color: context.colors.primary, ), ), ); } } class _Tile extends StatelessWidget { const _Tile({ required this.icon, required this.title, required this.onTap, this.subtitle, }); final IconData icon; final String title; final String? subtitle; final VoidCallback onTap; @override Widget build(BuildContext context) { return ListTile( contentPadding: EdgeInsets.zero, leading: Icon(icon), title: Text(title), subtitle: subtitle == null ? null : Text(subtitle!), trailing: Icon( Icons.chevron_left_rounded, color: context.colors.onSurfaceVariant, ), onTap: onTap, ); } } /// رقم الإصدار — أول ما يُسأل عنه في الدعم، وكان غائباً رغم وجود مفتاح /// ترجمته أصلاً. class _VersionTile extends StatelessWidget { const _VersionTile(); @override Widget build(BuildContext context) { final l10n = context.l10n; return FutureBuilder( future: PackageInfo.fromPlatform(), builder: (context, snapshot) { final info = snapshot.data; return ListTile( contentPadding: EdgeInsets.zero, leading: const Icon(Icons.info_outline_rounded), title: Text(l10n.aboutVersion), trailing: Text( // قبل وصول المعلومة يُترك المكان فارغاً لا «—»: القيمة تصل // في إطار واحد، والشرطة تومض بلا داعٍ. info == null ? '' : '${info.version} (${info.buildNumber})', textDirection: TextDirection.ltr, style: numericStyle(context.texts.bodySmall).copyWith( color: context.colors.onSurfaceVariant, ), ), ); }, ); } }