tracpulse/lib/info_screen.dart

272 lines
No EOL
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,
),
),
],
),
);
}
}