app.dart 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. ),
  109. ),
  110. Positioned(
  111. bottom: 300,
  112. right: 10,
  113. child: ClickOpacity(
  114. child: Container(
  115. width: 40,
  116. height: 40,
  117. decoration: BoxDecoration(
  118. color: Get.reactiveTheme.primaryColor.withValues(alpha: 0.5),
  119. borderRadius: BorderRadius.circular(40),
  120. ),
  121. child: Icon(
  122. ReactiveTheme.isLightTheme ? Icons.sunny : Icons.nightlight,
  123. color: Get.reactiveTheme.primaryColor,
  124. ),
  125. ),
  126. onTap: () {
  127. // 切换主题
  128. IXTheme.changeTheme();
  129. },
  130. ),
  131. ),
  132. ],
  133. ),
  134. );
  135. }
  136. }