You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
7.6 KiB

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_intro/flutter_intro.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'core/utils/app_lifecycle_manager.dart';
import 'routes/app_pages.dart';
import 'routes/app_routes.dart';
import 'core/translations/app_translations.dart';
import 'core/themes/app_theme.dart';
import 'core/themes/theme_service.dart';
import 'core/bindings/initial_binding.dart';
import 'core/utils/logger.dart';
import 'data/services/login_service.dart';
import 'modules/meeting/controllers/meeting_home_controller.dart';
import 'modules/splash/controllers/splash_controller.dart';
bool _deepLinkHandlerInitialized = false;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化存储
await GetStorage.init();
// 加载环境变量
await dotenv.load(fileName: ".env");
Logger.i("Main", "环境变量加载成功");
// 初始化登录服务
Get.put(LoginService());
// 延迟初始化深链接处理器,确保Flutter完全准备好
WidgetsBinding.instance.addPostFrameCallback((_) {
Future.delayed(const Duration(milliseconds: 1500), () {
_initDeepLinkHandler();
});
});
runApp(MainApp());
}
// 初始化深链接处理器
void _initDeepLinkHandler() {
if (_deepLinkHandlerInitialized) return;
_deepLinkHandlerInitialized = true;
Logger.d("DeepLink", "初始化深链接处理器");
const platform = MethodChannel('com.saitong.voitrans/deeplink');
platform.setMethodCallHandler((call) async {
Logger.d("DeepLink", "Flutter 收到深链接调用: ${call.method}");
if (call.method == 'handleDeepLink') {
final arguments = call.arguments as Map<dynamic, dynamic>;
Logger.d("DeepLink", "深链接参数: $arguments");
final url = arguments['url'] as String?;
if (url != null) {
Logger.d("DeepLink", "处理深链接 URL: $url");
await _handleDeepLinkNavigation(url);
}
return;
}
if (call.method == 'handleSharedFile') {
final arguments = call.arguments as Map<dynamic, dynamic>;
final filePath = arguments['filePath'] as String?;
if (filePath == null || filePath.isEmpty) return;
await _handleSharedAudioFile(filePath);
return;
}
});
Logger.i("DeepLink", "深链接处理器初始化完成");
}
// 处理深链接导航
Future<void> _handleDeepLinkNavigation(String url) async {
Logger.d("DeepLink", "开始处理深链接导航: $url");
try {
final uri = Uri.parse(url);
Logger.d("DeepLink",
"解析URI: scheme=${uri.scheme}, host=${uri.host}, path=${uri.path}");
if (uri.scheme == 'deepvoice' && uri.host == 'qqmusic') {
Logger.i("DeepLink", "检测到QQ音乐登录回调");
// 等待SplashController注册
int retryCount = 0;
const maxRetries = 10;
while (retryCount < maxRetries) {
try {
if (Get.isRegistered<SplashController>()) {
Logger.i("DeepLink", "找到SplashController,处理QQ音乐登录");
final controller = Get.find<SplashController>();
controller.handleQQMusicLogin();
return;
}
} catch (e) {
Logger.e("DeepLink", "获取SplashController失败", e);
}
retryCount++;
Logger.d("DeepLink", "等待SplashController注册 ($retryCount/$maxRetries)");
await Future.delayed(const Duration(milliseconds: 500));
}
Logger.w("DeepLink", "超时等待SplashController注册");
}
} catch (e) {
Logger.e("DeepLink", "处理深链接时出错", e);
}
}
Future<void> _handleSharedAudioFile(String filePath) async {
try {
if (!File(filePath).existsSync()) {
Logger.w("DeepLink", "分享文件不存在: $filePath");
return;
}
int retryCount = 0;
const maxRetries = 10;
while (retryCount < maxRetries) {
try {
if (Get.isRegistered<MeetingHomeController>()) {
final controller = Get.find<MeetingHomeController>();
controller.addAudio(filePath);
return;
}
Get.toNamed(
Routes.meeting,
arguments: {
'filePath': filePath,
},
);
return;
} catch (e) {
retryCount++;
await Future.delayed(const Duration(milliseconds: 300));
}
}
} catch (e) {
Logger.e("DeepLink", "处理分享文件失败", e);
}
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
// 在应用构建时立即初始化深链接处理
_initDeepLinkHandler();
// 获取保存的主题设置
final themeMode = ThemeService().getThemeMode();
return ScreenUtilInit(
designSize: const Size(375, 812),
minTextAdapt: true,
splitScreenMode: true,
builder: (_, child) {
return GetMaterialApp(
title: 'Voitrans',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: themeMode, // 使用提前获取的主题模式
initialBinding: InitialBinding(),
initialRoute: Routes.splash,
getPages: AppPages.pages,
routingCallback: (routing) {
if (!Get.isRegistered<AppLifecycleManager>()) return;
unawaited(
Get.find<AppLifecycleManager>().refreshBleWakeupPolicy(
route: routing?.current,
),
);
},
debugShowCheckedModeBanner: false,
translations: AppTranslations(),
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
locale: AppTranslations.deviceLocale(),
fallbackLocale: AppTranslations.getSmartFallbackLocale(),
supportedLocales: AppTranslations.supportedLocales,
builder: EasyLoading.init(
builder: (BuildContext context, Widget? widget) {
EasyLoading.instance.userInteractions = false;
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.noScaling,
),
child: Intro(
padding: EdgeInsets.zero,
child: widget!,
),
);
},
),
);
});
// // 使用 ScreenUtilInit 包装整个应用
// return ScreenUtilInit(
// designSize: const Size(375, 812), // 设计稿尺寸,根据你的设计稿调整
// minTextAdapt: true,
// splitScreenMode: true,
// builder: (context, child) {
// return GetMaterialApp(
// title: 'VoiTrans',
// theme: AppTheme.lightTheme,
// darkTheme: AppTheme.darkTheme,
// themeMode: ThemeService().getThemeMode(),
// initialRoute: Routes.splash,
// getPages: AppPages.pages,
// initialBinding: InitialBinding(),
// translations: AppTranslations(),
// locale: Get.deviceLocale,
// fallbackLocale: const Locale('en', 'US'),
// debugShowCheckedModeBanner: false,
// );
// },
// );
}
}