feat: Version 3.6.3 - Carte IGN, mode boussole, corrections Flutter analyze
Nouvelles fonctionnalités: - #215 Mode boussole + carte IGN/satellite (Mode terrain) - #53 Définition zoom maximal pour éviter sur-zoom - #14 Correction bug F5 déconnexion - #204 Design couleurs flashy - #205 Écrans utilisateurs simplifiés Corrections Flutter analyze: - Suppression warnings room.g.dart, chat_service.dart, api_service.dart - 0 error, 0 warning, 30 infos (suggestions de style) Autres: - Intégration tuiles IGN Plan et IGN Ortho (geopf.fr) - flutter_compass pour Android/iOS - Réorganisation assets store Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ class BtnPassages extends StatelessWidget {
|
||||
final shouldShowLotType = _shouldShowLotType();
|
||||
|
||||
return SizedBox(
|
||||
height: 80,
|
||||
height: 92, // 80 + 12 pour le triangle indicateur
|
||||
width: double.infinity,
|
||||
child: ValueListenableBuilder<Box<PassageModel>>(
|
||||
valueListenable: Hive.box<PassageModel>(AppKeys.passagesBoxName).listenable(),
|
||||
@@ -121,6 +121,7 @@ class BtnPassages extends StatelessWidget {
|
||||
/// Colonne TOTAL (cliquable, affiche tous les passages)
|
||||
Widget _buildTotalColumn(BuildContext context, int total) {
|
||||
final bool isSelected = selectedTypeId == null;
|
||||
final Color bgColor = Colors.grey[200]!;
|
||||
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
@@ -147,55 +148,71 @@ class BtnPassages extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[200],
|
||||
border: Border.all(
|
||||
color: Colors.grey[400]!,
|
||||
width: isSelected ? 5 : 1,
|
||||
),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(AppTheme.borderRadiusMedium),
|
||||
bottomLeft: Radius.circular(AppTheme.borderRadiusMedium),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.route,
|
||||
size: 20,
|
||||
color: Colors.black54,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
total.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: bgColor,
|
||||
border: Border.all(
|
||||
color: Colors.grey[400]!,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(AppTheme.borderRadiusMedium),
|
||||
bottomLeft: Radius.circular(AppTheme.borderRadiusMedium),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.route,
|
||||
size: 20,
|
||||
color: Colors.black54,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
total.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
total > 1 ? 'passages' : 'passage',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
total > 1 ? 'passages' : 'passage',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
// Triangle indicateur de sélection
|
||||
if (isSelected)
|
||||
Center(
|
||||
child: CustomPaint(
|
||||
size: const Size(20, 12),
|
||||
painter: _TrianglePainter(color: bgColor),
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
else
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -236,62 +253,78 @@ class BtnPassages extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: couleur.withOpacity(0.1),
|
||||
border: Border.all(
|
||||
color: couleur,
|
||||
width: isSelected ? 5 : 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
iconData,
|
||||
size: 20,
|
||||
color: couleur,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
count.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: couleur,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||
child: Text(
|
||||
titre,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
border: Border.all(
|
||||
color: couleur,
|
||||
width: 1,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
iconData,
|
||||
size: 20,
|
||||
color: Colors.white,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
count.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||
child: Text(
|
||||
titre,
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Triangle indicateur de sélection
|
||||
if (isSelected)
|
||||
Center(
|
||||
child: CustomPaint(
|
||||
size: const Size(20, 12),
|
||||
painter: _TrianglePainter(color: couleur),
|
||||
),
|
||||
)
|
||||
else
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Colonne NOUVEAU PASSAGE (bouton +, fond vert)
|
||||
/// Colonne NOUVEAU PASSAGE (bouton +, fond blanc)
|
||||
Widget _buildAddColumn(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
@@ -302,47 +335,55 @@ class BtnPassages extends StatelessWidget {
|
||||
_showPassageFormDialog(context);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.buttonSuccessColor.withOpacity(0.1),
|
||||
border: Border.all(
|
||||
color: AppTheme.buttonSuccessColor,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(AppTheme.borderRadiusMedium),
|
||||
bottomRight: Radius.circular(AppTheme.borderRadiusMedium),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.add_circle_outline,
|
||||
size: 24,
|
||||
color: AppTheme.buttonSuccessColor,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'Nouveau',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: AppTheme.buttonSuccessColor,
|
||||
fontWeight: FontWeight.w600,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(
|
||||
color: Colors.grey[400]!,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(AppTheme.borderRadiusMedium),
|
||||
bottomRight: Radius.circular(AppTheme.borderRadiusMedium),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.add_circle_outline,
|
||||
size: 24,
|
||||
color: Colors.black87,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'Nouveau',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.grey[700],
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Espace pour aligner avec les autres colonnes (pas de triangle sur ce bouton)
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -377,3 +418,30 @@ class BtnPassages extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// CustomPainter pour dessiner un triangle pointant vers le bas
|
||||
class _TrianglePainter extends CustomPainter {
|
||||
final Color color;
|
||||
|
||||
_TrianglePainter({required this.color});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()
|
||||
..color = color
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
final path = Path()
|
||||
..moveTo(0, 0) // Coin supérieur gauche
|
||||
..lineTo(size.width, 0) // Coin supérieur droit
|
||||
..lineTo(size.width / 2, size.height) // Pointe en bas au centre
|
||||
..close();
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant _TrianglePainter oldDelegate) {
|
||||
return oldDelegate.color != color;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user