fix marker rendering & modernize riding widgets for dark mode - 2026-04-11
This commit is contained in:
@@ -7,12 +7,22 @@ import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
import 'navigation_controller.dart';
|
||||
|
||||
// ─── Brand colours ───────────────────────────────────────────────────────────
|
||||
const Color _kBlue = Color(0xFF1A73E8);
|
||||
const Color _kBlueDark = Color(0xFF0D47A1);
|
||||
const Color _kSurface = Color(0xFFFFFFFF);
|
||||
const Color _kText = Color(0xFF1C1C1E);
|
||||
const Color _kSubtext = Color(0xFF6B7280);
|
||||
const Color _kGreen = Color(0xFF34A853);
|
||||
// ─── Theme-aware Brand colours ──────────────────────────────────────────────
|
||||
Color get _kBlue => const Color(0xFF1A73E8);
|
||||
Color get _kBlueDark => const Color(0xFF0D47A1);
|
||||
Color get _kSurface =>
|
||||
Get.isDarkMode ? const Color(0xFF1E1E1E) : const Color(0xFFFFFFFF);
|
||||
Color get _kText =>
|
||||
Get.isDarkMode ? const Color(0xFFF5F5F7) : const Color(0xFF1C1C1E);
|
||||
Color get _kSubtext =>
|
||||
Get.isDarkMode ? Colors.white60 : const Color(0xFF6B7280);
|
||||
Color get _kGreen => const Color(0xFF34A853);
|
||||
Color get _kGlassSurface => Get.isDarkMode
|
||||
? Colors.black.withOpacity(0.7)
|
||||
: Colors.white.withOpacity(0.92);
|
||||
Color get _kGlassBorder => Get.isDarkMode
|
||||
? Colors.white.withOpacity(0.12)
|
||||
: Colors.white.withOpacity(0.5);
|
||||
|
||||
class NavigationView extends StatelessWidget {
|
||||
const NavigationView({super.key});
|
||||
@@ -33,7 +43,9 @@ class NavigationView extends StatelessWidget {
|
||||
onMapCreated: c.onMapCreated,
|
||||
onStyleLoadedCallback: c.onStyleLoaded,
|
||||
onMapLongClick: c.onMapLongPressed,
|
||||
styleString: "assets/style.json",
|
||||
styleString: Get.isDarkMode
|
||||
? "assets/style_dark.json"
|
||||
: "assets/style.json",
|
||||
initialCameraPosition: CameraPosition(
|
||||
target: c.myLocation ?? const LatLng(33.5138, 36.2765),
|
||||
zoom: 16.0,
|
||||
@@ -106,7 +118,7 @@ class _SearchBar extends StatelessWidget {
|
||||
controller: controller.placeDestinationController,
|
||||
onChanged: controller.onSearchChanged,
|
||||
textInputAction: TextInputAction.search,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: _kText,
|
||||
fontWeight: FontWeight.w500),
|
||||
@@ -167,8 +179,10 @@ class _SearchResults extends StatelessWidget {
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: controller.placesDestination.length,
|
||||
separatorBuilder: (_, __) =>
|
||||
Divider(height: 1, color: Colors.grey[100], indent: 56),
|
||||
separatorBuilder: (_, __) => Divider(
|
||||
height: 1,
|
||||
color: Get.isDarkMode ? Colors.white12 : Colors.grey[100],
|
||||
indent: 56),
|
||||
itemBuilder: (_, i) {
|
||||
final place = controller.placesDestination[i];
|
||||
final dist = place['distanceKm'] as double?;
|
||||
@@ -187,8 +201,8 @@ class _SearchResults extends StatelessWidget {
|
||||
color: _kBlue.withOpacity(0.08),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(Icons.place_rounded,
|
||||
color: _kBlue, size: 18),
|
||||
child:
|
||||
Icon(Icons.place_rounded, color: _kBlue, size: 18),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
@@ -196,7 +210,7 @@ class _SearchResults extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(place['name'] ?? '',
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 14.5,
|
||||
color: _kText),
|
||||
@@ -222,7 +236,7 @@ class _SearchResults extends StatelessWidget {
|
||||
),
|
||||
child: Text(
|
||||
'${dist.toStringAsFixed(1)} كم',
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
color: _kBlue,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600),
|
||||
@@ -259,11 +273,14 @@ class _TurnBanner extends StatelessWidget {
|
||||
padding: const EdgeInsets.fromLTRB(12, 10, 12, 0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: _kBlueDark,
|
||||
color: Get.isDarkMode
|
||||
? Colors.grey[900]?.withOpacity(0.95)
|
||||
: _kBlueDark,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: _kBlueDark.withOpacity(0.35),
|
||||
color: (Get.isDarkMode ? Colors.black : _kBlueDark)
|
||||
.withOpacity(0.35),
|
||||
blurRadius: 20,
|
||||
offset: const Offset(0, 6)),
|
||||
],
|
||||
@@ -274,14 +291,14 @@ class _TurnBanner extends StatelessWidget {
|
||||
children: [
|
||||
// Turn arrow icon
|
||||
Container(
|
||||
width: 52,
|
||||
height: 52,
|
||||
width: 64,
|
||||
height: 64,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.15),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: const Icon(Icons.turn_right_rounded,
|
||||
color: Colors.white, size: 30),
|
||||
color: Colors.white, size: 40),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
|
||||
@@ -293,16 +310,16 @@ class _TurnBanner extends StatelessWidget {
|
||||
Text(
|
||||
controller.distanceToNextStep,
|
||||
style: const TextStyle(
|
||||
color: Colors.white70,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500),
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
controller.currentInstruction,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 19,
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1.2),
|
||||
maxLines: 2,
|
||||
@@ -429,7 +446,7 @@ class _RouteSummaryCard extends StatelessWidget {
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
decoration: BoxDecoration(
|
||||
color: _kSurface,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
boxShadow: [
|
||||
@@ -520,20 +537,20 @@ class _InfoPill extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: color.withOpacity(0.08),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(color: color.withOpacity(0.2)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(icon, color: color, size: 15),
|
||||
const SizedBox(width: 5),
|
||||
Icon(icon, color: color, size: 22),
|
||||
const SizedBox(width: 8),
|
||||
Text(label,
|
||||
style: TextStyle(
|
||||
color: color, fontSize: 13.5, fontWeight: FontWeight.w700)),
|
||||
color: color, fontSize: 18, fontWeight: FontWeight.w800)),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -577,22 +594,27 @@ class _NavigationHUD extends StatelessWidget {
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF8F9FA),
|
||||
color: Get.isDarkMode
|
||||
? Colors.white.withOpacity(0.05)
|
||||
: const Color(0xFFF8F9FA),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: Colors.grey.withOpacity(0.15)),
|
||||
border: Border.all(
|
||||
color: Get.isDarkMode
|
||||
? Colors.white10
|
||||
: Colors.grey.withOpacity(0.15)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.arrow_forward_rounded,
|
||||
size: 15, color: _kSubtext),
|
||||
const SizedBox(width: 8),
|
||||
size: 20, color: _kSubtext),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
controller.nextInstruction,
|
||||
style: TextStyle(
|
||||
color: _kSubtext,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500),
|
||||
color: _kText,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@@ -636,13 +658,13 @@ class _NavigationHUD extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.stop_rounded,
|
||||
color: Colors.redAccent, size: 16),
|
||||
const SizedBox(width: 5),
|
||||
color: Colors.redAccent, size: 24),
|
||||
const SizedBox(width: 6),
|
||||
const Text('إيقاف',
|
||||
style: TextStyle(
|
||||
color: Colors.redAccent,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w700)),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -669,44 +691,61 @@ class _SpeedBadge extends StatelessWidget {
|
||||
final bool fast = kmh > 100;
|
||||
|
||||
return Positioned(
|
||||
bottom: MediaQuery.of(context).padding.bottom + 130,
|
||||
left: 14,
|
||||
child: Container(
|
||||
width: 62,
|
||||
height: 62,
|
||||
decoration: BoxDecoration(
|
||||
color: fast ? const Color(0xFFD93025) : _kSurface,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: fast ? Colors.red.withOpacity(0.3) : Colors.grey[200]!,
|
||||
width: 2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.12),
|
||||
blurRadius: 12,
|
||||
offset: const Offset(0, 4)),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'$kmh',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: fast ? Colors.white : _kText,
|
||||
height: 1),
|
||||
bottom: MediaQuery.of(context).padding.bottom + 150,
|
||||
left: 16,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
// Circular progress mimicking a speedometer
|
||||
SizedBox(
|
||||
width: 86,
|
||||
height: 86,
|
||||
child: CircularProgressIndicator(
|
||||
value: (kmh / 140.0)
|
||||
.clamp(0.0, 1.0), // Assuming 140 is max speed shown
|
||||
strokeWidth: 6,
|
||||
backgroundColor: Get.isDarkMode
|
||||
? Colors.white10
|
||||
: Colors.grey.withOpacity(0.3),
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
fast ? Colors.redAccent : _kBlue),
|
||||
),
|
||||
Text(
|
||||
'كم/س',
|
||||
style: TextStyle(
|
||||
fontSize: 9,
|
||||
color: fast ? Colors.white70 : _kSubtext,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
Container(
|
||||
width: 74,
|
||||
height: 74,
|
||||
decoration: BoxDecoration(
|
||||
color: fast ? const Color(0xFFD93025) : _kSurface,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.15),
|
||||
blurRadius: 16,
|
||||
offset: const Offset(0, 6)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'$kmh',
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: fast ? Colors.white : _kText,
|
||||
height: 1),
|
||||
),
|
||||
Text(
|
||||
'كم/س',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: fast ? Colors.white70 : _kSubtext,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -735,7 +774,7 @@ class _LoadingOverlay extends StatelessWidget {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const CircularProgressIndicator(
|
||||
CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation(_kBlue),
|
||||
strokeWidth: 3,
|
||||
),
|
||||
@@ -777,14 +816,14 @@ class _GlassCard extends StatelessWidget {
|
||||
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.92),
|
||||
color: _kGlassSurface,
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
border: Border.all(color: Colors.white.withOpacity(0.5)),
|
||||
border: Border.all(color: _kGlassBorder),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.07),
|
||||
color: Colors.black.withOpacity(Get.isDarkMode ? 0.4 : 0.07),
|
||||
blurRadius: 16,
|
||||
offset: const Offset(0, 4)),
|
||||
offset: const Offset(0, 8)),
|
||||
],
|
||||
),
|
||||
padding: padding,
|
||||
|
||||
Reference in New Issue
Block a user