import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'pages/tabs/tabs.dart'; import 'providers/auth_provider.dart'; import 'router/index.dart'; import 'services/online_time_service.dart'; import 'services/update_dialog_service.dart'; import 'components/WelcomeDialog.dart'; import 'package:flutter/services.dart'; final GlobalKey navigatorKey = GlobalKey(); // 自定义页面转场,禁用Android手势返回 class NoTransitionPageTransitionsBuilder extends PageTransitionsBuilder { const NoTransitionPageTransitionsBuilder(); @override Widget buildTransitions( PageRoute route, BuildContext context, Animation animation, Animation secondaryAnimation, Widget child, ) { return child; } } void main() async { WidgetsFlutterBinding.ensureInitialized(); // 在APP启动时完全重置版本检查状态 UpdateDialogService().resetAllCheckStatus(); try { final packageInfo = await PackageInfo.fromPlatform(); print('应用启动版本: ${packageInfo.version}'); } catch (e) { print('启动时获取版本信息失败: $e'); } // 获取登录状态 final prefs = await SharedPreferences.getInstance(); final token = prefs.getString('token'); final userId = prefs.getString('userId'); runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => AuthProvider()..setToken(token, userId: userId)), ], child: const MyApp(), ), ); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State createState() => _MyAppState(); } class _MyAppState extends State with WidgetsBindingObserver { final OnlineTimeService _onlineTimeService = OnlineTimeService(); bool _showedWelcomeDialog = false; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); _onlineTimeService.initWebSocket(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); _onlineTimeService.dispose(); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: _onlineTimeService.initWebSocket(); break; case AppLifecycleState.paused: _onlineTimeService.dispose(); break; default: break; } } // 显示欢迎弹窗 void _showWelcomeDialog(BuildContext context) { // 如果已显示过或用户已登录,则不再显示 if (_showedWelcomeDialog) return; _showedWelcomeDialog = true; WidgetsBinding.instance.addPostFrameCallback((_) { showGeneralDialog( context: context, barrierColor: Colors.black.withOpacity(0.5), barrierDismissible: false, pageBuilder: (_, __, ___) { return WelcomeDialog( onAgree: () { Navigator.of(context).pop(); Navigator.pushReplacementNamed(context, '/login'); }, onBasicMode: () { // 先关闭弹窗 Navigator.of(context).pop(); // 直接使用全局导航器进行页面导航 navigatorKey.currentState?.pushAndRemoveUntil( MaterialPageRoute( builder: (context) => const StartPageOne(), ), (route) => false, ); }, onDisagree: () { // 退出应用 SystemNavigator.pop(); }, ); }, ); }); } @override Widget build(BuildContext context) { return MaterialApp( navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, title: '看那', theme: ThemeData( useMaterial3: false, //Tabbar取消下划线 primaryColor: const Color.fromRGBO(255, 255, 255, 0.3), appBarTheme: AppBarTheme( centerTitle: true, backgroundColor: const Color(0xff0C0C16), titleTextStyle: Typography.dense2014.bodyLarge, ), // 禁用Android手势返回 pageTransitionsTheme: PageTransitionsTheme( builders: { TargetPlatform.android: NoTransitionPageTransitionsBuilder(), TargetPlatform.iOS: NoTransitionPageTransitionsBuilder(), }, ), platform: TargetPlatform.android, // 定义默认的输入装饰主题 inputDecorationTheme: const InputDecorationTheme( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Color.fromRGBO(255, 255, 255, 0.3)), ), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Color.fromRGBO(255, 255, 255, 0.3)), ), labelStyle: TextStyle(color: Color.fromRGBO(255, 255, 255, 0.3)), hintStyle: TextStyle(color: Color.fromRGBO(255, 255, 255, 0.3)), ), // 定义默认的文本选择主题 textSelectionTheme: TextSelectionThemeData( cursorColor: const Color.fromRGBO(255, 255, 255, 0.3), // 光标颜色 selectionColor: const Color.fromRGBO(255, 255, 255, 0.3).withOpacity(0.4), // 选择颜色 selectionHandleColor: const Color.fromRGBO(255, 255, 255, 0.3), // 选择句柄颜色 ), ), home: Builder( builder: (context) { // 只有在未登录时才显示欢迎弹窗 if (!Provider.of(context).isLoggedIn) { _showWelcomeDialog(context); } return Provider.of(context).isLoggedIn ? const Tabs(initialIndex: 0) : const SplashScreen(); }, ), // Initialize your routes and handle routing // initialRoute: "/", 没有home的时候直接进入tabs onGenerateRoute: onGenerateRoute, ); } } // SplashScreen Widget - 修改后不会自动跳转 class SplashScreen extends StatelessWidget { const SplashScreen({super.key}); @override Widget build(BuildContext context) { // 移除自动跳转逻辑 return GestureDetector( // 添加点击事件,允许用户通过点击跳转到下一页 onTap: () { Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const StartPageOne()), ); }, child: Container( width: double.infinity, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('images/start.png'), fit: BoxFit.fill, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 100), ClipRRect( borderRadius: BorderRadius.circular(5), child: const Image( image: AssetImage('images/logo.png'), width: 36, height: 36, fit: BoxFit.fill, ), ), const SizedBox(height: 20), const Text( '看那,探索MR元宇宙', style: TextStyle( fontSize: 16, color: Colors.white, decoration: TextDecoration.none), ), ], ), ), ); } } // StartPageOne Widget class StartPageOne extends StatefulWidget { const StartPageOne({super.key}); @override _StartPageOneState createState() => _StartPageOneState(); } class _StartPageOneState extends State { int _currentIndex = 0; late PageController _pageController; @override void initState() { super.initState(); _pageController = PageController(); } @override void dispose() { _pageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xff0C0C16), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ClipRRect( borderRadius: BorderRadius.circular(5), // 设置圆角半径 child: const Image( image: AssetImage('images/logo.png'), width: 18, height: 18, fit: BoxFit.fill, ), ), const SizedBox(width: 10), const Text( '看那', style: TextStyle(fontSize: 18, color: Colors.white), ), ], ), const SizedBox( height: 30, ), SizedBox( height: MediaQuery.of(context).size.height * 0.5, child: PageView( controller: _pageController, scrollDirection: Axis.horizontal, onPageChanged: (index) { setState(() { _currentIndex = index; }); }, children: [ Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: double.infinity, height: MediaQuery.of(context).size.height * 0.25, margin: const EdgeInsets.only(bottom: 10), decoration: const BoxDecoration( image: DecorationImage( image: AssetImage( 'images/loading1.png'), // Replace with your start.png path fit: BoxFit.fill, ), ), ), const Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '奇幻MR之旅', style: TextStyle( fontSize: 32, color: Colors.white, fontWeight: FontWeight.bold), ), Image( image: AssetImage('images/trip_new.png'), width: 18, height: 18, fit: BoxFit.fill, ), ], ), const SizedBox(height: 10), const Text( '享受到一种全新、沉浸式的MR旅游体验', style: TextStyle(fontSize: 12, color: Color(0xff4E515A)), ), const SizedBox(height: 10), const Image( image: AssetImage('images/decration.png'), width: 60, height: 20, fit: BoxFit.fill, ), ], ), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: double.infinity, height: MediaQuery.of(context).size.height * 0.25, margin: const EdgeInsets.only(bottom: 10), decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('images/loading2.png'), fit: BoxFit.fill, ), ), ), const Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '探秘MR艺术展', style: TextStyle( fontSize: 32, color: Colors.white, fontWeight: FontWeight.bold), ), Image( image: AssetImage('images/trip_new.png'), width: 20, height: 20, fit: BoxFit.fill, ), ], ), const SizedBox(height: 10), const Text( '领略一场震撼、交互式的MR视觉盛宴', style: TextStyle(fontSize: 12, color: Color(0xff4E515A)), ), const SizedBox(height: 10), const Image( image: AssetImage('images/decration.png'), width: 60, height: 20, fit: BoxFit.fill, ), ], ), ], ), ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(2, (index) { return Container( margin: const EdgeInsets.symmetric(horizontal: 4), width: 12, height: 12, decoration: BoxDecoration( shape: BoxShape.circle, color: _currentIndex == index ? Colors.white : Colors.grey, ), ); }), ), const SizedBox(height: 32), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), gradient: const LinearGradient(colors: [ Color(0xff80DAA4), Color(0xff79DDED), ]), ), child: ElevatedButton( onPressed: () { if (_currentIndex == 0) { setState(() { _currentIndex = 1; }); _pageController.animateToPage( _currentIndex, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, ); } else { // 跳转主页 Navigator.pushReplacementNamed(context, '/tabs'); } }, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, elevation: 0, // 阴影 shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(8))), minimumSize: const Size(double.infinity, 50), padding: const EdgeInsets.symmetric(horizontal: 20), ), child: Text( _currentIndex == 0 ? '继续' : '开始进入', style: const TextStyle(fontSize: 16, color: Colors.black), ), ), ), const SizedBox(height: 20), ElevatedButton( onPressed: () async { final authProvider = Provider.of(context, listen: false); // 使用公开方法名 await authProvider.loadTokenFromPrefs(); if (authProvider.isLoggedIn) { // 已登录,直接进入主页并切换到我的页面 if (!mounted) return; Navigator.pushReplacementNamed(context, '/tabs', arguments: {'initialIndex': 4}); } else { // 未登录,跳转到登录页 if (!mounted) return; Navigator.pushNamed(context, '/login'); } }, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(8)), ), minimumSize: const Size(double.infinity, 50), padding: const EdgeInsets.symmetric(horizontal: 20), side: const BorderSide( style: BorderStyle.solid, width: 1, // 边框宽度 color: Color(0xff73cfcf), // 默认边框颜色 )), child: const Text( '登录', style: TextStyle( color: Color(0xff73cfcf), fontSize: 16, ), ), ), ], ), ), ], ), ); } }