272 lines
8.8 KiB
Dart
272 lines
8.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
class InfoScreen extends StatelessWidget {
|
|
const InfoScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: const Color(0xFF0d0d0d),
|
|
appBar: AppBar(
|
|
backgroundColor: const Color(0xFF161616),
|
|
elevation: 0,
|
|
leading: IconButton(
|
|
icon: const Icon(
|
|
Icons.arrow_back,
|
|
color: Color(0xFF9e9e9e),
|
|
size: 20,
|
|
),
|
|
onPressed: () => Navigator.pop(context),
|
|
),
|
|
title: const Text(
|
|
'HOW IT WORKS',
|
|
style: TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w700,
|
|
letterSpacing: 2,
|
|
color: Color(0xFFe0e0e0),
|
|
),
|
|
),
|
|
bottom: PreferredSize(
|
|
preferredSize: const Size.fromHeight(1),
|
|
child: Container(height: 1, color: const Color(0xFF2a2a2a)),
|
|
),
|
|
),
|
|
body: ListView(
|
|
padding: const EdgeInsets.all(20),
|
|
children: [
|
|
_buildSection(
|
|
icon: Icons.gps_fixed,
|
|
title: 'LOCATION UPDATES',
|
|
description:
|
|
'Your device sends location to the server based on Update Interval. Higher intervals use less battery but report less frequently.',
|
|
),
|
|
_buildSection(
|
|
icon: Icons.speed,
|
|
title: 'SPEED CALCULATION',
|
|
description:
|
|
'GPS doesn\'t always provide speed. When native speed is unavailable, we take TWO locations 2.5s apart and calculate speed from the distance/time delta.',
|
|
),
|
|
_buildSection(
|
|
icon: Icons.info_outline,
|
|
title: 'SPEED SOURCES',
|
|
descriptions: [
|
|
'Native - from GPS chip (most accurate)',
|
|
'Calculated - from coordinate pair',
|
|
],
|
|
),
|
|
_buildSection(
|
|
icon: Icons.straighten,
|
|
title: 'DISTANCE FILTER',
|
|
description:
|
|
'Locations closer than this distance are filtered out. Higher values = fewer reports = less battery usage. Lower values = more reports = more battery.',
|
|
),
|
|
_buildSection(
|
|
icon: Icons.cloud_off,
|
|
title: 'OFFLINE BUFFER',
|
|
description:
|
|
'When offline, locations are stored locally and sent when connection returns.',
|
|
),
|
|
const SizedBox(height: 24),
|
|
_buildSectionHeader('SETTINGS GUIDE'),
|
|
const SizedBox(height: 16),
|
|
_buildSettingsItem(
|
|
title: 'Server URL / Device ID',
|
|
subtitle: 'Where & who',
|
|
description:
|
|
'Your Traccar server endpoint and device identifier. Locations are POSTed to: serverUrl/?id=deviceId&lat=...&lon=...',
|
|
),
|
|
_buildSettingsItem(
|
|
title: 'Accuracy',
|
|
subtitle: 'GPS vs Battery',
|
|
description:
|
|
'High = GPS only, best accuracy, more battery\nBalanced = GPS + Network, good balance\nLow = Network only, battery saver, less accurate',
|
|
),
|
|
_buildSettingsItem(
|
|
title: 'Distance Filter',
|
|
subtitle: 'Meters',
|
|
description:
|
|
'Minimum distance between reported locations. If you move less than this, the location is filtered. 50m = only report when moved 50+ meters.',
|
|
),
|
|
_buildSettingsItem(
|
|
title: 'Update Interval',
|
|
subtitle: 'Seconds',
|
|
description:
|
|
'How often the device checks location. 120s = check every 2 minutes. Lower = more frequent = more battery. Combined with Distance Filter.',
|
|
),
|
|
_buildSettingsItem(
|
|
title: 'Heartbeat',
|
|
subtitle: 'Seconds',
|
|
description:
|
|
'Keep-alive interval when stationary. Sends a location update even if not moving. Prevents server from thinking device is offline.',
|
|
),
|
|
_buildSettingsItem(
|
|
title: 'Offline Buffering',
|
|
subtitle: 'On/Off',
|
|
description:
|
|
'When enabled, locations are queued locally when offline and sent in batch when connection returns. Recommended to keep ON.',
|
|
),
|
|
_buildSettingsItem(
|
|
title: 'Stop Detection',
|
|
subtitle: 'On/Off',
|
|
description:
|
|
'Auto-stops tracking when stationary for extended period. Saves battery. Resume by manually starting tracking again.',
|
|
),
|
|
const SizedBox(height: 20),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSection({
|
|
required IconData icon,
|
|
required String title,
|
|
String? description,
|
|
List<String>? descriptions,
|
|
}) {
|
|
return Container(
|
|
margin: const EdgeInsets.only(bottom: 16),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF161616),
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(color: const Color(0xFF2a2a2a), width: 1),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(icon, size: 16, color: const Color(0xFF00bcd4)),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
title,
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontSize: 11,
|
|
fontWeight: FontWeight.w700,
|
|
letterSpacing: 2,
|
|
color: Color(0xFF00bcd4),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 12),
|
|
if (description != null)
|
|
Text(
|
|
description,
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontSize: 12,
|
|
color: Color(0xFF9e9e9e),
|
|
height: 1.5,
|
|
),
|
|
),
|
|
if (descriptions != null)
|
|
...descriptions.map(
|
|
(d) => Padding(
|
|
padding: const EdgeInsets.only(bottom: 4),
|
|
child: Text(
|
|
'• $d',
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontSize: 12,
|
|
color: Color(0xFF9e9e9e),
|
|
height: 1.5,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSectionHeader(String title) {
|
|
return Row(
|
|
children: [
|
|
Container(
|
|
width: 3,
|
|
height: 14,
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF00bcd4),
|
|
borderRadius: BorderRadius.circular(1),
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
title,
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontSize: 11,
|
|
fontWeight: FontWeight.w700,
|
|
letterSpacing: 2,
|
|
color: Color(0xFF00bcd4),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildSettingsItem({
|
|
required String title,
|
|
required String subtitle,
|
|
required String description,
|
|
}) {
|
|
return Container(
|
|
margin: const EdgeInsets.only(bottom: 12),
|
|
padding: const EdgeInsets.all(14),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF161616),
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(color: const Color(0xFF2a2a2a), width: 1),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text(
|
|
title,
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFFe0e0e0),
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF2a2a2a),
|
|
borderRadius: BorderRadius.circular(2),
|
|
),
|
|
child: Text(
|
|
subtitle,
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontSize: 10,
|
|
color: Color(0xFF616161),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
description,
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontSize: 11,
|
|
color: Color(0xFF757575),
|
|
height: 1.5,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|