2026-07-17 15:23:12 +02:00

213 lines
7.7 KiB
Dart

//import 'package:audioplayers/audioplayers.dart';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// TODO // import 'package:flutter_beacon/flutter_beacon.dart';
import 'package:get/get.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart';
import 'package:mymuseum_visitapp/Helpers/requirement_state_controller.dart';
import 'package:mymuseum_visitapp/Models/articleRead.dart';
import 'package:mymuseum_visitapp/Screens/Home/home_3.0.dart';
import 'package:mymuseum_visitapp/Screens/splash_screen.dart';
import 'package:mymuseum_visitapp/Services/Glasses/voice_orchestrator.dart';
import 'package:mymuseum_visitapp/Services/meta_glasses_service.dart';
import 'package:mymuseum_visitapp/Services/voice_controller.dart';
import 'package:mymuseum_visitapp/Services/pushNotificationService.dart';
import 'package:mymuseum_visitapp/l10n/app_localizations.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'Helpers/DatabaseHelper.dart';
import 'Models/visitContext.dart';
import 'app_context.dart';
import 'client.dart';
import 'constants.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const AppBootstrap());
}
class AppBootstrap extends StatefulWidget {
const AppBootstrap({Key? key}) : super(key: key);
@override
_AppBootstrapState createState() => _AppBootstrapState();
}
class _AppBootstrapState extends State<AppBootstrap> {
VisitAppContext? _ctx;
@override
void initState() {
super.initState();
_initApp();
}
Future<void> _initApp() async {
// Firebase init (requires google-services.json on Android, GoogleService-Info.plist on iOS)
if (!Platform.isWindows) {
await Firebase.initializeApp();
}
VisitAppContext? localContext = await DatabaseHelper.instance.getData(DatabaseTableType.main);
Directory? appDocumentsDirectory = Platform.isIOS ? await getApplicationDocumentsDirectory() : await getDownloadsDirectory();
String localPath = appDocumentsDirectory!.path;
MapboxOptions.setAccessToken("pk.eyJ1IjoidGZyYW5zb2xldCIsImEiOiJjbHRpcGNvZDYwYWhkMnFxdmF0ampveW10In0.7xHN0NGvUfQu5ThS3RGJRw"); // TODO put in json file or resource file
if (localContext != null) {
print("we've got an local db !");
print(localContext);
List<SectionRead> articleReadTest = List<SectionRead>.from(await DatabaseHelper.instance.getData(DatabaseTableType.articleRead));
localContext.readSections = articleReadTest;
} else {
localContext = VisitAppContext(language: "FR", id: "UserId_Init", instanceId: kInstanceId, isAdmin: false, isAllLanguages: false);
DatabaseHelper.instance.insert(DatabaseTableType.main, localContext.toMap());
List<SectionRead> articleReadTest = List<SectionRead>.from(await DatabaseHelper.instance.getData(DatabaseTableType.articleRead));
localContext.readSections = articleReadTest;
print(localContext.readSections);
print("NO LOCAL DB !");
}
localContext.clientAPI = Client(kApiBaseUrl, apiKey: localContext.apiKey ?? (kApiKey.isNotEmpty ? kApiKey : null));
// Récupère publicApiKey depuis le backend si pas encore en mémoire
if (localContext.apiKey == null && localContext.instanceId != null) {
try {
final instanceDto = await localContext.clientAPI.instanceApi!
.instanceGetDetail(localContext.instanceId!);
if (instanceDto?.publicApiKey != null) {
localContext.apiKey = instanceDto!.publicApiKey;
localContext.clientAPI = Client(kApiBaseUrl, apiKey: localContext.apiKey);
DatabaseHelper.instance.updateTableMain(DatabaseTableType.main, localContext);
print('publicApiKey loaded and saved');
}
} catch (e) {
print('Could not load publicApiKey: $e');
}
}
// Push notifications — subscribe to instance topic if enabled
if (!Platform.isWindows && localContext.instanceId != null) {
try {
await PushNotificationService.initialize(localContext.instanceId!);
} catch (e) {
print('PushNotification init failed: $e');
}
}
localContext.localPath = localPath;
print("Local path $localPath");
// Glasses SDK init — toujours initialisé pour détecter la connexion BT.
// L'orchestrateur vocal ne démarre PAS automatiquement — c'est VoiceController qui gère ça.
if (!Platform.isWindows && (Platform.isAndroid || Platform.isIOS)) {
await MetaGlassesService.instance.initialize();
}
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
systemNavigationBarColor: Colors.transparent,
statusBarColor: Colors.transparent,
));
if (mounted) setState(() => _ctx = localContext);
}
@override
Widget build(BuildContext context) {
if (_ctx == null) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: SplashScreen(),
);
}
return MyApp(visitAppContext: _ctx!, initialRoute: '/home');
}
}
class MyApp extends StatefulWidget {
String initialRoute = "";
VisitAppContext visitAppContext;
MyApp({Key? key, required this.initialRoute, required this.visitAppContext}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
// Le mode vocal ne démarre plus automatiquement — l'utilisateur choisit via VoiceModeSheet.
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
final o = activeVoiceOrchestrator;
if (o != null && o.isRunning && !o.isInConversation) {
o.restartWakeWord();
}
}
}
@override
Widget build(BuildContext context) {
Get.put(RequirementStateController());
return MultiProvider(
providers: [
ChangeNotifierProvider<AppContext>(
create: (_) => AppContext(widget.visitAppContext),
),
ChangeNotifierProvider<VoiceController>(
create: (_) => VoiceController(),
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Carnaval de Marche', //'Musée de la fraise' // Autres // 'Fort Saint Héribert'
initialRoute: widget.initialRoute,
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const[
Locale('en', ''),
Locale('fr', ''),
],
theme: ThemeData(
primarySwatch: Colors.blue,
scaffoldBackgroundColor: kBackgroundColor,
//fontFamily: "Vollkorn",
textTheme: TextTheme(bodyLarge: TextStyle(color: widget.visitAppContext.configuration != null ? widget.visitAppContext.configuration!.primaryColor != null ? Color(int.parse(widget.visitAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)): kMainColor1 : kMainColor1)),
visualDensity: VisualDensity.adaptivePlatformDensity,
appBarTheme: const AppBarTheme(
iconTheme: IconThemeData(color: Colors.white), // Change the color here
),
),
routes: {
'/home': (context) => const HomePage3(),
}
),
);
}
}