app.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter/services.dart';
  3. import 'package:get/get.dart';
  4. import 'package:nomo/config/theme/theme_extensions/theme_extension.dart';
  5. import '../config/theme/ix_theme.dart';
  6. import '../config/translations/localization_service.dart';
  7. import '../config/translations/strings_enum.dart';
  8. import '../utils/developer/ix_developer_tools.dart';
  9. import '../utils/device_manager.dart';
  10. import '../utils/ix_back_button_dispatcher.dart';
  11. import '../utils/log/logger.dart';
  12. import 'components/ix_snackbar.dart';
  13. import 'constants/configs.dart';
  14. import 'data/sp/ix_sp.dart';
  15. import 'routes/app_pages.dart';
  16. import 'package:flutter_screenutil/flutter_screenutil.dart';
  17. import 'widgets/click_opacity.dart';
  18. import 'widgets/triple_tap_detector.dart';
  19. class App extends StatelessWidget {
  20. const App({super.key});
  21. @override
  22. Widget build(BuildContext context) {
  23. return ScreenUtilInit(
  24. designSize: const Size(375, 812),
  25. minTextAdapt: true,
  26. splitScreenMode: true,
  27. useInheritedMediaQuery: true,
  28. rebuildFactor: (old, data) => true,
  29. builder: (context, widget) => _buildMaterialApp(),
  30. );
  31. }
  32. Widget _buildMaterialApp() {
  33. bool isLightTheme = IXSP.getThemeIsLight();
  34. log('App', 'isLightTheme: $isLightTheme');
  35. return GetMaterialApp.router(
  36. title: 'ixVPN',
  37. useInheritedMediaQuery: true,
  38. debugShowCheckedModeBanner: Configs.debug,
  39. backButtonDispatcher: IXBackButtonDispatcher(),
  40. getPages: AppPages.routes,
  41. theme: IXTheme.getThemeData(isLight: true),
  42. darkTheme: IXTheme.getThemeData(isLight: false),
  43. themeMode: isLightTheme ? ThemeMode.light : ThemeMode.dark,
  44. fallbackLocale: LocalizationService.defaultLanguage,
  45. locale: IXSP.getCurrentLocal(),
  46. translations: LocalizationService.getInstance(),
  47. builder: (context, widget) => _buildThemedApp(context, widget),
  48. );
  49. }
  50. Widget _buildThemedApp(BuildContext context, Widget? widget) {
  51. return MediaQuery(
  52. data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
  53. child: Stack(
  54. children: [
  55. widget!,
  56. Positioned(
  57. top: 0,
  58. right: 0,
  59. width: 100,
  60. height: 100,
  61. child: TripleTapDetector(
  62. requiredTaps: 10,
  63. onTripleTap: () async {
  64. Clipboard.setData(
  65. ClipboardData(text: await DeviceManager.getDeviceId()),
  66. );
  67. IXSnackBar.showIXSnackBar(
  68. title: Strings.copied.tr,
  69. message: await DeviceManager.getDeviceId(),
  70. );
  71. },
  72. child: const SizedBox.shrink(), // 不显示任何东西
  73. ),
  74. ),
  75. Positioned(
  76. top: 0,
  77. left: 0,
  78. width: 100,
  79. height: 100,
  80. child: TripleTapDetector(
  81. requiredTaps: 10,
  82. onTripleTap: () async {
  83. IXDeveloperTools.show();
  84. },
  85. child: const SizedBox.shrink(), // 不显示任何东西
  86. ),
  87. ),
  88. if (Configs.debug)
  89. Positioned(
  90. bottom: 200,
  91. right: 10,
  92. child: ClickOpacity(
  93. child: Container(
  94. width: 40,
  95. height: 40,
  96. decoration: BoxDecoration(
  97. color: Get.reactiveTheme.primaryColor.withValues(
  98. alpha: 0.5,
  99. ),
  100. borderRadius: BorderRadius.circular(40),
  101. ),
  102. child: Icon(Icons.adb, color: Get.reactiveTheme.primaryColor),
  103. ),
  104. onTap: () {
  105. // 使用简化版开发者工具
  106. IXDeveloperTools.show();
  107. // 切换主题
  108. // IXTheme.changeTheme();
  109. },
  110. ),
  111. ),
  112. ],
  113. ),
  114. );
  115. }
  116. }