feat: app Flutter GameManager (OIDC pocket-id, contrôle serveurs, MOTD live, auto-update) + CI APK signée

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
neckfire
2026-07-13 09:13:55 +02:00
co-authored by Claude Opus 4.8
parent 2c5476b1db
commit 3286640b37
14 changed files with 969 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:ota_update/ota_update.dart';
import 'package:package_info_plus/package_info_plus.dart';
/// Vérifie s'il existe une version plus récente (API `/version`) et, si oui,
/// télécharge + installe l'APK (hors Play Store).
class UpdateService {
UpdateService(this._baseUrl);
final Future<String> _baseUrl;
Future<UpdateInfo?> check() async {
try {
final base = await _baseUrl;
final res = await http.get(Uri.parse('$base/version')).timeout(const Duration(seconds: 6));
if (res.statusCode != 200) return null;
final data = jsonDecode(res.body) as Map<String, dynamic>;
final remote = data['version_code'] as int? ?? 0;
final info = await PackageInfo.fromPlatform();
final current = int.tryParse(info.buildNumber) ?? 0;
if (remote > current) {
return UpdateInfo(
version: data['version'] as String? ?? '?',
apkUrl: data['apk_url'] as String? ?? '$base/download/apk',
notes: data['notes'] as String? ?? '',
);
}
} catch (_) {/* pas de réseau / pas d'update → on ignore */}
return null;
}
/// Lance le téléchargement + l'installation ; renvoie le flux de progression.
Stream<OtaEvent> apply(UpdateInfo info) =>
OtaUpdate().execute(info.apkUrl, destinationFilename: 'gamemanager.apk');
}
class UpdateInfo {
UpdateInfo({required this.version, required this.apkUrl, required this.notes});
final String version;
final String apkUrl;
final String notes;
}