mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-20 03:06:59 +08:00
376 lines
12 KiB
Dart
376 lines
12 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:PiliPlus/build_config.dart';
|
|
import 'package:PiliPlus/common/constants.dart';
|
|
import 'package:PiliPlus/common/widgets/custom_toast.dart';
|
|
import 'package:PiliPlus/common/widgets/mouse_back.dart';
|
|
import 'package:PiliPlus/http/init.dart';
|
|
import 'package:PiliPlus/models/common/theme/theme_color_type.dart';
|
|
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
|
import 'package:PiliPlus/router/app_pages.dart';
|
|
import 'package:PiliPlus/services/account_service.dart';
|
|
import 'package:PiliPlus/services/download/download_service.dart';
|
|
import 'package:PiliPlus/services/logger.dart';
|
|
import 'package:PiliPlus/services/service_locator.dart';
|
|
import 'package:PiliPlus/utils/app_scheme.dart';
|
|
import 'package:PiliPlus/utils/cache_manager.dart';
|
|
import 'package:PiliPlus/utils/calc_window_position.dart';
|
|
import 'package:PiliPlus/utils/date_utils.dart';
|
|
import 'package:PiliPlus/utils/page_utils.dart';
|
|
import 'package:PiliPlus/utils/path_utils.dart';
|
|
import 'package:PiliPlus/utils/request_utils.dart';
|
|
import 'package:PiliPlus/utils/storage.dart';
|
|
import 'package:PiliPlus/utils/storage_key.dart';
|
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
|
import 'package:PiliPlus/utils/theme_utils.dart';
|
|
import 'package:PiliPlus/utils/utils.dart';
|
|
import 'package:catcher_2/catcher_2.dart';
|
|
import 'package:dynamic_color/dynamic_color.dart';
|
|
import 'package:flex_seed_scheme/flex_seed_scheme.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/gestures.dart' show PointerDeviceKind;
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:media_kit/media_kit.dart';
|
|
import 'package:path/path.dart' as path;
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'package:window_manager/window_manager.dart' hide calcWindowPosition;
|
|
|
|
WebViewEnvironment? webViewEnvironment;
|
|
|
|
void main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
MediaKit.ensureInitialized();
|
|
tmpDirPath = (await getTemporaryDirectory()).path;
|
|
appSupportDirPath = (await getApplicationSupportDirectory()).path;
|
|
try {
|
|
await GStorage.init();
|
|
} catch (e) {
|
|
await Utils.copyText(e.toString());
|
|
if (kDebugMode) debugPrint('GStorage init error: $e');
|
|
exit(0);
|
|
}
|
|
if (Utils.isDesktop) {
|
|
final customDownPath = Pref.downloadPath;
|
|
if (customDownPath != null && customDownPath.isNotEmpty) {
|
|
try {
|
|
final dir = Directory(customDownPath);
|
|
if (!dir.existsSync()) {
|
|
await dir.create(recursive: true);
|
|
}
|
|
downloadPath = customDownPath;
|
|
} catch (e) {
|
|
downloadPath = defDownloadPath;
|
|
await GStorage.setting.delete(SettingBoxKey.downloadPath);
|
|
if (kDebugMode) {
|
|
debugPrint('download path error: $e');
|
|
}
|
|
}
|
|
} else {
|
|
downloadPath = defDownloadPath;
|
|
}
|
|
} else if (Platform.isAndroid) {
|
|
final externalStorageDirPath = (await getExternalStorageDirectory())?.path;
|
|
downloadPath = externalStorageDirPath != null
|
|
? path.join(externalStorageDirPath, PathUtils.downloadDir)
|
|
: defDownloadPath;
|
|
} else {
|
|
downloadPath = defDownloadPath;
|
|
}
|
|
Get
|
|
..lazyPut(AccountService.new)
|
|
..lazyPut(DownloadService.new);
|
|
HttpOverrides.global = _CustomHttpOverrides();
|
|
|
|
CacheManager.autoClearCache();
|
|
|
|
if (Utils.isMobile) {
|
|
await Future.wait([
|
|
SystemChrome.setPreferredOrientations(
|
|
[
|
|
DeviceOrientation.portraitUp,
|
|
if (Pref.horizontalScreen) ...[
|
|
DeviceOrientation.landscapeLeft,
|
|
DeviceOrientation.landscapeRight,
|
|
],
|
|
],
|
|
),
|
|
setupServiceLocator(),
|
|
]);
|
|
}
|
|
|
|
if (Platform.isWindows) {
|
|
if (await WebViewEnvironment.getAvailableVersion() != null) {
|
|
webViewEnvironment = await WebViewEnvironment.create(
|
|
settings: WebViewEnvironmentSettings(
|
|
userDataFolder: path.join(appSupportDirPath, 'flutter_inappwebview'),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Request();
|
|
Request.setCookie();
|
|
RequestUtils.syncHistoryStatus();
|
|
|
|
SmartDialog.config.toast = SmartConfigToast(
|
|
displayType: SmartToastType.onlyRefresh,
|
|
);
|
|
|
|
if (Utils.isMobile) {
|
|
PiliScheme.init();
|
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
|
SystemChrome.setSystemUIOverlayStyle(
|
|
const SystemUiOverlayStyle(
|
|
systemNavigationBarColor: Colors.transparent,
|
|
systemNavigationBarDividerColor: Colors.transparent,
|
|
statusBarColor: Colors.transparent,
|
|
systemNavigationBarContrastEnforced: false,
|
|
),
|
|
);
|
|
if (Platform.isAndroid) {
|
|
late List<DisplayMode> modes;
|
|
FlutterDisplayMode.supported.then((value) {
|
|
modes = value;
|
|
final String? storageDisplay = GStorage.setting.get(
|
|
SettingBoxKey.displayMode,
|
|
);
|
|
DisplayMode? displayMode;
|
|
if (storageDisplay != null) {
|
|
displayMode = modes.firstWhereOrNull(
|
|
(e) => e.toString() == storageDisplay,
|
|
);
|
|
}
|
|
FlutterDisplayMode.setPreferredMode(displayMode ?? DisplayMode.auto);
|
|
});
|
|
}
|
|
} else if (Utils.isDesktop) {
|
|
await windowManager.ensureInitialized();
|
|
|
|
WindowOptions windowOptions = WindowOptions(
|
|
minimumSize: const Size(400, 720),
|
|
skipTaskbar: false,
|
|
titleBarStyle: Pref.showWindowTitleBar
|
|
? TitleBarStyle.normal
|
|
: TitleBarStyle.hidden,
|
|
title: Constants.appName,
|
|
);
|
|
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
|
final windowSize = Pref.windowSize;
|
|
await windowManager.setBounds(
|
|
await calcWindowPosition(windowSize) & windowSize,
|
|
);
|
|
if (Pref.isWindowMaximized) await windowManager.maximize();
|
|
await windowManager.show();
|
|
await windowManager.focus();
|
|
});
|
|
}
|
|
|
|
if (Pref.enableLog) {
|
|
// 异常捕获 logo记录
|
|
final customParameters = {
|
|
'BuildConfig':
|
|
'''\n
|
|
Build Time: ${DateFormatUtils.format(BuildConfig.buildTime, format: DateFormatUtils.longFormatDs)}
|
|
Commit Hash: ${BuildConfig.commitHash}''',
|
|
};
|
|
final Catcher2Options debugConfig = Catcher2Options(
|
|
SilentReportMode(),
|
|
[
|
|
FileHandler(await LoggerUtils.getLogsPath()),
|
|
ConsoleHandler(
|
|
enableDeviceParameters: false,
|
|
enableApplicationParameters: false,
|
|
enableCustomParameters: true,
|
|
),
|
|
],
|
|
customParameters: customParameters,
|
|
);
|
|
|
|
final Catcher2Options releaseConfig = Catcher2Options(
|
|
SilentReportMode(),
|
|
[
|
|
FileHandler(await LoggerUtils.getLogsPath()),
|
|
ConsoleHandler(enableCustomParameters: true),
|
|
],
|
|
customParameters: customParameters,
|
|
);
|
|
|
|
Catcher2(
|
|
debugConfig: debugConfig,
|
|
releaseConfig: releaseConfig,
|
|
runAppFunction: () => runApp(const MyApp()),
|
|
);
|
|
} else {
|
|
runApp(const MyApp());
|
|
}
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
const MyApp({super.key});
|
|
|
|
static ThemeData? darkThemeData;
|
|
|
|
static void _onBack() {
|
|
if (SmartDialog.checkExist()) {
|
|
SmartDialog.dismiss();
|
|
return;
|
|
}
|
|
|
|
if (Get.isDialogOpen ?? Get.isBottomSheetOpen ?? false) {
|
|
Get.back();
|
|
return;
|
|
}
|
|
|
|
final plCtr = PlPlayerController.instance;
|
|
if (plCtr != null) {
|
|
if (plCtr.isFullScreen.value) {
|
|
plCtr
|
|
..triggerFullScreen(status: false)
|
|
..controlsLock.value = false
|
|
..showControls.value = false;
|
|
return;
|
|
}
|
|
|
|
if (plCtr.isDesktopPip) {
|
|
plCtr
|
|
..exitDesktopPip().whenComplete(
|
|
() => plCtr.initialFocalPoint = Offset.zero,
|
|
)
|
|
..controlsLock.value = false
|
|
..showControls.value = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
Get.back();
|
|
}
|
|
|
|
static Widget _build({
|
|
ColorScheme? lightColorScheme,
|
|
ColorScheme? darkColorScheme,
|
|
}) {
|
|
late final brandColor = colorThemeTypes[Pref.customColor].color;
|
|
late final variant = FlexSchemeVariant.values[Pref.schemeVariant];
|
|
return GetMaterialApp(
|
|
title: Constants.appName,
|
|
theme: ThemeUtils.getThemeData(
|
|
colorScheme:
|
|
lightColorScheme ??
|
|
SeedColorScheme.fromSeeds(
|
|
variant: variant,
|
|
primaryKey: brandColor,
|
|
brightness: Brightness.light,
|
|
useExpressiveOnContainerColors: false,
|
|
),
|
|
isDynamic: lightColorScheme != null,
|
|
),
|
|
darkTheme: ThemeUtils.getThemeData(
|
|
isDark: true,
|
|
colorScheme:
|
|
darkColorScheme ??
|
|
SeedColorScheme.fromSeeds(
|
|
variant: variant,
|
|
primaryKey: brandColor,
|
|
brightness: Brightness.dark,
|
|
useExpressiveOnContainerColors: false,
|
|
),
|
|
isDynamic: darkColorScheme != null,
|
|
),
|
|
themeMode: Pref.themeMode,
|
|
localizationsDelegates: const [
|
|
GlobalCupertinoLocalizations.delegate,
|
|
GlobalMaterialLocalizations.delegate,
|
|
GlobalWidgetsLocalizations.delegate,
|
|
],
|
|
locale: const Locale("zh", "CN"),
|
|
fallbackLocale: const Locale("zh", "CN"),
|
|
supportedLocales: const [Locale("zh", "CN"), Locale("en", "US")],
|
|
initialRoute: '/',
|
|
getPages: Routes.getPages,
|
|
builder: FlutterSmartDialog.init(
|
|
toastBuilder: (String msg) => CustomToast(msg: msg),
|
|
loadingBuilder: (msg) => LoadingWidget(msg: msg),
|
|
builder: (context, child) {
|
|
child = MediaQuery(
|
|
data: MediaQuery.of(context).copyWith(
|
|
textScaler: TextScaler.linear(Pref.defaultTextScale),
|
|
),
|
|
child: child!,
|
|
);
|
|
if (Utils.isDesktop) {
|
|
return Focus(
|
|
canRequestFocus: false,
|
|
onKeyEvent: (_, event) {
|
|
if (event.logicalKey == LogicalKeyboardKey.escape &&
|
|
event is KeyDownEvent) {
|
|
_onBack();
|
|
return KeyEventResult.handled;
|
|
}
|
|
return KeyEventResult.ignored;
|
|
},
|
|
child: MouseBackDetector(
|
|
onTapDown: _onBack,
|
|
child: child,
|
|
),
|
|
);
|
|
}
|
|
return child;
|
|
},
|
|
),
|
|
navigatorObservers: [
|
|
PageUtils.routeObserver,
|
|
FlutterSmartDialog.observer,
|
|
],
|
|
scrollBehavior: const MaterialScrollBehavior().copyWith(
|
|
scrollbars: false,
|
|
dragDevices: {
|
|
PointerDeviceKind.touch,
|
|
PointerDeviceKind.stylus,
|
|
PointerDeviceKind.invertedStylus,
|
|
PointerDeviceKind.trackpad,
|
|
PointerDeviceKind.unknown,
|
|
if (Utils.isDesktop) PointerDeviceKind.mouse,
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (!Platform.isIOS && Pref.dynamicColor) {
|
|
return DynamicColorBuilder(
|
|
builder: ((ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
|
|
if (lightDynamic != null && darkDynamic != null) {
|
|
return _build(
|
|
lightColorScheme: lightDynamic.harmonized(),
|
|
darkColorScheme: darkDynamic.harmonized(),
|
|
);
|
|
} else {
|
|
return _build();
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
return _build();
|
|
}
|
|
}
|
|
|
|
class _CustomHttpOverrides extends HttpOverrides {
|
|
@override
|
|
HttpClient createHttpClient(SecurityContext? context) {
|
|
final client = super.createHttpClient(context)
|
|
// ..maxConnectionsPerHost = 32
|
|
..idleTimeout = const Duration(seconds: 15);
|
|
if (kDebugMode || Pref.badCertificateCallback) {
|
|
client.badCertificateCallback = (cert, host, port) => true;
|
|
}
|
|
return client;
|
|
}
|
|
}
|