feat: add Jordan 3D topographic platform, Siro Map cinematic orbit studio, sun-shadow simulation, and sovereign intelligence security gating

This commit is contained in:
Hamza-Ayed
2026-09-19 12:34:26 +03:00
parent 91e9e71ce4
commit 0bf13824c9
180 changed files with 245224 additions and 704 deletions
+2 -2
View File
@@ -12,7 +12,7 @@
IMPORTANT NOTICE FOR APP REVIEWERS:
1. Operational Geographic Coverage:
Uruk Map is engineered on an independent, self-hosted regional spatial vector engine. Our active vector map tiles and routing servers are currently provisioned specifically for three operational countries in the MENA region:
Siro Map is engineered on an independent, self-hosted regional spatial vector engine. Our active vector map tiles and routing servers are currently provisioned specifically for three operational countries in the MENA region:
- Jordan (الأردن)
- Iraq (العراق)
- Egypt (مصر)
@@ -51,7 +51,7 @@ For any technical inquiries during review, please contact: support@intaleqapp.co
ملاحظة هامة لفاحصي ومراجعي التطبيق:
1. نطاق التغطية الجغرافية التشغيلية:
تعتمد «خرائط أوروك» على منظومة خرائط وملاحة فيكتورية مستقلة ومستضافة ذاتياً، وتغطي خوادم الخرائط والبيانات المكانية الحالية ثلاث دول تشغيلية رئيسية في منطقة الشرق الأوسط وشمال أفريقيا:
تعتمد «خرائط سيرو» على منظومة خرائط وملاحة فيكتورية مستقلة ومستضافة ذاتياً، وتغطي خوادم الخرائط والبيانات المكانية الحالية ثلاث دول تشغيلية رئيسية في منطقة الشرق الأوسط وشمال أفريقيا:
- الأردن
- العراق
- مصر
+17 -23
View File
@@ -1,7 +1,7 @@
# ملف بيانات ونصوص النشر على Google Play Console | خرائط أوروك (Uruk Map)
# ملف بيانات ونصوص النشر على Google Play Console | خرائط سيرو (Siro Map)
================================================================================
هذا الملف يحتوي على كافة النصوص والبيانات المطلوبة لرفع وتعبئة تطبيق **Uruk Map** على **Google Play Console** باللغتين العربية والإنجليزية، وفق معايير خوارزميات تحسين متجر التطبيقات (ASO) وتوافقاً مع الحدود الرسمية لعدد الحروف.
هذا الملف يحتوي على كافة النصوص والبيانات المطلوبة لرفع وتعبئة تطبيق **Siro Map** على **Google Play Console** باللغتين العربية والإنجليزية، وفق معايير خوارزميات تحسين متجر التطبيقات (ASO) وتوافقاً مع الحدود الرسمية لعدد الحروف، مع الحفاظ على معرف الحزمة التقني المعتمد على المتجر: `com.urukmap.app`.
---
@@ -10,9 +10,9 @@
### باللغة العربية (Arabic - Default)
* **اسم التطبيق (App name - بحد أقصى 30 حرفاً)**:
```text
خرائط أوروك: ملاحة وتوجيه ذكي
خرائط سيرو: ملاحة وتوجيه ذكي
```
*(بديل مقترح: `خرائط أوروك - Uruk Map`)*
*(بديل مقترح: `خرائط سيرو - Siro Map`)*
* **الوصف القصير (Short description - بحد أقصى 80 حرفاً)**:
```text
@@ -21,13 +21,11 @@
* **الوصف الكامل (Full description - بحد أقصى 4000 حرف)**:
```text
«خرائط أوروك - Uruk Map» هي المنظومة المتقدمة للملاحة والخرائط الذكية المصممة خصيصاً لتلبية احتياجات العالم العربي ومنطقة الشرق الأوسط وشمال أفريقيا، بموثوقية فائقة وتقنيات تشغيل مستقلة.
«خرائط سيرو - Siro Map» هي المنظومة المتقدمة للملاحة والخرائط الذكية المصممة خصيصاً لتلبية احتياجات العالم العربي ومنطقة الشرق الأوسط وشمال أفريقيا، بموثوقية فائقة وتقنيات تشغيل مستقلة.
🏆 مشروع يحظى برعاية ودعم برنامج جائزة أوروك الدولية للابتكار وتطوير الخدمات التقنية.
سواء كنت تتنقل داخل المدن المزدحمة، أو تقود عبر الطرق السريعة في المناطق التي تعاني من ضعف شبكات التغطية أو قيود خدمات الخرائط العالمية (في العراق، السودان، اليمن، سوريا، والمنطقة)، تمنحك خرائط سيرو تجربة تنقل دقيقة، سريعة، واقتصادية في استهلاك البيانات.
سواء كنت تتنقل داخل المدن المزدحمة، أو تقود عبر الطرق السريعة في المناطق التي تعاني من ضعف شبكات التغطية أو قيود خدمات الخرائط العالمية (في العراق، السودان، اليمن، سوريا، والمنطقة)، تمنحك خرائط أوروك تجربة تنقل دقيقة، سريعة، واقتصادية في استهلاك البيانات.
لماذا تختار خرائط أوروك؟
لماذا تختار خرائط سيرو؟
🧠 1. كاش ذكي واستدعاء فوري من الذاكرة
نظام متقدم لحفظ بلاطات الخريطة في ذاكرة الجهاز (Memory Cache) لاستدعائها فوراً دون تأخير، مما يوفر سرعة استجابة فائقة ويقلل استهلاك باقة الإنترنت.
@@ -56,7 +54,7 @@
🛡️ 9. حماية الخصوصية وتوفير البطارية
تصميم برمجي حديث ومحسّن لا يستهلك طاقة البطارية ولا يجمع بياناتك الخاصة بدون إذن.
حمّل «خرائط أوروك» اليوم واستمتع بتجربة ملاحة حرة، ذكية، ومستقلة 100%!
حمّل «خرائط سيرو» اليوم واستمتع بتجربة ملاحة حرة، ذكية، ومستقلة 100%!
```
---
@@ -64,9 +62,9 @@
### باللغة الإنجليزية (English - United States)
* **App Name (Max 30 characters)**:
```text
Uruk Map: GPS Navigation
Siro Map: GPS Navigation
```
*(Alternative: `Uruk Map - Smart Navigation`)*
*(Alternative: `Siro Map - Smart Navigation`)*
* **Short Description (Max 80 characters)**:
```text
@@ -75,11 +73,9 @@
* **Full Description (Max 4000 characters)**:
```text
Uruk Map is an advanced GPS navigation and digital mapping platform engineered specifically for the Middle East, North Africa, and regional markets requiring dependable offline capabilities.
Siro Map is an advanced GPS navigation and digital mapping platform engineered specifically for the Middle East, North Africa, and regional markets requiring dependable offline capabilities.
🏆 Backed and supported by the Uruk International Prize program for technological innovation and digital service infrastructure.
Whether commuting through bustling metropolitan hubs or navigating transit routes across Iraq, Sudan, Yemen, Syria, and the broader MENA region, Uruk Map delivers unmatched precision, high-speed memory caching, and independent offline reliability.
Whether commuting through bustling metropolitan hubs or navigating transit routes across Iraq, Sudan, Yemen, Syria, and the broader MENA region, Siro Map delivers unmatched precision, high-speed memory caching, and independent offline reliability.
KEY FEATURES:
@@ -110,7 +106,7 @@
🔋 9. Battery & Data Optimized
Engineered with high-performance native rendering (MapLibre vector graphics) that maximizes battery endurance and minimizes background data.
Download Uruk Map today and experience fast, smart, and independent navigation!
Download Siro Map today and experience fast, smart, and independent navigation!
```
---
@@ -135,14 +131,12 @@
1. **أيقونة التطبيق (App Icon)**:
- القياس: `512 x 512` بكسل
- الصيغة: `PNG 32-bit`
- المسار الجاهز: `assets/images/uruk_map_playstore_512.png`
- *(ملف تم إنشاؤه مسبقاً ومطابق لمعايير جوجل بلاي)*.
- المسار الجاهز: `assets/images/siro_map_playstore_512.png`
2. **الرسم المميز / البانر (Feature Graphic)**:
- القياس: `1024 x 500` بكسل
- الصيغة: `JPEG / PNG` (بدون شفافية)
- المسار الجاهز: `assets/images/uruk_playstore_feature_graphic_1024x500.jpg`
- *(بانر ملكي فاخر يدمج تمثال أوروك الذهبي وشبكة الطرق المتوهجة)*.
- المسار الجاهز: `assets/images/siro_playstore_feature_graphic_1024x500.png`
3. **لقطات الشاشة (Screenshots)**:
- الحد الأدنى: 2 لقطات (المستحسن من 4 إلى 8 لقطات).
@@ -151,7 +145,7 @@
1. شاشة الخريطة الرئيسية مع شريط البحث والملاحة الفيكتورية.
2. شاشة التوجيه الفعلي Turn-by-Turn مع بطاقة PiP ولوحة السرعة.
3. شاشة طبقات الخريطة وتخصيص أيقونة المركبة.
4. شاشة الاعتماد وجائزة أوروك الدولية للسيادة المكانية.
4. شاشة بطاقة التعريف ومنظومة سيرو ماب للسيادة المكانية.
---
@@ -196,7 +190,7 @@
IMPORTANT NOTICE FOR APP REVIEWERS:
1. Operational Geographic Coverage:
Uruk Map operates on an independent, self-hosted regional spatial vector engine. Our vector map tiles and routing servers are currently live specifically for three operational countries in the MENA region:
Siro Map operates on an independent, self-hosted regional spatial vector engine. Our vector map tiles and routing servers are currently live specifically for three operational countries in the MENA region:
- Jordan (الأردن)
- Iraq (العراق)
- Egypt (مصر)
@@ -11,7 +11,7 @@
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE"/>
<application
android:label="Uruk Map"
android:label="Siro Map"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 30 KiB

+4 -4
View File
@@ -7,7 +7,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Uruk Map</string>
<string>Siro Map</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
@@ -15,7 +15,7 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>uruk_map</string>
<string>siro_maps</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
@@ -27,9 +27,9 @@
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSLocationWhenInUseUsageDescription</key>
<string>يستخدم تطبيق خرائط أوروك (Uruk Map) موقعك لعرض خريطة تفاعلية وتوفير الملاحة الحية الدقيقة.</string>
<string>يستخدم تطبيق خرائط سيرو (Siro Map) موقعك لعرض خريطة تفاعلية وتوفير الملاحة الحية الدقيقة.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>يستخدم تطبيق خرائط أوروك (Uruk Map) موقعك في الخلفية لتقديم التوجيهات الصوتية الحية وتنبيهات الطريق أثناء القيادة.</string>
<string>يستخدم تطبيق خرائط سيرو (Siro Map) موقعك في الخلفية لتقديم التوجيهات الصوتية الحية وتنبيهات الطريق أثناء القيادة.</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
@@ -20,10 +20,10 @@ class AppColors {
static const Color tacticalNavy = Color(0xFF0B192C);
static const Color tacticalEmerald = Color(0xFF059669);
static const Color sovereignGold = Color(0xFFD97706);
static const Color urukGold = Color(0xFFD4AF37);
static const Color urukGoldLight = Color(0xFFFFF9E6);
static const Color urukGoldDark = Color(0xFF8C6B1C);
static const Color urukGoldBorder = Color(0x40D4AF37);
static const Color siroGold = Color(0xFFD4AF37);
static const Color siroGoldLight = Color(0xFFFFF9E6);
static const Color siroGoldDark = Color(0xFF8C6B1C);
static const Color siroGoldBorder = Color(0x40D4AF37);
static const Color coralDanger = Color(0xFFDC2626);
// Borders & Dividers
+1 -1
View File
@@ -55,7 +55,7 @@ class SiroMapsApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'خرائط أوروك - Uruk Map',
title: 'خرائط سيرو - Siro Map',
debugShowCheckedModeBanner: false,
theme: AppTheme.lightTheme,
locale: const Locale('ar', 'JO'),
+29 -4
View File
@@ -21,6 +21,7 @@ import 'widgets/report_hazard_sheet.dart';
import 'widgets/add_place_sheet.dart';
import 'widgets/vehicle_customizer_sheet.dart';
import 'widgets/about_awards_sheet.dart';
import 'widgets/cinematic_3d_studio_sheet.dart';
class MapView extends StatefulWidget {
const MapView({super.key});
@@ -116,6 +117,18 @@ class _MapViewState extends State<MapView> {
);
}
void _showCinematic3DStudio(BuildContext context, NavigationCubit cubit, NavigationState state) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (_) => Cinematic3DStudioSheet(
cubit: cubit,
state: state,
),
);
}
void _showLayerSelector(BuildContext context, NavigationCubit cubit, MapThemeType current) {
showModalBottomSheet(
context: context,
@@ -126,6 +139,10 @@ class _MapViewState extends State<MapView> {
cubit.setMapTheme(theme);
Navigator.of(context).pop();
},
onOpenCinematic3DStudio: () {
Navigator.of(context).pop();
_showCinematic3DStudio(context, cubit, cubit.state);
},
onOpenVehicleCustomizer: () {
Navigator.of(context).pop();
_showVehicleCustomizer(context, cubit, cubit.state);
@@ -1251,6 +1268,14 @@ class _MapViewState extends State<MapView> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 3D Cinematic Studio Button
_buildFloatingCircle(
icon: Icons.view_in_ar_rounded,
color: const Color(0xFFEA580C),
tooltip: 'استوديو التضاريس والسينما 3D',
onTap: () => _showCinematic3DStudio(context, cubit, state),
),
const SizedBox(height: 12),
// Layer Selector Button
_buildFloatingCircle(
icon: Icons.layers_rounded,
@@ -1259,11 +1284,11 @@ class _MapViewState extends State<MapView> {
onTap: () => _showLayerSelector(context, cubit, state.mapTheme),
),
const SizedBox(height: 12),
// Uruk International Prize & Platform Architecture Button
// Siro Map Platform Architecture & Info Button
_buildFloatingCircle(
icon: Icons.workspace_premium_rounded,
color: AppColors.urukGoldDark,
tooltip: 'عن جائزة أوروك والمنظومة التقنية',
icon: Icons.info_outline_rounded,
color: AppColors.appleBlue,
tooltip: 'عن سيرو ماب والمنظومة التقنية',
onTap: () => _showAboutAwardsSheet(context),
),
const SizedBox(height: 12),
@@ -56,12 +56,12 @@ class AboutAwardsSheet extends StatelessWidget {
shape: BoxShape.circle,
color: AppColors.pureWhite,
border: Border.all(
color: AppColors.urukGold.withValues(alpha: 0.45),
color: AppColors.appleBlue.withValues(alpha: 0.35),
width: 2,
),
boxShadow: [
BoxShadow(
color: AppColors.urukGold.withValues(alpha: 0.2),
color: AppColors.appleBlue.withValues(alpha: 0.15),
blurRadius: 26,
offset: const Offset(0, 8),
),
@@ -70,14 +70,14 @@ class AboutAwardsSheet extends StatelessWidget {
padding: const EdgeInsets.all(6),
child: ClipOval(
child: Image.asset(
'assets/images/uruk_prize_logo.png',
'assets/images/siro_maps_logo.png',
fit: BoxFit.contain,
),
),
),
const SizedBox(height: 14),
Text(
'جائزة أوروك الدولية',
'خرائط سيرو',
style: GoogleFonts.alexandria(
fontSize: 22,
fontWeight: FontWeight.w800,
@@ -86,11 +86,11 @@ class AboutAwardsSheet extends StatelessWidget {
),
const SizedBox(height: 2),
Text(
'URUK INTERNATIONAL PRIZE',
'SIRO MAP',
style: GoogleFonts.alexandria(
fontSize: 12,
fontWeight: FontWeight.w700,
color: AppColors.urukGoldDark,
color: AppColors.appleBlue,
letterSpacing: 1.5,
),
),
@@ -98,25 +98,25 @@ class AboutAwardsSheet extends StatelessWidget {
Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6),
decoration: BoxDecoration(
color: AppColors.urukGoldLight,
color: AppColors.surfaceMuted,
borderRadius: BorderRadius.circular(20),
border: Border.all(color: AppColors.urukGoldBorder),
border: Border.all(color: AppColors.borderSubtle),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.workspace_premium_rounded,
Icons.verified_rounded,
size: 16,
color: AppColors.urukGoldDark,
color: AppColors.appleBlue,
),
const SizedBox(width: 6),
Text(
'رعاية ودعم الابتكار والخدمات التقنية',
'منظومة الملاحة والخرائط الذكية المستقلة',
style: GoogleFonts.alexandria(
fontSize: 11.5,
fontWeight: FontWeight.w700,
color: AppColors.urukGoldDark,
color: AppColors.textPrimary,
),
),
],
@@ -128,16 +128,16 @@ class AboutAwardsSheet extends StatelessWidget {
const SizedBox(height: 22),
// ── 2. URUK PRIZE MISSION & ROLE ──
// ── 2. SIRO MAP MISSION & VISION ──
_buildSectionCard(
icon: Icons.lightbulb_rounded,
iconColor: AppColors.urukGoldDark,
title: 'دور جائزة أوروك ورسالتها التقنية',
icon: Icons.explore_rounded,
iconColor: AppColors.appleBlue,
title: 'عن سيرو ماب والرؤية التقنية',
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'تستلهم جائزة أوروك الدولية رمزيتها من حضارة أوروك العريقة — مهد التنظيم المدني والقياسات الأولى في تاريخ الإنسانية — لتبني وتدعم المشاريع والخدمات التقنية المبتكرة في العالم العربي والشرق الأوسط.',
'تعتمد خرائط سيرو (Siro Map) على منظومة خرائط وملاحة فيكتورية متقدمة ومستضافة ذاتياً، لتقديم حلول مكانية متطورة تخدم التنقل الذكي وسلاسل الإمداد في العالم العربي ومنطقة الشرق الأوسط وشمال أفريقيا.',
style: GoogleFonts.alexandria(
fontSize: 12.5,
height: 1.65,
@@ -147,7 +147,7 @@ class AboutAwardsSheet extends StatelessWidget {
),
const SizedBox(height: 10),
Text(
'تعمل الجائزة وبرامجها على تشجيع التوسع في البنى التحتية الرقمية، وتمكين الحلول الذكية المستقلة التي تسد الفجوات التقنية وتخدم المجتمعات وقطاعات النقل والحركة بكفاءة عالية.',
'تهدف المنظومة إلى تمكين الاستقلالية الرقمية الجغرافية الكاملة، وتقديم خرائط عالية السرعة والدقة مع خفض جذري في تكاليف واستهلاك البيانات مقارنة بالخدمات العالمية التقليدية.',
style: GoogleFonts.alexandria(
fontSize: 12.5,
height: 1.65,
@@ -191,7 +191,7 @@ class AboutAwardsSheet extends StatelessWidget {
const Divider(height: 18, color: AppColors.borderSubtle),
_buildTechRow(
icon: Icons.public_rounded,
iconColor: AppColors.urukGoldDark,
iconColor: AppColors.appleBlue,
title: 'تغطية الأسواق الإقليمية الحيوية',
desc: 'تركيز استراتيجي على توفير بيانات طرق تفصيلية ومحدثة للأسواق التي تعاني من نقص أو قيود في الخرائط العالمية (العراق، السودان، اليمن، سوريا، والمنطقة).',
),
@@ -55,7 +55,7 @@ class _AddPlaceSheetState extends State<AddPlaceSheet> {
),
const SizedBox(height: 18),
const Text(
'إضافة مكان جديد إلى خرائط أوروك',
'إضافة مكان جديد إلى خرائط سيرو',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700),
),
@@ -0,0 +1,756 @@
import 'dart:async';
import 'package:flutter/material.dart';
import '../../../../core/constants/app_colors.dart';
import '../../../../logic/cubits/navigation/navigation_cubit.dart';
import '../../../../logic/cubits/navigation/navigation_state.dart';
class Cinematic3DStudioSheet extends StatefulWidget {
final NavigationCubit cubit;
final NavigationState state;
const Cinematic3DStudioSheet({
super.key,
required this.cubit,
required this.state,
});
@override
State<Cinematic3DStudioSheet> createState() => _Cinematic3DStudioSheetState();
}
class _Cinematic3DStudioSheetState extends State<Cinematic3DStudioSheet> {
// Camera Tilt State
double _tilt = 55.0;
// Orbit State
bool _isOrbiting = false;
double _orbitSpeed = 1.0;
Timer? _orbitTimer;
// Sun & Shadow Simulation State
// Range: 330 minutes (05:30 AM) to 1260 minutes (09:00 PM)
int _sunTimeMinutes = 1110; // Default: 18:30 (Golden Hour Sunset)
bool _isSunPlaying = false;
Timer? _sunTimer;
// Layer Toggles
bool _showBuildings = true;
bool _showContours = true;
bool _showHillshading = true;
@override
void initState() {
super.initState();
// Get initial camera tilt if available
final initialPos = widget.cubit.mapController?.cameraPosition;
if (initialPos != null && initialPos.tilt > 0) {
_tilt = initialPos.tilt;
} else {
// Set to 55 degrees for instant 3D perspective
widget.cubit.mapController?.setTilt(55.0);
}
// Apply initial golden hour lighting
WidgetsBinding.instance.addPostFrameCallback((_) {
_applySunLighting(_sunTimeMinutes);
});
}
@override
void dispose() {
_orbitTimer?.cancel();
_sunTimer?.cancel();
super.dispose();
}
// ── Orbit Logic ──
void _toggleOrbit() {
setState(() {
_isOrbiting = !_isOrbiting;
});
_orbitTimer?.cancel();
if (_isOrbiting) {
_orbitTimer = Timer.periodic(const Duration(milliseconds: 60), (_) {
if (!mounted || !_isOrbiting) return;
widget.cubit.mapController?.orbitStep(
_orbitSpeed,
duration: const Duration(milliseconds: 60),
);
});
}
}
// ── Sun & Shadows Simulation Logic ──
void _toggleSunAutoPlay() {
setState(() {
_isSunPlaying = !_isSunPlaying;
});
_sunTimer?.cancel();
if (_isSunPlaying) {
_sunTimer = Timer.periodic(const Duration(milliseconds: 130), (_) {
if (!mounted || !_isSunPlaying) return;
setState(() {
_sunTimeMinutes += 12;
if (_sunTimeMinutes > 1260) {
_sunTimeMinutes = 330; // Loop back to 05:30 AM
}
});
_applySunLighting(_sunTimeMinutes);
});
}
}
void _onSunSliderChanged(double value) {
setState(() {
_sunTimeMinutes = value.toInt();
});
_applySunLighting(_sunTimeMinutes);
}
void _setPresetTime(int minutes) {
setState(() {
_sunTimeMinutes = minutes;
});
_applySunLighting(minutes);
}
void _applySunLighting(int minutes) {
// Fraction of daylight cycle: 0.0 (05:30) to 1.0 (21:00)
final double fraction = ((minutes - 330) / (1260 - 330)).clamp(0.0, 1.0);
// Azimuth sweeps from 75° (East - Sunrise) to 180° (South - Noon) to 290° (West - Sunset)
final double sunAzimuth = 75.0 + (fraction * 215.0);
String shadowColor;
String highlightColor;
String buildingColor;
double opacity = 0.88;
if (minutes < 420) {
// Dawn (05:30 - 07:00)
shadowColor = '#4c1d95'; // Deep violet dawn shadow
highlightColor = '#fed7aa'; // Peach highlight
buildingColor = '#fbcfe8'; // Morning rose tint
opacity = 0.85;
} else if (minutes < 660) {
// Morning (07:00 - 11:00)
shadowColor = '#334155';
highlightColor = '#ffffff';
buildingColor = '#fef08a'; // Golden morning sun
opacity = 0.88;
} else if (minutes < 840) {
// Noon (11:00 - 14:00)
shadowColor = '#1e293b'; // Crisp direct shadow
highlightColor = '#ffffff';
buildingColor = '#f8fafc'; // Crisp bright daylight
opacity = 0.90;
} else if (minutes < 1050) {
// Afternoon (14:00 - 17:30)
shadowColor = '#374151';
highlightColor = '#ffedd5';
buildingColor = '#fed7aa'; // Warm afternoon sun
opacity = 0.88;
} else if (minutes < 1170) {
// Sunset / Golden Hour (17:30 - 19:30)
shadowColor = '#3b0764'; // Dramatic deep purple-amber shadow
highlightColor = '#ffedd5';
buildingColor = '#ea580c'; // Glowing warm sunset orange
opacity = 0.92;
} else {
// Night / Twilight (19:30 - 21:00)
shadowColor = '#020617';
highlightColor = '#60a5fa'; // Cool blue moonlight
buildingColor = '#1e293b'; // Dark sapphire buildings
opacity = 0.80;
}
widget.cubit.mapController?.updateSunSimulation(
sunAzimuth: sunAzimuth,
shadowColorHex: shadowColor,
highlightColorHex: highlightColor,
buildingColorHex: buildingColor,
buildingOpacity: opacity,
);
}
String _formatSunTime(int minutes) {
final int hours = minutes ~/ 60;
final int mins = minutes % 60;
final String minsStr = mins.toString().padLeft(2, '0');
final String period = hours >= 12 ? 'م' : 'ص';
final int displayHour = hours > 12 ? hours - 12 : (hours == 0 ? 12 : hours);
String label = '';
if (minutes < 420) {
label = 'الفجر والشروق 🌅';
} else if (minutes < 660) {
label = 'الصباح الباكر ☀️';
} else if (minutes < 840) {
label = 'الظهيرة الساطعة 🌤️';
} else if (minutes < 1050) {
label = 'العصر ⛅';
} else if (minutes < 1170) {
label = 'الغروب الذهبي 🌇';
} else {
label = 'الليل التكتيكي 🌙';
}
return '$displayHour:$minsStr $period • $label';
}
// ── Tilt Logic ──
void _setTilt(double newTilt) {
setState(() => _tilt = newTilt);
widget.cubit.mapController?.setTilt(newTilt);
}
// ── Layer Toggles ──
void _toggleBuildings() {
setState(() => _showBuildings = !_showBuildings);
widget.cubit.mapController?.setLayerVisibility('building-3d', _showBuildings);
widget.cubit.mapController?.setLayerVisibility('building-3d-osm', _showBuildings);
}
void _toggleContours() {
setState(() => _showContours = !_showContours);
widget.cubit.mapController?.setLayerVisibility('tactical-contour-minor', _showContours);
widget.cubit.mapController?.setLayerVisibility('tactical-contour-major', _showContours);
widget.cubit.mapController?.setLayerVisibility('opentopo-contour-lines', _showContours);
}
void _toggleHillshading() {
setState(() => _showHillshading = !_showHillshading);
widget.cubit.mapController?.setLayerVisibility('hillshading', _showHillshading);
}
@override
Widget build(BuildContext context) {
final isSatellite = widget.state.mapTheme == MapThemeType.satellite;
final double fraction = ((_sunTimeMinutes - 330) / (1260 - 330)).clamp(0.0, 1.0);
final double sunAzimuth = 75.0 + (fraction * 215.0);
return Container(
padding: const EdgeInsets.fromLTRB(20, 16, 20, 36),
decoration: const BoxDecoration(
color: AppColors.pureWhite,
borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
boxShadow: [
BoxShadow(
color: Color(0x28000000),
blurRadius: 28,
offset: Offset(0, -8),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Drag Handle
Center(
child: Container(
width: 42,
height: 4.5,
decoration: BoxDecoration(
color: AppColors.borderGlass,
borderRadius: BorderRadius.circular(3),
),
),
),
const SizedBox(height: 14),
// Header
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
width: 38,
height: 38,
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFFEA580C), Color(0xFFF59E0B)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(11),
boxShadow: [
BoxShadow(
color: const Color(0xFFEA580C).withValues(alpha: 0.35),
blurRadius: 10,
),
],
),
child: const Icon(Icons.view_in_ar_rounded, color: Colors.white, size: 22),
),
const SizedBox(width: 12),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'استوديو التضاريس والسينما 3D',
style: TextStyle(
fontSize: 15.5,
fontWeight: FontWeight.w800,
color: AppColors.textPrimary,
),
),
Text(
'دوران سينمائي • محاكاة حركة الشمس والظلال',
style: TextStyle(fontSize: 11, color: AppColors.textSecondary),
),
],
),
],
),
IconButton(
onPressed: () => Navigator.of(context).pop(),
icon: const Icon(Icons.close_rounded, color: AppColors.textMuted),
),
],
),
const SizedBox(height: 18),
const Divider(height: 1, color: AppColors.borderSubtle),
const SizedBox(height: 16),
// ── 1. DAY-TO-NIGHT SUN & SHADOWS SIMULATION (Stationary Location) ──
Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: const Color(0xFF0F172A),
borderRadius: BorderRadius.circular(18),
border: Border.all(color: const Color(0xFF334155)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: const Color(0xFFEA580C).withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(8),
),
child: const Icon(Icons.wb_sunny_rounded, color: Color(0xFFFB923C), size: 16),
),
const SizedBox(width: 8),
const Text(
'محاكاة حركة الشمس وسقوط الظلال',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
],
),
// Auto-Play Toggle Button
InkWell(
onTap: _toggleSunAutoPlay,
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: _isSunPlaying
? const Color(0xFFEA580C)
: Colors.white.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: _isSunPlaying
? const Color(0xFFEA580C)
: Colors.white.withValues(alpha: 0.2),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
_isSunPlaying ? Icons.pause_rounded : Icons.play_arrow_rounded,
size: 14,
color: Colors.white,
),
const SizedBox(width: 4),
Text(
_isSunPlaying ? 'إيقاف الدورة' : 'دورة تلقائية',
style: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
],
),
),
),
],
),
const SizedBox(height: 6),
const Text(
'المكان ثابت: وحركة الضوء تحاكي زاوية الشمس لرؤية تشكل وظلال المباني والجبال',
style: TextStyle(fontSize: 10.5, color: Color(0xFF94A3B8)),
),
const SizedBox(height: 12),
// Current Time Display & Azimuth
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_formatSunTime(_sunTimeMinutes),
style: const TextStyle(
fontSize: 12.5,
fontWeight: FontWeight.w800,
color: Color(0xFFFDBA74),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 2),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(6),
),
child: Text(
'زاوية الإسقاط: ${sunAzimuth.toStringAsFixed(0)}°',
style: const TextStyle(fontSize: 10, color: Color(0xFFCBD5E1)),
),
),
],
),
const SizedBox(height: 6),
// Slider
SliderTheme(
data: SliderTheme.of(context).copyWith(
activeTrackColor: const Color(0xFFEA580C),
inactiveTrackColor: Colors.white.withValues(alpha: 0.15),
thumbColor: const Color(0xFFFB923C),
overlayColor: const Color(0xFFEA580C).withValues(alpha: 0.2),
trackHeight: 4,
),
child: Slider(
min: 330.0,
max: 1260.0,
value: _sunTimeMinutes.toDouble(),
onChanged: _onSunSliderChanged,
),
),
// Quick Sun Period Buttons
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildSunPeriodChip('06:00 ص', 'الفجر', 360),
_buildSunPeriodChip('09:00 ص', 'الصباح', 540),
_buildSunPeriodChip('12:00 م', 'الظهيرة', 720),
_buildSunPeriodChip('06:30 م', 'الغروب', 1110),
_buildSunPeriodChip('08:30 م', 'الليل', 1230),
],
),
],
),
),
const SizedBox(height: 16),
// ── 2. CINEMATIC 360° ORBIT & CAMERA TILT ──
Row(
children: [
// Orbit Button
Expanded(
child: InkWell(
onTap: _toggleOrbit,
borderRadius: BorderRadius.circular(16),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 13, horizontal: 12),
decoration: BoxDecoration(
color: _isOrbiting
? AppColors.appleBlue.withValues(alpha: 0.1)
: AppColors.surfaceMuted,
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: _isOrbiting ? AppColors.appleBlue : AppColors.borderSubtle,
width: _isOrbiting ? 2 : 1,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.rotate_right_rounded,
color: _isOrbiting ? AppColors.appleBlue : AppColors.textPrimary,
size: 20,
),
const SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_isOrbiting ? 'الدوران نشط 360°' : 'دوران سينمائي',
style: TextStyle(
fontSize: 12.5,
fontWeight: FontWeight.w700,
color: _isOrbiting ? AppColors.appleBlue : AppColors.textPrimary,
),
),
Text(
_isOrbiting ? 'انقر للإيقاف' : 'التفاف حول الموقع',
style: const TextStyle(fontSize: 10, color: AppColors.textMuted),
),
],
),
],
),
),
),
),
const SizedBox(width: 10),
// Orbit Speed Selector (When active)
if (_isOrbiting)
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
decoration: BoxDecoration(
color: AppColors.surfaceMuted,
borderRadius: BorderRadius.circular(14),
border: Border.all(color: AppColors.borderSubtle),
),
child: Row(
children: [
_buildSpeedChip(0.6, 'بطيء'),
_buildSpeedChip(1.2, 'سلس'),
_buildSpeedChip(2.4, 'سريع'),
],
),
),
],
),
const SizedBox(height: 14),
// ── 3. CAMERA TILT CONTROLS ──
Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
decoration: BoxDecoration(
color: AppColors.surfaceMuted,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.borderSubtle),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'إمالة الكاميرا للأفق (Camera Tilt):',
style: TextStyle(
fontSize: 12.5,
fontWeight: FontWeight.w700,
color: AppColors.textPrimary,
),
),
Text(
'${_tilt.toStringAsFixed(0)}°',
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w800,
color: AppColors.appleBlue,
),
),
],
),
const SizedBox(height: 8),
Row(
children: [
_buildTiltPresetChip(0.0, '2D مسطح (0°)'),
const SizedBox(width: 8),
_buildTiltPresetChip(45.0, '3D كتل (45°)'),
const SizedBox(width: 8),
_buildTiltPresetChip(60.0, 'أفق سينمائي (60°)'),
],
),
],
),
),
const SizedBox(height: 14),
// ── 4. 3D LAYERS TOGGLES ──
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildFeatureToggle(
title: 'المباني 3D',
icon: Icons.apartment_rounded,
active: _showBuildings,
onTap: _toggleBuildings,
),
_buildFeatureToggle(
title: 'خطوط الكنتور',
icon: Icons.layers_outlined,
active: _showContours,
onTap: _toggleContours,
),
_buildFeatureToggle(
title: 'ظلال التضاريس',
icon: Icons.landscape_rounded,
active: _showHillshading,
onTap: _toggleHillshading,
),
_buildFeatureToggle(
title: 'أقمار صناعية',
icon: Icons.satellite_alt_rounded,
active: isSatellite,
onTap: () {
widget.cubit.setMapTheme(
isSatellite ? MapThemeType.vectorLight : MapThemeType.satellite,
);
},
),
],
),
],
),
);
}
Widget _buildSunPeriodChip(String time, String label, int minutes) {
final bool isSelected = (_sunTimeMinutes - minutes).abs() < 40;
return InkWell(
onTap: () => _setPresetTime(minutes),
borderRadius: BorderRadius.circular(6),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
decoration: BoxDecoration(
color: isSelected
? const Color(0xFFEA580C)
: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(6),
),
child: Column(
children: [
Text(
label,
style: TextStyle(
fontSize: 9.5,
fontWeight: isSelected ? FontWeight.w800 : FontWeight.w500,
color: isSelected ? Colors.white : const Color(0xFFCBD5E1),
),
),
Text(
time,
style: TextStyle(
fontSize: 8.5,
color: isSelected ? Colors.white.withValues(alpha: 0.9) : const Color(0xFF64748B),
),
),
],
),
),
);
}
Widget _buildSpeedChip(double speed, String label) {
final bool isSelected = (_orbitSpeed - speed).abs() < 0.1;
return InkWell(
onTap: () => setState(() => _orbitSpeed = speed),
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 5),
decoration: BoxDecoration(
color: isSelected ? AppColors.appleBlue : Colors.transparent,
borderRadius: BorderRadius.circular(8),
),
child: Text(
label,
style: TextStyle(
fontSize: 10.5,
fontWeight: isSelected ? FontWeight.w700 : FontWeight.w500,
color: isSelected ? Colors.white : AppColors.textSecondary,
),
),
),
);
}
Widget _buildTiltPresetChip(double tiltValue, String label) {
final bool isSelected = (_tilt - tiltValue).abs() < 4.0;
return Expanded(
child: InkWell(
onTap: () => _setTilt(tiltValue),
borderRadius: BorderRadius.circular(10),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 8),
decoration: BoxDecoration(
color: isSelected ? AppColors.appleBlue : Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: isSelected ? AppColors.appleBlue : AppColors.borderSubtle,
),
),
child: Text(
label,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 11,
fontWeight: isSelected ? FontWeight.w700 : FontWeight.w600,
color: isSelected ? Colors.white : AppColors.textPrimary,
),
),
),
),
);
}
Widget _buildFeatureToggle({
required String title,
required IconData icon,
required bool active,
required VoidCallback onTap,
}) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Container(
width: 76,
padding: const EdgeInsets.symmetric(vertical: 9),
decoration: BoxDecoration(
color: active
? AppColors.appleBlue.withValues(alpha: 0.08)
: AppColors.surfaceMuted,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: active ? AppColors.appleBlue : AppColors.borderSubtle,
width: active ? 1.5 : 1,
),
),
child: Column(
children: [
Icon(
icon,
size: 20,
color: active ? AppColors.appleBlue : AppColors.textMuted,
),
const SizedBox(height: 5),
Text(
title,
style: TextStyle(
fontSize: 10,
fontWeight: active ? FontWeight.w700 : FontWeight.w500,
color: active ? AppColors.appleBlue : AppColors.textSecondary,
),
),
],
),
),
);
}
}
@@ -7,6 +7,7 @@ class LayerSelectorSheet extends StatelessWidget {
final ValueChanged<MapThemeType> onThemeChanged;
final VoidCallback? onOpenVehicleCustomizer;
final VoidCallback? onOpenAboutAwards;
final VoidCallback? onOpenCinematic3DStudio;
const LayerSelectorSheet({
super.key,
@@ -14,6 +15,7 @@ class LayerSelectorSheet extends StatelessWidget {
required this.onThemeChanged,
this.onOpenVehicleCustomizer,
this.onOpenAboutAwards,
this.onOpenCinematic3DStudio,
});
@override
@@ -68,6 +70,43 @@ class LayerSelectorSheet extends StatelessWidget {
),
],
),
if (onOpenCinematic3DStudio != null) ...[
const SizedBox(height: 16),
ListTile(
onTap: onOpenCinematic3DStudio,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
side: const BorderSide(color: Color(0x33EA580C)),
),
tileColor: const Color(0xFFEA580C).withValues(alpha: 0.08),
leading: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFFEA580C), Color(0xFFF59E0B)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12),
),
child: const Icon(Icons.view_in_ar_rounded, color: Colors.white, size: 22),
),
title: const Text(
'استوديو التضاريس والسينما 3D',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w800,
color: AppColors.textPrimary,
),
),
subtitle: const Text(
'دوران سينمائي 360° • محاكاة حركة الشمس وسقوط الظلال',
style: TextStyle(fontSize: 11, color: Color(0xFFEA580C), fontWeight: FontWeight.w600),
),
trailing: const Icon(Icons.arrow_forward_ios_rounded, size: 14, color: Color(0xFFEA580C)),
),
],
if (onOpenVehicleCustomizer != null) ...[
const SizedBox(height: 18),
const Divider(height: 1, color: AppColors.borderSubtle),
@@ -106,37 +145,37 @@ class LayerSelectorSheet extends StatelessWidget {
onTap: onOpenAboutAwards,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
side: const BorderSide(color: AppColors.urukGoldBorder),
side: const BorderSide(color: AppColors.borderSubtle),
),
tileColor: AppColors.urukGoldLight,
tileColor: AppColors.surfaceMuted,
leading: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: AppColors.pureWhite,
shape: BoxShape.circle,
border: Border.all(color: AppColors.urukGold.withValues(alpha: 0.4)),
border: Border.all(color: AppColors.borderSubtle),
),
child: ClipOval(
child: Image.asset(
'assets/images/uruk_prize_logo.png',
'assets/images/siro_maps_logo.png',
fit: BoxFit.contain,
),
),
),
title: const Text(
'عن منظومة أوروك والتقنيات المفعلة',
'عن منظومة سيرو ماب والتقنيات المفعلة',
style: TextStyle(
fontSize: 13.5,
fontWeight: FontWeight.w700,
color: AppColors.urukGoldDark,
color: AppColors.textPrimary,
),
),
subtitle: const Text(
'الكاش الذكي، مفاتيح الأجهزة، والملاحة دون اتصال',
style: TextStyle(fontSize: 11, color: AppColors.textSecondary),
),
trailing: const Icon(Icons.workspace_premium_rounded, size: 20, color: AppColors.urukGoldDark),
trailing: const Icon(Icons.info_outline_rounded, size: 20, color: AppColors.appleBlue),
),
],
],
@@ -75,20 +75,20 @@ class _SplashViewState extends State<SplashView> with SingleTickerProviderStateM
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Luxury Uruk Emblem Container
// Luxury Siro Maps Emblem Container
Container(
width: 114,
height: 114,
width: 116,
height: 116,
decoration: BoxDecoration(
color: const Color(0xFF131722),
borderRadius: BorderRadius.circular(32),
border: Border.all(
color: AppColors.urukGold.withValues(alpha: 0.35),
color: AppColors.appleBlue.withValues(alpha: 0.35),
width: 1.5,
),
boxShadow: [
BoxShadow(
color: AppColors.urukGold.withValues(alpha: 0.22),
color: AppColors.appleBlue.withValues(alpha: 0.18),
blurRadius: 36,
offset: const Offset(0, 14),
),
@@ -102,7 +102,7 @@ class _SplashViewState extends State<SplashView> with SingleTickerProviderStateM
child: ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Image.asset(
'assets/images/siro_uruk_logo.png',
'assets/images/siro_maps_logo.png',
fit: BoxFit.cover,
),
),
@@ -110,7 +110,7 @@ class _SplashViewState extends State<SplashView> with SingleTickerProviderStateM
const SizedBox(height: 24),
// App Title
Text(
'خرائط أوروك',
'خرائط سيرو',
style: GoogleFonts.alexandria(
fontSize: 28,
fontWeight: FontWeight.w800,
@@ -121,104 +121,13 @@ class _SplashViewState extends State<SplashView> with SingleTickerProviderStateM
const SizedBox(height: 6),
// Subtitle
Text(
'Uruk Map • منظومة الخرائط والملاحة الذكية',
'Siro Map • منظومة الخرائط والملاحة الذكية',
style: GoogleFonts.alexandria(
fontSize: 13,
fontWeight: FontWeight.w600,
color: AppColors.textSecondary,
),
),
const SizedBox(height: 26),
// Official Uruk International Prize Award Badge
Container(
constraints: const BoxConstraints(maxWidth: 340),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 11),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [
Color(0xFFFFFDF7),
Color(0xFFFFF6D8),
],
begin: Alignment.topRight,
end: Alignment.bottomLeft,
),
borderRadius: BorderRadius.circular(18),
border: Border.all(color: AppColors.urukGoldBorder, width: 1.2),
boxShadow: [
BoxShadow(
color: AppColors.urukGold.withValues(alpha: 0.14),
blurRadius: 22,
offset: const Offset(0, 8),
),
],
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 44,
height: 44,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.pureWhite,
border: Border.all(
color: AppColors.urukGold.withValues(alpha: 0.4),
width: 1.2,
),
),
child: ClipOval(
child: Image.asset(
'assets/images/uruk_prize_logo.png',
fit: BoxFit.contain,
),
),
),
const SizedBox(width: 12),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.workspace_premium_rounded,
size: 16,
color: AppColors.urukGoldDark,
),
const SizedBox(width: 4),
Flexible(
child: Text(
'الحائز على جائزة أوروك الدولية',
style: GoogleFonts.alexandria(
fontSize: 12,
fontWeight: FontWeight.w700,
color: AppColors.urukGoldDark,
),
),
),
],
),
const SizedBox(height: 2),
Text(
'مشروع منبثق عن برنامج جوائز أوروك للسيادة الرقمية',
style: GoogleFonts.alexandria(
fontSize: 10,
fontWeight: FontWeight.w500,
color: AppColors.textSecondary,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
const SizedBox(height: 28),
// Regional Sovereignty Pill Badge
Container(
@@ -5,10 +5,10 @@
// 'flutter create' template.
// The application's name. By default this is also the title of the Flutter window.
PRODUCT_NAME = uruk_map
PRODUCT_NAME = siro_maps
// The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = com.urukmap.app
// The copyright displayed in application information
PRODUCT_COPYRIGHT = Copyright © 2026 com.urukmap. All rights reserved.
PRODUCT_COPYRIGHT = Copyright © 2026 Siro Map. All rights reserved.
+6 -6
View File
@@ -627,10 +627,10 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
url: "https://pub.dev"
source: hosted
version: "0.12.18"
version: "0.12.19"
material_color_utilities:
dependency: transitive
description:
@@ -643,10 +643,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
url: "https://pub.dev"
source: hosted
version: "1.17.0"
version: "1.18.0"
mime:
dependency: transitive
description:
@@ -1032,10 +1032,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
url: "https://pub.dev"
source: hosted
version: "0.7.9"
version: "0.7.11"
typed_data:
dependency: transitive
description:
+1 -1
View File
@@ -27,7 +27,7 @@ void main() {
),
);
expect(find.text('خرائط أوروك'), findsOneWidget);
expect(find.text('خرائط سيرو'), findsOneWidget);
expect(find.textContaining('v2.4 PRO'), findsOneWidget);
await tester.pump(const Duration(milliseconds: 3000));