import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/services.dart'; import 'package:flutter/material.dart'; import 'services/mattermost_auth_service.dart'; import 'services/push_notification_background.dart'; import 'services/push_notification_service.dart'; import 'services/workspace_launcher.dart'; import 'screens/workspace_home_page.dart'; final _navigatorKey = GlobalKey(); final _pushService = PushNotificationService(); final _launcher = WorkspaceLauncher(); Future _applyFullscreenMode() async { await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.transparent, systemNavigationBarDividerColor: Colors.transparent, )); } void main() async { WidgetsFlutterBinding.ensureInitialized(); await _applyFullscreenMode(); await Firebase.initializeApp(); FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); _pushService.init(); // Mattermost 자동 로그인 + FCM 토큰 서버 등록 final authService = MattermostAuthService(_pushService); try { await authService.autoLoginAndRegister(); } catch (e) { print('[Main] Mattermost auto-login failed: $e'); } runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'nomadcode-app', navigatorKey: _navigatorKey, theme: ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: Colors.deepPurple, brightness: Brightness.dark, ), useMaterial3: true, ), home: const MyHomePage(title: 'nomadcode-app'), builder: (context, child) { _pushService.onNavigateToChannel = (serverUrl, channelId) { print('[Nav] Navigate to channel: $channelId on $serverUrl'); }; _pushService.onNavigateToThread = (serverUrl, rootId) { print('[Nav] Navigate to thread: $rootId on $serverUrl'); }; return child!; }, ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { StreamSubscription? _notifSub; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { _applyFullscreenMode(); }); _notifSub = _pushService.onNotification.listen((data) { if (data['type'] != 'message') return; final message = data['message'] as String? ?? ''; final channel = data['channel_name'] as String? ?? ''; final sender = data['sender_name'] as String? ?? ''; if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( sender.isNotEmpty ? '[$channel] $sender: $message' : message, maxLines: 2, overflow: TextOverflow.ellipsis, ), duration: const Duration(seconds: 4), behavior: SnackBarBehavior.floating, ), ); }); } @override void dispose() { _notifSub?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return WorkspaceHomePage( onLaunchCodeServer: (project) async { return _launcher.openCodeServer(project); }, ); } }