feat: improve map initialization process and communication
This commit is contained in:
@@ -14848,8 +14848,8 @@
|
||||
el.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
showTrainDetails(lat, lng, recordData);
|
||||
if (window.flutter_inappwebview) {
|
||||
window.flutter_inappwebview.callHandler("showTrainDetails", {
|
||||
if (window.showTrainDetails) {
|
||||
window.showTrainDetails.postMessage(JSON.stringify({
|
||||
id: recordData.id || Date.now(),
|
||||
trainNumber: trainNumber || "未知车次",
|
||||
trainType: recordData.trainType || "未知类型",
|
||||
@@ -14858,7 +14858,7 @@
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}));
|
||||
}
|
||||
});
|
||||
const marker = new maplibregl.Marker({
|
||||
@@ -14931,11 +14931,21 @@
|
||||
.addTo(map);
|
||||
}
|
||||
function setCenter(lat, lng, zoom, bearing) {
|
||||
map.jumpTo({
|
||||
if (!window.map) {
|
||||
console.error("[JS] Map object not ready in setCenter");
|
||||
return;
|
||||
}
|
||||
|
||||
window.map.jumpTo({
|
||||
center: [lng, lat],
|
||||
zoom: zoom !== undefined ? zoom : map.getZoom(),
|
||||
bearing: bearing !== undefined ? bearing : map.getBearing(),
|
||||
zoom: zoom !== undefined ? zoom : window.map.getZoom(),
|
||||
bearing: bearing !== undefined ? bearing : window.map.getBearing(),
|
||||
});
|
||||
|
||||
const mapContainer = window.map.getContainer();
|
||||
if (mapContainer.style.opacity === "0") {
|
||||
mapContainer.style.opacity = "1";
|
||||
}
|
||||
}
|
||||
function getMapState() {
|
||||
const center = map.getCenter();
|
||||
@@ -14948,17 +14958,19 @@
|
||||
}
|
||||
function setupMapEventListeners() {
|
||||
if (!map) return;
|
||||
map.on("moveend", function () {
|
||||
map.on("move", function () {
|
||||
const center = map.getCenter();
|
||||
const zoom = map.getZoom();
|
||||
const bearing = map.getBearing();
|
||||
if (window.flutter_inappwebview) {
|
||||
window.flutter_inappwebview.callHandler("onMapStateChanged", {
|
||||
|
||||
if (window.onMapStateChanged) {
|
||||
const mapState = JSON.stringify({
|
||||
lat: center.lat,
|
||||
lng: center.lng,
|
||||
zoom: zoom,
|
||||
bearing: bearing,
|
||||
});
|
||||
window.onMapStateChanged.postMessage(mapState);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,13 +32,41 @@ class MapWebViewScreenState extends State<MapWebViewScreen>
|
||||
double _currentRotation = 0.0;
|
||||
LatLng? _currentLocation;
|
||||
LatLng? _lastTrainLocation;
|
||||
bool _isDataLoaded = false;
|
||||
final Completer<void> _webViewReadyCompleter = Completer<void>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_initializeWebView();
|
||||
_initializeServices();
|
||||
_startInitialization();
|
||||
}
|
||||
|
||||
Future<void> _startInitialization() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
await _loadSettings();
|
||||
await _loadTrainRecordsFromDatabase();
|
||||
|
||||
await _webViewReadyCompleter.future;
|
||||
|
||||
_initializeMapCamera();
|
||||
|
||||
_initializeLocation();
|
||||
_startAutoRefresh();
|
||||
} catch (e, s) {
|
||||
print('[Flutter] Init Map WebView Screen Failed: $e\n$s');
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -48,16 +76,7 @@ class MapWebViewScreenState extends State<MapWebViewScreen>
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _initializeServices() async {
|
||||
try {
|
||||
await _loadSettings();
|
||||
await _loadTrainRecordsFromDatabase();
|
||||
_initializeLocation();
|
||||
_startAutoRefresh();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void _initializeWebView() {
|
||||
Future<void> _initializeWebView() async {
|
||||
_controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setBackgroundColor(const Color(0xFF121212))
|
||||
@@ -92,9 +111,8 @@ class MapWebViewScreenState extends State<MapWebViewScreen>
|
||||
_isLoading = false;
|
||||
});
|
||||
|
||||
if (mounted) {
|
||||
_initializeMap();
|
||||
_initializeLocation();
|
||||
if (!_webViewReadyCompleter.isCompleted) {
|
||||
_webViewReadyCompleter.complete();
|
||||
}
|
||||
},
|
||||
onWebResourceError: (WebResourceError error) {
|
||||
@@ -107,6 +125,8 @@ class MapWebViewScreenState extends State<MapWebViewScreen>
|
||||
..loadFlutterAsset('assets/mapbox_map.html')
|
||||
.then((_) {})
|
||||
.catchError((error) {});
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
Future<void> _initializeLocation() async {
|
||||
@@ -266,10 +286,6 @@ class MapWebViewScreenState extends State<MapWebViewScreen>
|
||||
} else {}
|
||||
} else {}
|
||||
} else {}
|
||||
|
||||
if (mounted) {
|
||||
_initializeMapPosition();
|
||||
}
|
||||
});
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 3000), () {
|
||||
@@ -351,25 +367,38 @@ class MapWebViewScreenState extends State<MapWebViewScreen>
|
||||
}
|
||||
}
|
||||
|
||||
void _initializeMapPosition() {
|
||||
void _initializeMapCamera() {
|
||||
if (_isMapInitialized) return;
|
||||
|
||||
LatLng? targetLocation;
|
||||
LatLng targetLocation;
|
||||
double targetZoom = _currentZoom;
|
||||
double targetRotation = _currentRotation;
|
||||
|
||||
if (_lastTrainLocation != null) {
|
||||
targetLocation = _lastTrainLocation;
|
||||
} else if (_currentPosition != null) {
|
||||
targetLocation =
|
||||
LatLng(_currentPosition!.latitude, _currentPosition!.longitude);
|
||||
}
|
||||
|
||||
if (targetLocation != null) {
|
||||
_centerMap(targetLocation,
|
||||
zoom: _currentZoom, rotation: _currentRotation);
|
||||
_isMapInitialized = true;
|
||||
if (_currentLocation != null) {
|
||||
targetLocation = _currentLocation!;
|
||||
} else if (_lastTrainLocation != null) {
|
||||
targetLocation = _lastTrainLocation!;
|
||||
targetZoom = 14.0;
|
||||
targetRotation = 0.0;
|
||||
} else {
|
||||
_isMapInitialized = true;
|
||||
targetLocation = const LatLng(39.9042, 116.4074);
|
||||
targetZoom = 10.0;
|
||||
}
|
||||
|
||||
_centerMap(targetLocation, zoom: targetZoom, rotation: targetRotation);
|
||||
_isMapInitialized = true;
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
if (mounted) {
|
||||
_updateUserLocation();
|
||||
_updateTrainMarkers();
|
||||
_controller.runJavaScript('''
|
||||
if (window.MapInterface) {
|
||||
window.MapInterface.setRailwayVisible($_isRailwayLayerVisible);
|
||||
}
|
||||
''');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _centerMap(LatLng location, {double? zoom, double? rotation}) {
|
||||
@@ -430,91 +459,6 @@ class MapWebViewScreenState extends State<MapWebViewScreen>
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
Future<void> _initializeMap() async {
|
||||
try {
|
||||
LatLng? targetLocation;
|
||||
double targetZoom = 14.0;
|
||||
double targetRotation = _currentRotation;
|
||||
|
||||
if (_lastTrainLocation != null) {
|
||||
targetLocation = _lastTrainLocation;
|
||||
targetZoom = 14.0;
|
||||
targetRotation = 0.0;
|
||||
} else if (_currentPosition != null) {
|
||||
targetLocation =
|
||||
LatLng(_currentPosition!.latitude, _currentPosition!.longitude);
|
||||
targetZoom = 16.0;
|
||||
targetRotation = 0.0;
|
||||
}
|
||||
|
||||
if (targetLocation != null) {
|
||||
_centerMap(targetLocation, zoom: targetZoom, rotation: targetRotation);
|
||||
|
||||
try {
|
||||
await _controller.runJavaScript('''
|
||||
(function() {
|
||||
if (window.map && window.map.getContainer) {
|
||||
window.map.getContainer().style.opacity = '1';
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
''');
|
||||
} catch (e) {
|
||||
print('显示地图失败: $e');
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
_controller.runJavaScript('''
|
||||
(function() {
|
||||
if (window.map && window.map.getContainer) {
|
||||
window.map.getContainer().style.opacity = '1';
|
||||
console.log('延迟显示地图成功');
|
||||
}
|
||||
})();
|
||||
''');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isMapInitialized = true;
|
||||
});
|
||||
} catch (e, stackTrace) {}
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 1000), () {
|
||||
if (mounted && _isMapInitialized) {
|
||||
_updateTrainMarkers();
|
||||
|
||||
_controller.runJavaScript('''
|
||||
(function() {
|
||||
if (window.MapInterface) {
|
||||
try {
|
||||
window.MapInterface.setRailwayVisible($_isRailwayLayerVisible);
|
||||
console.log('初始化铁路图层状态: $_isRailwayLayerVisible');
|
||||
} catch (error) {
|
||||
console.error('初始化铁路图层失败:', error);
|
||||
}
|
||||
}
|
||||
})();
|
||||
''');
|
||||
}
|
||||
});
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 3000), () {
|
||||
if (mounted && _isMapInitialized) {
|
||||
_updateTrainMarkers();
|
||||
}
|
||||
});
|
||||
|
||||
Future.delayed(const Duration(seconds: 5), () {
|
||||
if (mounted && _isLoading) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
LatLng? _parseDmsCoordinate(String? positionInfo) {
|
||||
if (positionInfo == null ||
|
||||
positionInfo.isEmpty ||
|
||||
@@ -943,10 +887,10 @@ class MapWebViewScreenState extends State<MapWebViewScreen>
|
||||
|
||||
void _onMapStateChanged(Map<String, dynamic> mapState) {
|
||||
try {
|
||||
final lat = mapState['lat'] as double;
|
||||
final lng = mapState['lng'] as double;
|
||||
final zoom = mapState['zoom'] as double;
|
||||
final bearing = mapState['bearing'] as double;
|
||||
final lat = (mapState['lat'] as num).toDouble();
|
||||
final lng = (mapState['lng'] as num).toDouble();
|
||||
final zoom = (mapState['zoom'] as num).toDouble();
|
||||
final bearing = (mapState['bearing'] as num).toDouble();
|
||||
|
||||
setState(() {
|
||||
_currentLocation = LatLng(lat, lng);
|
||||
|
||||
@@ -13,7 +13,7 @@ class DatabaseService {
|
||||
DatabaseService._internal();
|
||||
|
||||
static const String _databaseName = 'train_database';
|
||||
static const _databaseVersion = 6;
|
||||
static const _databaseVersion = 7;
|
||||
|
||||
static const String trainRecordsTable = 'train_records';
|
||||
static const String appSettingsTable = 'app_settings';
|
||||
@@ -87,6 +87,10 @@ class DatabaseService {
|
||||
await db.execute(
|
||||
'ALTER TABLE $appSettingsTable ADD COLUMN hideUngroupableRecords INTEGER NOT NULL DEFAULT 0');
|
||||
}
|
||||
if (oldVersion < 7) {
|
||||
await db.execute(
|
||||
'ALTER TABLE $appSettingsTable ADD COLUMN mapSettingsTimestamp INTEGER');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onCreate(Database db, int version) async {
|
||||
@@ -136,7 +140,8 @@ class DatabaseService {
|
||||
groupBy TEXT NOT NULL DEFAULT 'trainAndLoco',
|
||||
timeWindow TEXT NOT NULL DEFAULT 'unlimited',
|
||||
mapTimeFilter TEXT NOT NULL DEFAULT 'unlimited',
|
||||
hideUngroupableRecords INTEGER NOT NULL DEFAULT 0
|
||||
hideUngroupableRecords INTEGER NOT NULL DEFAULT 0,
|
||||
mapSettingsTimestamp INTEGER
|
||||
)
|
||||
''');
|
||||
|
||||
@@ -164,6 +169,7 @@ class DatabaseService {
|
||||
'timeWindow': 'unlimited',
|
||||
'mapTimeFilter': 'unlimited',
|
||||
'hideUngroupableRecords': 0,
|
||||
'mapSettingsTimestamp': null,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 0.5.0-flutter+50
|
||||
version: 0.5.1-flutter+51
|
||||
|
||||
environment:
|
||||
sdk: ^3.5.4
|
||||
|
||||
Reference in New Issue
Block a user