102 lines
3.7 KiB
Dart
102 lines
3.7 KiB
Dart
import 'dart:developer';
|
|
|
|
import 'package:flutter/services.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
import 'package:terepi_seged/models/project.dart';
|
|
import 'package:terepi_seged/services/app_database.dart';
|
|
import 'package:terepi_seged/services/app_logger.dart';
|
|
|
|
/// Induláskor eldönti, hogy a navigációs képernyőt is meg kell-e nyitni.
|
|
///
|
|
/// Mind a négy feltételnek teljesülnie kell:
|
|
/// 1. A felhasználó be van jelentkezve (a munkamenet a készüléken tárolt,
|
|
/// ez offline is eldönthető).
|
|
/// 2. Az utoljára aktív projekt FELHŐS (nem csak helyi), aktív, és már
|
|
/// szinkronizált (sync_status == 'synced').
|
|
/// 3. A szerver elérhető — ezt maga a lekérdezés bizonyítja (offline hibára
|
|
/// fut).
|
|
/// 4. A `terepi_seged_app_config` táblában megtalálható a
|
|
/// `nav_autostart:<ANDROID_ID>` kulcs. Az érték tetszőleges (pl. 'igen'),
|
|
/// csak a kulcs megléte számít. A járművet (V1, V2…) NEM állítja be, az
|
|
/// marad a helyi érték.
|
|
///
|
|
/// OFFLINE-FIRST: bármilyen hiba, időtúllépés vagy hiányzó adat esetén a
|
|
/// válasz `false`, az app a megszokott módon indul. Sosem dob kivételt.
|
|
class NavAutoStartService {
|
|
NavAutoStartService._();
|
|
|
|
static const keyPrefix = 'nav_autostart:';
|
|
static const _channel = MethodChannel('hu.app_dev.terepi_seged/deviceInfo');
|
|
|
|
static bool _no(String reason) {
|
|
// ignore: avoid_print
|
|
print('🚀 NavAutoStart: NEM — $reason');
|
|
return false;
|
|
}
|
|
|
|
static Future<bool> shouldStartNavigation() async {
|
|
try {
|
|
final androidId = await _androidId();
|
|
if (androidId == null || androidId.isEmpty) {
|
|
return _no('nincs ANDROID_ID');
|
|
}
|
|
// ignore: avoid_print
|
|
print('🚀 NavAutoStart: androidId=$androidId');
|
|
|
|
if (Supabase.instance.client.auth.currentUser == null) {
|
|
return _no('nincs bejelentkezett felhasználó');
|
|
}
|
|
|
|
if (!await _activeProjectIsOnline()) return false;
|
|
|
|
final row = await Supabase.instance.client
|
|
.from('terepi_seged_app_config')
|
|
.select('key')
|
|
.eq('key', '$keyPrefix$androidId')
|
|
.maybeSingle()
|
|
.timeout(const Duration(seconds: 3));
|
|
if (row == null) {
|
|
return _no('nincs sor a kulccsal: $keyPrefix$androidId');
|
|
}
|
|
|
|
AppLogger.event('nav_autostart');
|
|
// ignore: avoid_print
|
|
print('🚀 NavAutoStart: IGEN');
|
|
return true;
|
|
} catch (e) {
|
|
return _no('hiba / időtúllépés: $e');
|
|
}
|
|
}
|
|
|
|
/// Az utoljára aktív projektet a ProjectService is a SharedPreferences-ből
|
|
/// állítja vissza, ezért itt közvetlenül azt vizsgáljuk — így nem függ a
|
|
/// ProjectService aszinkron indulásának időzítésétől.
|
|
static Future<bool> _activeProjectIsOnline() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final id = prefs.getInt('active_project_id');
|
|
if (id == null) return _no('nincs mentett aktív projekt');
|
|
|
|
final project = await AppDatabase.instance.getProject(id);
|
|
if (project == null) return _no('a projekt nincs a helyi adatbázisban');
|
|
if (project.isLocalOnly) return _no('az aktív projekt csak helyi');
|
|
if (project.status != ProjectStatus.active) {
|
|
return _no('a projekt nem aktív (${project.status})');
|
|
}
|
|
|
|
final sync = await AppDatabase.instance.getProjectSyncStatus(id);
|
|
if (sync != 'synced') return _no('sync_status=$sync (nem synced)');
|
|
return true;
|
|
}
|
|
|
|
/// Settings.Secure.ANDROID_ID — ugyanaz a csatorna, mint amit a
|
|
/// DeviceIdentityService használ.
|
|
static Future<String?> _androidId() async {
|
|
try {
|
|
return await _channel.invokeMethod<String>('getAndroidId');
|
|
} catch (_) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|