chore: add build artifacts, map assets, and routing data

This commit is contained in:
Hamza-Ayed
2026-09-19 12:34:24 +03:00
parent aa2b9f131f
commit 43ad2e0ad4
327 changed files with 52421 additions and 1810 deletions
@@ -0,0 +1,30 @@
import '../env/env.dart';
class ApiConstants {
ApiConstants._();
// Official Keys extracted from Siro Ecosystem (Encrypted & Obfuscated via Envied)
static final String mapSaasKey = Env.mapSaasApiKey;
static final String googleMapApiKey = Env.googleMapApiKey;
// MapSaaS Endpoints
static const String mapSaasRoute = 'https://map-saas.intaleqapp.com/api/maps/route';
static const String mapSaasSearch = 'https://map-saas.intaleqapp.com/api/geocoding/search';
static const String mapSaasPlaces = 'https://map-saas.intaleqapp.com/api/geocoding/places';
static const String mapSaasTelemetry = 'https://map-saas.intaleqapp.com/api/telemetry';
static const String mapSaasStyleBase = 'https://map-saas.intaleqapp.com/api/maps/style.json';
static const String googlePlacesNearby = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json';
// 50 km Radius Threshold (Strictly as specified)
static const double maxSearchRadiusMeters = 50000.0;
static const double maxSearchRadiusKm = 50.0;
// Secondary / Alternative Routing Engines
static const String osrmRouteJordan = 'https://routesjo.intaleq.xyz/route/v1/driving';
static const String osrmRouteSyria = 'https://routes-syria.siromove.com/route/v1/driving';
static const String osrmRouteEgypt = 'https://routes-egypt.siromove.com/route/v1/driving';
// Default Jordan Geospatial Center (Amman 7th Circle / Abdoun)
static const double defaultLat = 31.9539;
static const double defaultLng = 35.9106;
}
@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
class AppColors {
AppColors._();
// Pure White & Canvas
static const Color pureWhite = Color(0xFFFFFFFF);
static const Color canvasLight = Color(0xFFFBFBFD);
static const Color surfaceCard = Color(0xFFFFFFFF);
static const Color surfaceMuted = Color(0xFFF5F5F7);
// Apple Text Palette
static const Color textPrimary = Color(0xFF1D1D1F);
static const Color textSecondary = Color(0xFF424245);
static const Color textMuted = Color(0xFF86868B);
// Sovereign / Apple Accent Colors
static const Color appleBlue = Color(0xFF0071E3);
static const Color appleBlueHover = Color(0xFF0077ED);
static const Color tacticalNavy = Color(0xFF0B192C);
static const Color tacticalEmerald = Color(0xFF059669);
static const Color sovereignGold = Color(0xFFD97706);
static const Color coralDanger = Color(0xFFDC2626);
// Borders & Dividers
static const Color borderSubtle = Color(0x12000000);
static const Color borderGlass = Color(0x1F000000);
static const Color glassFill = Color(0xD1FFFFFF);
// Dark Theme Palette
static const Color darkCanvas = Color(0xFF0B0F17);
static const Color darkSurface = Color(0xFF161A22);
static const Color darkCard = Color(0xFF1F2430);
static const Color darkText = Color(0xFFF5F5F7);
}
@@ -0,0 +1,59 @@
import 'package:flutter/services.dart';
class CarPlatformBridge {
CarPlatformBridge._();
static const _channel = MethodChannel('com.siro.siro_maps/car_navigation');
static bool _isInitialized = false;
static void ensureInitialized() {
if (_isInitialized) return;
_channel.setMethodCallHandler(_handleMethodCall);
_isInitialized = true;
}
static Future<dynamic> _handleMethodCall(MethodCall call) async {
switch (call.method) {
case 'isCarAppConnected':
return false;
default:
throw MissingPluginException();
}
}
static Future<void> updateNavState({
required double lat,
required double lng,
required double bearing,
required double speed,
required String instruction,
required double distanceToStep,
required double totalDistance,
required double eta,
required int maneuver,
required bool isNavigating,
bool isMapDarkMode = false,
}) async {
try {
await _channel.invokeMethod('updateNavState', {
'lat': lat,
'lng': lng,
'bearing': bearing,
'speed': speed,
'instruction': instruction,
'distanceToStep': distanceToStep,
'totalDistance': totalDistance,
'eta': eta,
'maneuver': maneuver,
'isNavigating': isNavigating,
'isMapDarkMode': isMapDarkMode,
});
} catch (_) {}
}
static Future<void> stopNavigation() async {
try {
await _channel.invokeMethod('stopNavigation');
} catch (_) {}
}
}
@@ -0,0 +1,42 @@
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
class ConnectivityService {
ConnectivityService._();
static final ConnectivityService instance = ConnectivityService._();
final Connectivity _connectivity = Connectivity();
StreamSubscription<List<ConnectivityResult>>? _subscription;
final StreamController<bool> _controller = StreamController<bool>.broadcast();
Stream<bool> get onConnectivityChanged => _controller.stream;
Future<bool> checkConnection() async {
try {
final results = await _connectivity.checkConnectivity();
return _hasConnection(results);
} catch (_) {
return true; // Fallback to optimistic
}
}
void initialize() {
_subscription?.cancel();
_subscription = _connectivity.onConnectivityChanged.listen((results) {
_controller.add(_hasConnection(results));
});
}
bool _hasConnection(List<ConnectivityResult> results) {
return results.any((r) =>
r == ConnectivityResult.mobile ||
r == ConnectivityResult.wifi ||
r == ConnectivityResult.ethernet ||
r == ConnectivityResult.vpn);
}
void dispose() {
_subscription?.cancel();
_controller.close();
}
}
@@ -0,0 +1,81 @@
import 'dart:async';
import 'package:geolocator/geolocator.dart';
import 'package:intaleq_maps/intaleq_maps.dart';
class LocationService {
LocationService._();
static final LocationService instance = LocationService._();
Future<bool> checkAndRequestPermission() async {
print("🛰️ [LocationService] Checking location service & permissions...");
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
print("⚠️ [LocationService] Device location services are DISABLED!");
return false;
}
LocationPermission permission = await Geolocator.checkPermission();
print("🛰️ [LocationService] Current permission status: $permission");
if (permission == LocationPermission.denied) {
print("🛰️ [LocationService] Requesting location permission...");
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
print("❌ [LocationService] User DENIED location permission!");
return false;
}
}
if (permission == LocationPermission.deniedForever) {
print("❌ [LocationService] Location permission is permanently denied!");
return false;
}
print("✅ [LocationService] Location permission granted: $permission");
return true;
}
Future<Position?> getCurrentPosition() async {
final hasPerm = await checkAndRequestPermission();
if (!hasPerm) {
print("⚠️ [LocationService] Cannot get current position (permission missing)");
return null;
}
print("🛰️ [LocationService] Fetching current GPS position from hardware...");
final pos = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
),
);
print("📍 [LocationService] Acquired GPS fix: lat=${pos.latitude.toStringAsFixed(6)}, lng=${pos.longitude.toStringAsFixed(6)}, alt=${pos.altitude.toStringAsFixed(1)}m, speed=${pos.speed.toStringAsFixed(1)}m/s, heading=${pos.heading.toStringAsFixed(1)}°");
return pos;
}
Stream<Position> getPositionStream({
int distanceFilter = 2,
}) {
final locationSettings = LocationSettings(
accuracy: LocationAccuracy.bestForNavigation,
distanceFilter: distanceFilter,
);
return Geolocator.getPositionStream(locationSettings: locationSettings);
}
double calculateDistance(LatLng start, LatLng end) {
return Geolocator.distanceBetween(
start.latitude,
start.longitude,
end.latitude,
end.longitude,
);
}
double calculateBearing(LatLng start, LatLng end) {
return Geolocator.bearingBetween(
start.latitude,
start.longitude,
end.latitude,
end.longitude,
);
}
}
@@ -0,0 +1,45 @@
import 'package:flutter_tts/flutter_tts.dart';
class TtsService {
TtsService._();
static final TtsService instance = TtsService._();
final FlutterTts _flutterTts = FlutterTts();
bool _isMuted = false;
bool _isInitialized = false;
bool get isMuted => _isMuted;
Future<void> init() async {
if (_isInitialized) return;
try {
await _flutterTts.setLanguage('ar');
await _flutterTts.setSpeechRate(0.5);
await _flutterTts.setVolume(1.0);
await _flutterTts.setPitch(1.0);
_isInitialized = true;
} catch (_) {}
}
void toggleMute() {
_isMuted = !_isMuted;
if (_isMuted) {
stop();
}
}
Future<void> speak(String text) async {
if (_isMuted || text.trim().isEmpty) return;
try {
await init();
await _flutterTts.stop();
await _flutterTts.speak(text);
} catch (_) {}
}
Future<void> stop() async {
try {
await _flutterTts.stop();
} catch (_) {}
}
}
@@ -0,0 +1,48 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../constants/app_colors.dart';
class AppTheme {
AppTheme._();
static ThemeData get lightTheme {
return ThemeData(
useMaterial3: true,
brightness: Brightness.light,
fontFamily: '.SF Pro Text', // Native iOS San Francisco & SF Arabic
scaffoldBackgroundColor: AppColors.canvasLight,
colorScheme: const ColorScheme.light(
primary: AppColors.appleBlue,
secondary: AppColors.tacticalNavy,
surface: AppColors.surfaceCard,
error: AppColors.coralDanger,
onPrimary: Colors.white,
onSurface: AppColors.textPrimary,
),
textTheme: const TextTheme(
displayLarge: TextStyle(
color: AppColors.textPrimary,
fontWeight: FontWeight.w800,
letterSpacing: -0.5,
),
titleLarge: TextStyle(
color: AppColors.textPrimary,
fontWeight: FontWeight.w700,
),
bodyLarge: TextStyle(
color: AppColors.textPrimary,
fontWeight: FontWeight.w400,
),
bodyMedium: TextStyle(
color: AppColors.textSecondary,
),
),
appBarTheme: const AppBarTheme(
backgroundColor: Colors.transparent,
elevation: 0,
systemOverlayStyle: SystemUiOverlayStyle.dark,
iconTheme: IconThemeData(color: AppColors.textPrimary),
),
);
}
}
@@ -0,0 +1,31 @@
import 'package:intaleq_maps/intaleq_maps.dart';
List<LatLng> decodePolylineIsolate(String encoded) {
List<LatLng> points = [];
int index = 0, len = encoded.length;
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.codeUnitAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.codeUnitAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
points.add(LatLng(lat / 1E5, lng / 1E5));
}
return points;
}