diff --git a/lib/models/device.dart b/lib/models/device.dart index ce7a937..d0338ae 100644 --- a/lib/models/device.dart +++ b/lib/models/device.dart @@ -49,6 +49,24 @@ class Device { ); } + Device copyWith({String? status}) { + return Device( + id: id, + name: name, + uniqueId: uniqueId, + status: status ?? this.status, + disabled: disabled, + lastUpdate: lastUpdate, + positionId: positionId, + groupId: groupId, + phone: phone, + model: model, + contact: contact, + category: category, + attributes: attributes, + ); + } + Map toJson() { return { 'id': id, diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 5bd73c7..52435b5 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -65,43 +65,57 @@ class _MainPageState extends State { Map get _visibleDevices { if (_mergeSecondaryIds.isEmpty) return _devices; - return Map.fromEntries( + final result = Map.fromEntries( _devices.entries.where((e) => !_mergeSecondaryIds.contains(e.key)), ); + for (final merge in _deviceMerges) { + if (_useSecondary(merge)) { + final primary = result[merge.primaryDeviceId]; + final secondary = _devices[merge.secondaryDeviceId]; + if (primary != null && secondary != null) { + result[merge.primaryDeviceId] = primary.copyWith(status: secondary.status); + } + } + } + return result; } Map get _effectivePositions { if (_deviceMerges.isEmpty) return _positions; final result = Map.from(_positions); for (final merge in _deviceMerges) { - final primaryPos = _positions[merge.primaryDeviceId]; - final secondaryPos = _positions[merge.secondaryDeviceId]; - if (secondaryPos != null) { - final primaryTime = primaryPos?.fixTime ?? DateTime.fromMillisecondsSinceEpoch(0); - if (secondaryPos.fixTime.isAfter(primaryTime)) { - result[merge.primaryDeviceId] = Position( - id: secondaryPos.id, - deviceId: merge.primaryDeviceId, - fixTime: secondaryPos.fixTime, - serverTime: secondaryPos.serverTime, - valid: secondaryPos.valid, - latitude: secondaryPos.latitude, - longitude: secondaryPos.longitude, - altitude: secondaryPos.altitude, - speed: secondaryPos.speed, - course: secondaryPos.course, - address: secondaryPos.address, - accuracy: secondaryPos.accuracy, - network: secondaryPos.network, - batteryLevel: secondaryPos.batteryLevel, - attributes: secondaryPos.attributes, - ); - } + if (_useSecondary(merge)) { + final secondaryPos = _positions[merge.secondaryDeviceId]!; + result[merge.primaryDeviceId] = Position( + id: secondaryPos.id, + deviceId: merge.primaryDeviceId, + fixTime: secondaryPos.fixTime, + serverTime: secondaryPos.serverTime, + valid: secondaryPos.valid, + latitude: secondaryPos.latitude, + longitude: secondaryPos.longitude, + altitude: secondaryPos.altitude, + speed: secondaryPos.speed, + course: secondaryPos.course, + address: secondaryPos.address, + accuracy: secondaryPos.accuracy, + network: secondaryPos.network, + batteryLevel: secondaryPos.batteryLevel, + attributes: secondaryPos.attributes, + ); } } return result; } + bool _useSecondary(DeviceMerge merge) { + final secondaryPos = _positions[merge.secondaryDeviceId]; + if (secondaryPos == null) return false; + final primaryPos = _positions[merge.primaryDeviceId]; + final primaryTime = primaryPos?.fixTime ?? DateTime.fromMillisecondsSinceEpoch(0); + return secondaryPos.fixTime.isAfter(primaryTime); + } + Future _init() async { final devices = await _apiService.fetchDevices(); final devicesMap = {}; @@ -539,7 +553,7 @@ class _MainPageState extends State { // Device Bottom Sheet _BottomSheetBuilder( selectedDeviceId: _selectedDeviceId, - devices: _devices, + devices: _visibleDevices, positions: _effectivePositions, deviceMerges: _deviceMerges, onClose: _closeBottomSheet, @@ -681,6 +695,7 @@ class _BottomSheetBuilder extends StatefulWidget { class _BottomSheetBuilderState extends State<_BottomSheetBuilder> { int? _lastDeviceId; int? _lastPositionId; + String? _lastDeviceStatus; bool? _lastShowingRoute; int? _lastHighlightedSegmentFirstId; Widget? _cachedSheet; @@ -700,13 +715,15 @@ class _BottomSheetBuilderState extends State<_BottomSheetBuilder> { // Check if device, position, or route view changed final deviceChanged = selectedDeviceId != _lastDeviceId; final positionChanged = currentPositionId != _lastPositionId; + final statusChanged = device?.status != _lastDeviceStatus; final routeViewChanged = widget.showingRoute != _lastShowingRoute; final highlightedSegmentChanged = currentHighlightedFirstId != _lastHighlightedSegmentFirstId; // Only rebuild if selected device's data or view actually changed - if (deviceChanged || positionChanged || routeViewChanged || highlightedSegmentChanged || _cachedSheet == null) { + if (deviceChanged || positionChanged || statusChanged || routeViewChanged || highlightedSegmentChanged || _cachedSheet == null) { _lastDeviceId = selectedDeviceId; _lastPositionId = currentPositionId; + _lastDeviceStatus = device?.status; _lastShowingRoute = widget.showingRoute; _lastHighlightedSegmentFirstId = currentHighlightedFirstId; @@ -749,6 +766,7 @@ class _BottomSheetBuilderState extends State<_BottomSheetBuilder> { } else { _lastDeviceId = null; _lastPositionId = null; + _lastDeviceStatus = null; _lastShowingRoute = null; _lastHighlightedSegmentFirstId = null; _cachedSheet = null; diff --git a/lib/widgets/reports_webview.dart b/lib/widgets/reports_webview.dart index 3e12edb..295ddc8 100644 --- a/lib/widgets/reports_webview.dart +++ b/lib/widgets/reports_webview.dart @@ -6,6 +6,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:http/http.dart' as http; +import 'package:package_info_plus/package_info_plus.dart'; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; import '../l10n/app_localizations.dart'; @@ -63,9 +64,10 @@ class _ReportsWebViewState extends State { } final defaultUa = await InAppWebViewController.getDefaultUserAgent(); + final packageInfo = await PackageInfo.fromPlatform(); if (!mounted) return; setState(() { - _userAgent = '$defaultUa com.fleetmap.jsrastreamento'; + _userAgent = '$defaultUa ${packageInfo.packageName}'; _initialUri = WebUri('$traccarBaseUrl/reports'); }); } diff --git a/pubspec.yaml b/pubspec.yaml index 32a2304..3c2428f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: manager description: "Track Fleet" publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 3.17.6+1 +version: 3.18.6+1 environment: sdk: ^3.9.2