mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-20 11:08:03 +08:00
318 lines
11 KiB
Dart
318 lines
11 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:PiliPlus/build_config.dart';
|
|
import 'package:PiliPlus/common/assets.dart';
|
|
import 'package:PiliPlus/common/constants.dart';
|
|
import 'package:PiliPlus/common/style.dart';
|
|
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
|
import 'package:PiliPlus/common/widgets/dialog/export_import.dart';
|
|
import 'package:PiliPlus/common/widgets/flutter/list_tile.dart';
|
|
import 'package:PiliPlus/common/widgets/flutter/scroll_view/scroll_view.dart';
|
|
import 'package:PiliPlus/pages/mine/controller.dart';
|
|
import 'package:PiliPlus/services/logger.dart';
|
|
import 'package:PiliPlus/utils/accounts.dart';
|
|
import 'package:PiliPlus/utils/accounts/account.dart';
|
|
import 'package:PiliPlus/utils/cache_manager.dart';
|
|
import 'package:PiliPlus/utils/date_utils.dart';
|
|
import 'package:PiliPlus/utils/extension/context_ext.dart';
|
|
import 'package:PiliPlus/utils/extension/num_ext.dart';
|
|
import 'package:PiliPlus/utils/login_utils.dart';
|
|
import 'package:PiliPlus/utils/page_utils.dart';
|
|
import 'package:PiliPlus/utils/platform_utils.dart';
|
|
import 'package:PiliPlus/utils/storage.dart';
|
|
import 'package:PiliPlus/utils/update.dart';
|
|
import 'package:PiliPlus/utils/utils.dart';
|
|
import 'package:flutter/material.dart' hide ListTile;
|
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
|
|
|
class AboutPage extends StatefulWidget {
|
|
const AboutPage({super.key, this.showAppBar = true});
|
|
|
|
final bool showAppBar;
|
|
|
|
@override
|
|
State<AboutPage> createState() => _AboutPageState();
|
|
}
|
|
|
|
class _AboutPageState extends State<AboutPage> {
|
|
final currentVersion =
|
|
'${BuildConfig.versionName}+${BuildConfig.versionCode}';
|
|
RxString cacheSize = ''.obs;
|
|
|
|
late int _pressCount = 0;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
getCacheSize();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
cacheSize.close();
|
|
super.dispose();
|
|
}
|
|
|
|
void getCacheSize() {
|
|
CacheManager.loadApplicationCache().then((res) {
|
|
if (mounted) {
|
|
cacheSize.value = CacheManager.formatSize(res);
|
|
}
|
|
});
|
|
}
|
|
|
|
void _showDialog() => showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
constraints: Style.dialogFixedConstraints,
|
|
content: TextField(
|
|
autofocus: true,
|
|
onSubmitted: (value) {
|
|
Get.back();
|
|
if (value.isNotEmpty) {
|
|
PageUtils.handleWebview(value, inApp: true);
|
|
}
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final theme = Theme.of(context);
|
|
const style = TextStyle(fontSize: 15);
|
|
final outline = theme.colorScheme.outline;
|
|
final subTitleStyle = TextStyle(fontSize: 13, color: outline);
|
|
final showAppBar = widget.showAppBar;
|
|
final padding = MediaQuery.viewPaddingOf(context);
|
|
return Scaffold(
|
|
appBar: showAppBar ? AppBar(title: const Text('关于')) : null,
|
|
resizeToAvoidBottomInset: false,
|
|
body: listView(
|
|
padding: EdgeInsets.only(
|
|
left: showAppBar ? padding.left : 0,
|
|
right: showAppBar ? padding.right : 0,
|
|
bottom: padding.bottom + 100,
|
|
),
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () {
|
|
if (++_pressCount == 5) {
|
|
_pressCount = 0;
|
|
_showDialog();
|
|
}
|
|
},
|
|
onSecondaryTap: PlatformUtils.isDesktop ? _showDialog : null,
|
|
child: Image.asset(
|
|
width: 150,
|
|
height: 150,
|
|
excludeFromSemantics: true,
|
|
cacheWidth: 150.cacheSize(context),
|
|
Assets.logo,
|
|
),
|
|
),
|
|
ListTile(
|
|
title: Text(
|
|
Constants.appName,
|
|
textAlign: TextAlign.center,
|
|
style: theme.textTheme.titleMedium!.copyWith(height: 2),
|
|
),
|
|
subtitle: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
'使用Flutter开发的B站第三方客户端',
|
|
style: TextStyle(color: outline),
|
|
semanticsLabel: '与你一起,发现不一样的世界',
|
|
),
|
|
const Icon(
|
|
Icons.accessibility_new,
|
|
semanticLabel: "无障碍适配",
|
|
size: 18,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
ListTile(
|
|
onTap: () => Update.checkUpdate(false),
|
|
onLongPress: () => Utils.copyText(currentVersion),
|
|
onSecondaryTap: PlatformUtils.isMobile
|
|
? null
|
|
: () => Utils.copyText(currentVersion),
|
|
title: const Text('当前版本'),
|
|
leading: const Icon(Icons.commit_outlined),
|
|
trailing: Text(
|
|
currentVersion,
|
|
style: subTitleStyle,
|
|
),
|
|
),
|
|
ListTile(
|
|
title: Text(
|
|
'''
|
|
Build Time: ${DateFormatUtils.format(BuildConfig.buildTime, format: DateFormatUtils.longFormatDs)}
|
|
Commit Hash: ${BuildConfig.commitHash}''',
|
|
style: const TextStyle(fontSize: 14),
|
|
),
|
|
leading: const Icon(Icons.info_outline),
|
|
onTap: () => PageUtils.launchURL(
|
|
'${Constants.sourceCodeUrl}/commit/${BuildConfig.commitHash}',
|
|
),
|
|
onLongPress: () => Utils.copyText(BuildConfig.commitHash),
|
|
onSecondaryTap: PlatformUtils.isMobile
|
|
? null
|
|
: () => Utils.copyText(BuildConfig.commitHash),
|
|
),
|
|
Divider(
|
|
thickness: 1,
|
|
height: 30,
|
|
color: theme.colorScheme.outlineVariant,
|
|
),
|
|
ListTile(
|
|
onTap: () => PageUtils.launchURL(Constants.sourceCodeUrl),
|
|
leading: const Icon(Icons.code),
|
|
title: const Text('Source Code'),
|
|
subtitle: Text(Constants.sourceCodeUrl, style: subTitleStyle),
|
|
),
|
|
if (Platform.isAndroid)
|
|
ListTile(
|
|
onTap: () => Utils.channel.invokeMethod('linkVerifySettings'),
|
|
leading: const Icon(MdiIcons.linkBoxOutline),
|
|
title: const Text('打开受支持的链接'),
|
|
trailing: Icon(
|
|
Icons.arrow_forward,
|
|
size: 16,
|
|
color: outline,
|
|
),
|
|
),
|
|
ListTile(
|
|
onTap: () =>
|
|
PageUtils.launchURL('${Constants.sourceCodeUrl}/issues'),
|
|
leading: const Icon(Icons.feedback_outlined),
|
|
title: const Text('问题反馈'),
|
|
trailing: Icon(
|
|
Icons.arrow_forward,
|
|
size: 16,
|
|
color: outline,
|
|
),
|
|
),
|
|
ListTile(
|
|
onTap: () => Get.toNamed('/logs'),
|
|
onLongPress: LoggerUtils.clearLogs,
|
|
onSecondaryTap: PlatformUtils.isMobile
|
|
? null
|
|
: LoggerUtils.clearLogs,
|
|
leading: const Icon(Icons.bug_report_outlined),
|
|
title: const Text('错误日志'),
|
|
subtitle: Text('长按清除日志', style: subTitleStyle),
|
|
trailing: Icon(Icons.arrow_forward, size: 16, color: outline),
|
|
),
|
|
ListTile(
|
|
onTap: () {
|
|
if (cacheSize.value.isNotEmpty) {
|
|
showConfirmDialog(
|
|
context: context,
|
|
title: const Text('提示'),
|
|
content: const Text('该操作将清除图片及网络请求缓存数据,确认清除?'),
|
|
onConfirm: () async {
|
|
SmartDialog.showLoading(msg: '正在清除...');
|
|
try {
|
|
await CacheManager.clearLibraryCache();
|
|
SmartDialog.showToast('清除成功');
|
|
} catch (err) {
|
|
SmartDialog.showToast(err.toString());
|
|
} finally {
|
|
SmartDialog.dismiss();
|
|
}
|
|
getCacheSize();
|
|
},
|
|
);
|
|
}
|
|
},
|
|
leading: const Icon(Icons.delete_outline),
|
|
title: const Text('清除缓存'),
|
|
subtitle: Obx(
|
|
() => Text(
|
|
'图片及网络缓存 ${cacheSize.value}',
|
|
style: subTitleStyle,
|
|
),
|
|
),
|
|
),
|
|
ListTile(
|
|
title: const Text('导入/导出登录信息'),
|
|
leading: const Icon(Icons.import_export_outlined),
|
|
onTap: () => showImportExportDialog<Map>(
|
|
context,
|
|
title: '登录信息',
|
|
localFileName: () => 'account',
|
|
onExport: () =>
|
|
Utils.jsonEncoder.convert(Accounts.account.toMap()),
|
|
onImport: (json) async {
|
|
final res = json.map(
|
|
(key, value) => MapEntry(key, LoginAccount.fromJson(value)),
|
|
);
|
|
await Accounts.account.putAll(res);
|
|
await Accounts.refresh();
|
|
MineController.anonymity.value = !Accounts.heartbeat.isLogin;
|
|
if (Accounts.main.isLogin) {
|
|
await LoginUtils.onLoginMain();
|
|
}
|
|
},
|
|
),
|
|
),
|
|
ListTile(
|
|
title: const Text('导入/导出设置'),
|
|
dense: false,
|
|
leading: const Icon(Icons.import_export_outlined),
|
|
onTap: () => showImportExportDialog<Map<String, dynamic>>(
|
|
context,
|
|
title: '设置',
|
|
localFileName: () => 'setting_${context.platformName}',
|
|
onExport: GStorage.exportAllSettings,
|
|
onImport: GStorage.importAllJsonSettings,
|
|
),
|
|
),
|
|
ListTile(
|
|
title: const Text('重置所有设置'),
|
|
leading: const Icon(Icons.settings_backup_restore_outlined),
|
|
onTap: () => showDialog(
|
|
context: context,
|
|
builder: (context) {
|
|
return SimpleDialog(
|
|
clipBehavior: Clip.hardEdge,
|
|
title: const Text('是否重置所有设置?'),
|
|
children: [
|
|
ListTile(
|
|
dense: true,
|
|
onTap: () async {
|
|
Get.back();
|
|
await Future.wait([
|
|
GStorage.setting.clear(),
|
|
GStorage.video.clear(),
|
|
]);
|
|
SmartDialog.showToast('重置成功');
|
|
},
|
|
title: const Text('重置可导出的设置', style: style),
|
|
),
|
|
ListTile(
|
|
dense: true,
|
|
onTap: () async {
|
|
Get.back();
|
|
await GStorage.clear();
|
|
SmartDialog.showToast('重置成功');
|
|
},
|
|
title: const Text('重置所有数据(含登录信息)', style: style),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|