494 lines
15 KiB
Dart
Executable File
494 lines
15 KiB
Dart
Executable File
import 'package:flutter/material.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
|
|
import '../../../services/singbox_imp/kr_sing_box_imp.dart';
|
|
import '../controllers/kr_setting_controller.dart';
|
|
import '../../../themes/kr_theme_service.dart';
|
|
import '../../../localization/app_translations.dart';
|
|
import '../../../routes/app_pages.dart';
|
|
import '../../../common/app_run_data.dart';
|
|
|
|
class KRSettingView extends GetView<KRSettingController> {
|
|
const KRSettingView({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
extendBodyBehindAppBar: true,
|
|
backgroundColor: Theme.of(context).primaryColor,
|
|
appBar: AppBar(
|
|
backgroundColor: Colors.transparent,
|
|
elevation: 0,
|
|
leading: IconButton(
|
|
icon: Icon(
|
|
Icons.arrow_back_ios,
|
|
size: 20.r,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
onPressed: () => Get.back(),
|
|
),
|
|
centerTitle: true,
|
|
title: Text(
|
|
AppTranslations.kr_setting.title,
|
|
style: KrAppTextStyle(
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
body: Obx(() {
|
|
return Container(
|
|
height: MediaQuery.of(context).size.height,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Color.fromRGBO(23, 151, 255, 0.15),
|
|
Color.fromRGBO(23, 151, 255, 0.05),
|
|
],
|
|
stops: [0.0, 0.3],
|
|
),
|
|
),
|
|
child: SingleChildScrollView(
|
|
physics: const BouncingScrollPhysics(),
|
|
child: Padding(
|
|
padding: EdgeInsets.only(
|
|
bottom: MediaQuery.of(context).padding.bottom),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: kToolbarHeight + 20.w),
|
|
_kr_buildSectionTitle(
|
|
context, AppTranslations.kr_setting.vpnConnection),
|
|
_kr_buildVPNSection(context),
|
|
_kr_buildSectionTitle(
|
|
context, AppTranslations.kr_setting.general),
|
|
_kr_buildGeneralSection(context),
|
|
SizedBox(height: 100.h),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildSectionTitle(BuildContext context, String title) {
|
|
return Padding(
|
|
padding: EdgeInsets.fromLTRB(16.w, 24.h, 16.w, 8.h),
|
|
child: Text(
|
|
title,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildVPNSection(BuildContext context) {
|
|
return Container(
|
|
margin: EdgeInsets.symmetric(horizontal: 16.w),
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).cardColor,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
_kr_buildSelectionTile(
|
|
context,
|
|
title: AppTranslations.kr_setting.mode,
|
|
value: controller.kr_vpnMode.value,
|
|
// subtitle: controller.kr_vpnModeRemark.value,
|
|
onTap: () => _kr_showRouteRuleSelectionSheet(context),
|
|
),
|
|
_kr_buildDivider(),
|
|
// _kr_buildSwitchTile(
|
|
// context,
|
|
// title: AppTranslations.kr_setting.autoConnect,
|
|
// value: controller.kr_autoConnect,
|
|
// onChanged: (value) => controller.kr_autoConnect.value = value,
|
|
// ),
|
|
// _kr_buildDivider(),
|
|
// _kr_buildSelectionTile(
|
|
// context,
|
|
// title: AppTranslations.kr_setting.routeRule,
|
|
// value: controller.kr_routeRule.value,
|
|
// onTap: () => _kr_showRouteRuleSelectionSheet(context),
|
|
// ),
|
|
// _kr_buildDivider(),
|
|
_kr_buildSelectionTile(
|
|
context,
|
|
title: AppTranslations.kr_setting.countrySelector,
|
|
subtitle: AppTranslations.kr_setting.connectionTypeRuleRemark,
|
|
value: controller.kr_currentCountry.value,
|
|
onTap: () => Get.toNamed(Routes.KR_COUNTRY_SELECTOR),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _kr_showVPNModeSelectionSheet(BuildContext context) {
|
|
Get.bottomSheet(
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).cardColor,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16.r)),
|
|
),
|
|
child: Padding(
|
|
padding: EdgeInsets.only(
|
|
bottom: MediaQuery.of(context).padding.bottom + 16.r),
|
|
child: Wrap(
|
|
children: [
|
|
ListTile(
|
|
title: Center(
|
|
child: Text(AppTranslations.kr_setting.vpnModeSmart),
|
|
),
|
|
onTap: () {
|
|
controller.kr_changeVPNMode(AppTranslations.kr_setting.vpnModeSmart);
|
|
Get.back();
|
|
},
|
|
),
|
|
ListTile(
|
|
title: Center(
|
|
child: Text(AppTranslations.kr_setting.vpnModeSecure),
|
|
),
|
|
onTap: () {
|
|
controller.kr_changeVPNMode(AppTranslations.kr_setting.vpnModeSecure);
|
|
Get.back();
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _kr_showRouteRuleSelectionSheet(BuildContext context) {
|
|
Get.bottomSheet(
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).cardColor,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16.r)),
|
|
),
|
|
child: Padding(
|
|
padding: EdgeInsets.only(
|
|
bottom: MediaQuery.of(context).padding.bottom + 16.r),
|
|
child: Wrap(
|
|
children: KRConnectionType.values.map((type) {
|
|
return ListTile(
|
|
title: Center(
|
|
child: Text(
|
|
controller.kr_getConnectionTypeString(type),
|
|
style: KrAppTextStyle(
|
|
fontSize: 16,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
),
|
|
),
|
|
onTap: () {
|
|
controller.kr_updateConnectionType(type);
|
|
Get.back();
|
|
},
|
|
);
|
|
}).toList(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildGeneralSection(BuildContext context) {
|
|
return Container(
|
|
margin: EdgeInsets.symmetric(horizontal: 16.w),
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).cardColor,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Obx(() => _kr_buildSelectionTile(
|
|
context,
|
|
title: AppTranslations.kr_setting.appearance,
|
|
value: controller.kr_themeOption.value,
|
|
onTap: () => _showThemeSelectionSheet(context),
|
|
)),
|
|
_kr_buildDivider(),
|
|
_kr_buildSwitchTile(
|
|
context,
|
|
title: AppTranslations.kr_setting.notifications,
|
|
value: controller.kr_notification,
|
|
onChanged: (value) => controller.kr_notification.value = value,
|
|
),
|
|
_kr_buildDivider(),
|
|
_kr_buildSwitchTile(
|
|
context,
|
|
title: AppTranslations.kr_setting.helpImprove,
|
|
value: controller.kr_helpImprove,
|
|
onChanged: (value) => controller.kr_helpImprove.value = value,
|
|
),
|
|
_kr_buildDivider(),
|
|
Obx(() {
|
|
final appRunData = KRAppRunData.getInstance();
|
|
final isLoggedIn = appRunData.kr_isLogin.value;
|
|
final isDeviceLogin = appRunData.isDeviceLogin();
|
|
|
|
if (!isLoggedIn) {
|
|
// 未登录,不显示此项
|
|
return SizedBox.shrink();
|
|
} else if (isDeviceLogin) {
|
|
// 设备登录(游客模式),显示"点击这里登录/注册"
|
|
return _kr_buildActionTile(
|
|
context,
|
|
title: 'userInfo.loginRegister'.tr,
|
|
trailing: "",
|
|
onTap: () => Get.toNamed(Routes.MR_LOGIN),
|
|
);
|
|
} else {
|
|
// 正常登录,显示用户邮箱
|
|
final userEmail = appRunData.kr_account.value ?? AppTranslations.kr_userInfo.myAccount;
|
|
return _kr_buildActionTile(
|
|
context,
|
|
title: userEmail,
|
|
trailing: AppTranslations.kr_setting.goToDelete,
|
|
onTap: controller.kr_deleteAccount,
|
|
);
|
|
}
|
|
}),
|
|
_kr_buildDivider(),
|
|
// _kr_buildTitleTile(
|
|
// context,
|
|
// title: AppTranslations.kr_setting.rateUs,
|
|
// ),
|
|
// _kr_buildDivider(),
|
|
Obx(() => _kr_buildValueTile(
|
|
context,
|
|
title: AppTranslations.kr_setting.version,
|
|
value: controller.kr_version.value,
|
|
)),
|
|
_kr_buildDivider(),
|
|
_kr_buildSelectionTile(
|
|
context,
|
|
title: AppTranslations.kr_setting.switchLanguage,
|
|
value: controller.kr_language.value,
|
|
onTap: controller.kr_changeLanguage,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showThemeSelectionSheet(BuildContext context) {
|
|
Get.bottomSheet(
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).cardColor,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16.r)),
|
|
),
|
|
child: Padding(
|
|
padding: EdgeInsets.only(
|
|
bottom: MediaQuery.of(context).padding.bottom + 16.r),
|
|
child: Wrap(
|
|
children: ThemeMode.values.map((option) {
|
|
String optionText;
|
|
switch (option) {
|
|
case ThemeMode.system:
|
|
optionText = AppTranslations.kr_setting.system;
|
|
break;
|
|
case ThemeMode.light:
|
|
optionText = AppTranslations.kr_setting.light;
|
|
break;
|
|
case ThemeMode.dark:
|
|
optionText = AppTranslations.kr_setting.dark;
|
|
break;
|
|
}
|
|
return ListTile(
|
|
title: Center(
|
|
child: Text(
|
|
optionText,
|
|
style: KrAppTextStyle(
|
|
fontSize: 16,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
),
|
|
),
|
|
onTap: () async {
|
|
final KRThemeService themeService = KRThemeService();
|
|
await themeService.kr_switchTheme(option);
|
|
|
|
controller.kr_themeOption.value = optionText;
|
|
Get.back();
|
|
},
|
|
);
|
|
}).toList(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildSelectionTile(
|
|
BuildContext context, {
|
|
required String title,
|
|
required String value,
|
|
String? subtitle,
|
|
required VoidCallback onTap,
|
|
}) {
|
|
return ListTile(
|
|
title: Text(
|
|
title,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
),
|
|
subtitle: subtitle != null
|
|
? Text(
|
|
subtitle,
|
|
style: KrAppTextStyle(
|
|
fontSize: 12,
|
|
color: Theme.of(context).textTheme.bodySmall?.color,
|
|
),
|
|
)
|
|
: null,
|
|
trailing: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(
|
|
value,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
),
|
|
SizedBox(width: 4.w),
|
|
Icon(
|
|
Icons.arrow_forward_ios,
|
|
size: 16.r,
|
|
color: Theme.of(context).textTheme.bodySmall?.color,
|
|
),
|
|
],
|
|
),
|
|
onTap: onTap,
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildSwitchTile(
|
|
BuildContext context, {
|
|
required String title,
|
|
String? subtitle,
|
|
required RxBool value,
|
|
required Function(bool) onChanged,
|
|
}) {
|
|
return ListTile(
|
|
title: Text(
|
|
title,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
),
|
|
subtitle: subtitle != null
|
|
? Text(
|
|
subtitle,
|
|
style: KrAppTextStyle(
|
|
fontSize: 12,
|
|
color: Theme.of(context).textTheme.bodySmall?.color,
|
|
),
|
|
)
|
|
: null,
|
|
trailing: Obx(
|
|
() => CupertinoSwitch(
|
|
value: value.value,
|
|
onChanged: onChanged,
|
|
activeColor: Colors.blue,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildActionTile(
|
|
BuildContext context, {
|
|
required String title,
|
|
required String trailing,
|
|
required VoidCallback onTap,
|
|
}) {
|
|
return ListTile(
|
|
title: Text(
|
|
title,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: Theme.of(context).textTheme.bodySmall?.color,
|
|
),
|
|
),
|
|
trailing: Text(
|
|
trailing,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
color: Theme.of(context).textTheme.bodySmall?.color,
|
|
),
|
|
),
|
|
onTap: onTap,
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildTitleTile(
|
|
BuildContext context, {
|
|
required String title,
|
|
}) {
|
|
return ListTile(
|
|
title: Text(
|
|
title,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildValueTile(
|
|
BuildContext context, {
|
|
required String title,
|
|
required String value,
|
|
}) {
|
|
return ListTile(
|
|
title: Text(
|
|
title,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
),
|
|
),
|
|
trailing: Text(
|
|
value,
|
|
style: KrAppTextStyle(
|
|
fontSize: 14,
|
|
color: Theme.of(context).textTheme.bodySmall?.color,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _kr_buildDivider() {
|
|
return Divider(
|
|
height: 1.h,
|
|
thickness: 0.2,
|
|
color: const Color(0xFFEEEEEE),
|
|
);
|
|
}
|
|
}
|