- 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
125 lines
3.4 KiB
Dart
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);
|
|
},
|
|
);
|
|
}
|
|
}
|