nomadcode/apps/mobile/lib/main.dart
toki 663919c8b0 refactor: organize roadmap phases and update mobile app structure
- Reorganize roadmap archives into phase-based directory structure
- Add PHASE.md files for each roadmap phase
- Update mobile app: remove Mattermost-specific push notification code
- Update mobile app: migrate to workspace-based authentication
- Update pubspec.yaml and platform configs for nomadcode app
2026-05-25 13:59:24 +09:00

125 lines
3.4 KiB
Dart

import 'dart:async';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:mattermost_push_plugin/mattermost_push_plugin.dart';
import 'services/mattermost_auth_service.dart';
import 'services/workspace_launcher.dart';
import 'screens/workspace_home_page.dart';
final _navigatorKey = GlobalKey<NavigatorState>();
final _pushService = MattermostPushPlugin.instance;
final _launcher = WorkspaceLauncher();
Future<void> _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();
await _pushService.initialize();
// 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<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
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);
},
);
}
}