Skip to content

Commit e67ae53

Browse files
committed
auto update ios
1 parent 5e43244 commit e67ae53

4 files changed

Lines changed: 83 additions & 3 deletions

File tree

lib/l10n/app_en.arb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,5 +342,15 @@
342342
"restart": "Restart",
343343
"@restart": {
344344
"description": "Snackbar action to restart the app and install the update"
345+
},
346+
347+
"updateAvailable": "A new version is available",
348+
"@updateAvailable": {
349+
"description": "Snackbar message when a newer version is available on the App Store"
350+
},
351+
352+
"update": "Update",
353+
"@update": {
354+
"description": "Snackbar action to open the App Store and update the app"
345355
}
346356
}

lib/l10n/app_fr.arb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,9 @@
139139

140140
"updateReady": "Mise à jour prête à installer",
141141

142-
"restart": "Redémarrer"
142+
"restart": "Redémarrer",
143+
144+
"updateAvailable": "Une nouvelle version est disponible",
145+
146+
"update": "Mettre à jour"
143147
}

lib/l10n/app_pt.arb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,9 @@
139139

140140
"updateReady": "Atualização pronta para instalar",
141141

142-
"restart": "Reiniciar"
142+
"restart": "Reiniciar",
143+
144+
"updateAvailable": "Está disponível uma nova versão",
145+
146+
"update": "Atualizar"
143147
}

lib/pages/main_page.dart

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import 'dart:io';
44
import 'dart:ui' show ImageFilter;
55
import 'package:flutter/foundation.dart' show kIsWeb;
66
import 'package:flutter/material.dart';
7+
import 'package:http/http.dart' as http;
78
import 'package:in_app_update/in_app_update.dart';
9+
import 'package:package_info_plus/package_info_plus.dart';
10+
import 'package:url_launcher/url_launcher.dart';
811
import '../l10n/app_localizations.dart';
912
import '../models/geofence.dart';
1013
import '../services/socket_service.dart';
@@ -250,7 +253,15 @@ class _MainPageState extends State<MainPage> {
250253
}
251254

252255
Future<void> _checkForUpdate() async {
253-
if (kIsWeb || !Platform.isAndroid) return;
256+
if (kIsWeb) return;
257+
if (Platform.isAndroid) {
258+
await _checkForUpdateAndroid();
259+
} else if (Platform.isIOS) {
260+
await _checkForUpdateIos();
261+
}
262+
}
263+
264+
Future<void> _checkForUpdateAndroid() async {
254265
try {
255266
final info = await InAppUpdate.checkForUpdate();
256267
if (!mounted) return;
@@ -280,6 +291,40 @@ class _MainPageState extends State<MainPage> {
280291
}
281292
}
282293

294+
Future<void> _checkForUpdateIos() async {
295+
try {
296+
final packageInfo = await PackageInfo.fromPlatform();
297+
final response = await http
298+
.get(Uri.parse(
299+
'https://itunes.apple.com/lookup?bundleId=com.fleetmap.fleetmanager'))
300+
.timeout(const Duration(seconds: 10));
301+
if (response.statusCode != 200) return;
302+
final data = jsonDecode(response.body) as Map<String, dynamic>;
303+
final results = data['results'] as List?;
304+
if (results == null || results.isEmpty) return;
305+
final storeVersion = results[0]['version'] as String?;
306+
final storeUrl = results[0]['trackViewUrl'] as String?;
307+
if (storeVersion == null || storeUrl == null) return;
308+
if (_isNewerVersion(storeVersion, packageInfo.version)) {
309+
if (mounted) _showIosUpdateSnackbar(storeUrl);
310+
}
311+
} catch (_) {
312+
// Update check is non-critical, ignore errors
313+
}
314+
}
315+
316+
bool _isNewerVersion(String storeVersion, String currentVersion) {
317+
final storeParts = storeVersion.split('.').map(int.tryParse).toList();
318+
final currentParts = currentVersion.split('.').map(int.tryParse).toList();
319+
for (var i = 0; i < storeParts.length; i++) {
320+
final store = storeParts[i] ?? 0;
321+
final current = i < currentParts.length ? (currentParts[i] ?? 0) : 0;
322+
if (store > current) return true;
323+
if (store < current) return false;
324+
}
325+
return false;
326+
}
327+
283328
void _showUpdateReadySnackbar() {
284329
final l10n = AppLocalizations.of(context)!;
285330
ScaffoldMessenger.of(context).showSnackBar(
@@ -294,6 +339,23 @@ class _MainPageState extends State<MainPage> {
294339
);
295340
}
296341

342+
void _showIosUpdateSnackbar(String storeUrl) {
343+
final l10n = AppLocalizations.of(context)!;
344+
ScaffoldMessenger.of(context).showSnackBar(
345+
SnackBar(
346+
content: Text(l10n.updateAvailable),
347+
duration: const Duration(seconds: 15),
348+
action: SnackBarAction(
349+
label: l10n.update,
350+
onPressed: () => launchUrl(
351+
Uri.parse(storeUrl),
352+
mode: LaunchMode.externalApplication,
353+
),
354+
),
355+
),
356+
);
357+
}
358+
297359
Future<void> _connectSocket() async {
298360
_socketService.onStatusChanged = () {
299361
if (mounted) setState(() => _wsConnected = _socketService.isConnected);

0 commit comments

Comments
 (0)