opt: safearea

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-04-21 11:15:21 +08:00
parent 95caf111ae
commit 9ad57dccb0
37 changed files with 1660 additions and 1518 deletions

View File

@@ -52,220 +52,230 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('选择应用主题')),
body: ListView(
children: [
ListTile(
onTap: () async {
ThemeType? result = await showDialog(
context: context,
builder: (context) {
return SelectDialog<ThemeType>(
title: '主题模式',
value: ctr.themeType.value,
values: ThemeType.values
.map((e) => (e, e.description))
.toList());
},
);
if (result != null) {
try {
Get.find<MineController>().themeType.value = result;
} catch (_) {}
ctr.themeType.value = result;
GStorage.setting.put(SettingBoxKey.themeMode, result.index);
Get.changeThemeMode(result.toThemeMode);
}
},
leading: Container(
width: 40,
alignment: Alignment.center,
child: const Icon(Icons.flashlight_on_outlined),
body: SafeArea(
bottom: false,
child: ListView(
children: [
ListTile(
onTap: () async {
ThemeType? result = await showDialog(
context: context,
builder: (context) {
return SelectDialog<ThemeType>(
title: '主题模式',
value: ctr.themeType.value,
values: ThemeType.values
.map((e) => (e, e.description))
.toList());
},
);
if (result != null) {
try {
Get.find<MineController>().themeType.value = result;
} catch (_) {}
ctr.themeType.value = result;
GStorage.setting.put(SettingBoxKey.themeMode, result.index);
Get.changeThemeMode(result.toThemeMode);
}
},
leading: Container(
width: 40,
alignment: Alignment.center,
child: const Icon(Icons.flashlight_on_outlined),
),
title: Text('主题模式', style: titleStyle),
subtitle: Obx(() => Text(
'当前模式:${ctr.themeType.value.description}',
style: subTitleStyle)),
),
title: Text('主题模式', style: titleStyle),
subtitle: Obx(() => Text('当前模式:${ctr.themeType.value.description}',
style: subTitleStyle)),
),
Obx(
() => ListTile(
enabled: ctr.type.value != 0,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('调色板风格'),
PopupMenuButton(
enabled: ctr.type.value != 0,
initialValue: _dynamicSchemeVariant,
onSelected: (item) async {
_dynamicSchemeVariant = item;
await GStorage.setting
.put(SettingBoxKey.schemeVariant, item.index);
Get.forceAppUpdate();
},
itemBuilder: (context) => FlexSchemeVariant.values
.map((item) => PopupMenuItem<FlexSchemeVariant>(
value: item,
child: Text(item.variantName),
))
.toList(),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
_dynamicSchemeVariant.variantName,
style: TextStyle(
height: 1,
fontSize: 13,
Obx(
() => ListTile(
enabled: ctr.type.value != 0,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('调色板风格'),
PopupMenuButton(
enabled: ctr.type.value != 0,
initialValue: _dynamicSchemeVariant,
onSelected: (item) async {
_dynamicSchemeVariant = item;
await GStorage.setting
.put(SettingBoxKey.schemeVariant, item.index);
Get.forceAppUpdate();
},
itemBuilder: (context) => FlexSchemeVariant.values
.map((item) => PopupMenuItem<FlexSchemeVariant>(
value: item,
child: Text(item.variantName),
))
.toList(),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
_dynamicSchemeVariant.variantName,
style: TextStyle(
height: 1,
fontSize: 13,
color: ctr.type.value == 0
? Theme.of(context)
.colorScheme
.outline
.withOpacity(0.8)
: Theme.of(context).colorScheme.secondary,
),
strutStyle: StrutStyle(leading: 0, height: 1),
),
Icon(
size: 20,
Icons.keyboard_arrow_right,
color: ctr.type.value == 0
? Theme.of(context)
.colorScheme
.outline
.withOpacity(0.8)
: Theme.of(context).colorScheme.secondary,
),
strutStyle: StrutStyle(leading: 0, height: 1),
),
Icon(
size: 20,
Icons.keyboard_arrow_right,
color: ctr.type.value == 0
? Theme.of(context)
.colorScheme
.outline
.withOpacity(0.8)
: Theme.of(context).colorScheme.secondary,
)
],
),
),
],
),
leading: Container(
width: 40,
alignment: Alignment.center,
child: Icon(Icons.palette_outlined),
),
subtitle: Text(
_dynamicSchemeVariant.description,
style: TextStyle(fontSize: 12),
),
),
),
Obx(
() => RadioListTile(
value: 0,
title: const Text('动态取色'),
groupValue: ctr.type.value,
onChanged: (dynamic val) async {
ctr.type.value = 0;
ctr.setting.put(SettingBoxKey.dynamicColor, true);
Get.forceAppUpdate();
},
),
),
Obx(
() => RadioListTile(
value: 1,
title: const Text('指定颜色'),
groupValue: ctr.type.value,
onChanged: (dynamic val) async {
ctr.type.value = 1;
ctr.setting.put(SettingBoxKey.dynamicColor, false);
Get.forceAppUpdate();
},
),
),
AnimatedSize(
curve: Curves.easeInOut,
alignment: Alignment.topCenter,
duration: const Duration(milliseconds: 200),
child: Obx(
() => SizedBox(
height: ctr.type.value == 0 ? 0 : null,
child: Padding(
padding:
const EdgeInsets.only(top: 12, left: 12, right: 12),
child: Wrap(
alignment: WrapAlignment.center,
spacing: 22,
runSpacing: 18,
children: [
...ctr.colorThemes.map(
(e) {
final index = ctr.colorThemes.indexOf(e);
return GestureDetector(
onTap: () {
ctr.currentColor.value = index;
ctr.setting
.put(SettingBoxKey.customColor, index);
Get.forceAppUpdate();
},
child: Column(
children: [
Container(
width: 46,
height: 46,
decoration: BoxDecoration(
color: e['color'].withOpacity(0.8),
borderRadius: BorderRadius.circular(50),
border: Border.all(
width: 2,
color: ctr.currentColor.value == index
? Colors.black
: e['color'].withOpacity(0.8),
),
),
child: AnimatedOpacity(
opacity: ctr.currentColor.value == index
? 1
: 0,
duration:
const Duration(milliseconds: 200),
child: const Icon(
Icons.done,
color: Colors.black,
size: 20,
),
),
),
const SizedBox(height: 3),
Text(
e['label'],
style: TextStyle(
fontSize: 12,
color: ctr.currentColor.value != index
? Theme.of(context)
.colorScheme
.outline
: null,
),
),
],
),
);
},
)
],
),
),
],
),
leading: Container(
width: 40,
alignment: Alignment.center,
child: Icon(Icons.palette_outlined),
),
subtitle: Text(
_dynamicSchemeVariant.description,
style: TextStyle(fontSize: 12),
),
),
),
Obx(
() => RadioListTile(
value: 0,
title: const Text('动态取色'),
groupValue: ctr.type.value,
onChanged: (dynamic val) async {
ctr.type.value = 0;
ctr.setting.put(SettingBoxKey.dynamicColor, true);
Get.forceAppUpdate();
},
),
),
Obx(
() => RadioListTile(
value: 1,
title: const Text('指定颜色'),
groupValue: ctr.type.value,
onChanged: (dynamic val) async {
ctr.type.value = 1;
ctr.setting.put(SettingBoxKey.dynamicColor, false);
Get.forceAppUpdate();
},
),
),
AnimatedSize(
curve: Curves.easeInOut,
alignment: Alignment.topCenter,
duration: const Duration(milliseconds: 200),
child: Obx(
() => SizedBox(
height: ctr.type.value == 0 ? 0 : null,
child: Padding(
padding: const EdgeInsets.only(top: 12, left: 12, right: 12),
child: Wrap(
alignment: WrapAlignment.center,
spacing: 22,
runSpacing: 18,
children: [
...ctr.colorThemes.map(
(e) {
final index = ctr.colorThemes.indexOf(e);
return GestureDetector(
onTap: () {
ctr.currentColor.value = index;
ctr.setting.put(SettingBoxKey.customColor, index);
Get.forceAppUpdate();
},
child: Column(
children: [
Container(
width: 46,
height: 46,
decoration: BoxDecoration(
color: e['color'].withOpacity(0.8),
borderRadius: BorderRadius.circular(50),
border: Border.all(
width: 2,
color: ctr.currentColor.value == index
? Colors.black
: e['color'].withOpacity(0.8),
),
),
child: AnimatedOpacity(
opacity:
ctr.currentColor.value == index ? 1 : 0,
duration: const Duration(milliseconds: 200),
child: const Icon(
Icons.done,
color: Colors.black,
size: 20,
),
),
),
const SizedBox(height: 3),
Text(
e['label'],
style: TextStyle(
fontSize: 12,
color: ctr.currentColor.value != index
? Theme.of(context).colorScheme.outline
: null,
),
),
],
),
);
},
)
],
),
),
),
),
),
...[
IgnorePointer(
child: SizedBox(
height: Get.height / 2,
width: Get.width,
child: const HomePage(),
...[
IgnorePointer(
child: SizedBox(
height: Get.height / 2,
width: Get.width,
child: const HomePage(),
),
),
),
IgnorePointer(
child: NavigationBar(
destinations: defaultNavigationBars
.map(
(item) => NavigationDestination(
icon: item['icon'],
label: item['label'],
),
)
.toList(),
IgnorePointer(
child: NavigationBar(
destinations: defaultNavigationBars
.map(
(item) => NavigationDestination(
icon: item['icon'],
label: item['label'],
),
)
.toList(),
),
),
),
],
],
],
),
),
);
}

View File

@@ -48,58 +48,55 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
const SizedBox(width: 12)
],
),
body: Column(
children: [
Expanded(
child: Center(
child: Text(
'当前字体大小:${currentSize == 1.0 ? '默认' : currentSize}',
style: TextStyle(fontSize: 14 * currentSize),
body: SafeArea(
child: Column(
children: [
Expanded(
child: Center(
child: Text(
'当前字体大小:${currentSize == 1.0 ? '默认' : currentSize}',
style: TextStyle(fontSize: 14 * currentSize),
),
),
),
),
Container(
width: double.infinity,
padding: EdgeInsets.only(
left: 20,
right: 20,
top: 20,
bottom: MediaQuery.of(context).padding.bottom + 20,
),
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.3))),
color: Theme.of(context).colorScheme.surface,
),
child: Row(
children: [
const Text(''),
Expanded(
child: Slider(
min: minSize,
value: currentSize,
max: maxSize,
divisions: list.length - 1,
secondaryTrackValue: 1,
onChanged: (double val) {
currentSize = val.toPrecision(2);
setState(() {});
},
Container(
width: double.infinity,
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.3))),
color: Theme.of(context).colorScheme.surface,
),
child: Row(
children: [
const Text(''),
Expanded(
child: Slider(
min: minSize,
value: currentSize,
max: maxSize,
divisions: list.length - 1,
secondaryTrackValue: 1,
onChanged: (double val) {
currentSize = val.toPrecision(2);
setState(() {});
},
),
),
),
const SizedBox(width: 5),
const Text(
'',
style: TextStyle(fontSize: 20),
),
],
),
)
],
const SizedBox(width: 5),
const Text(
'',
style: TextStyle(fontSize: 20),
),
],
),
)
],
),
),
);
}

View File

@@ -144,62 +144,79 @@ class _LogsPageState extends State<LogsPage> {
],
),
body: logsContent.isNotEmpty
? ListView.builder(
itemCount: logsContent.length,
itemBuilder: (context, index) {
final log = logsContent[index];
if (log['date'] is DateTime) {
latestLog ??= log['date'];
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
? SafeArea(
bottom: false,
child: ListView.separated(
itemCount: logsContent.length,
itemBuilder: (context, index) {
final log = logsContent[index];
if (log['date'] is DateTime) {
latestLog ??= log['date'];
}
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
log['date'].toString(),
style: Theme.of(context).textTheme.titleMedium,
Row(
children: [
Text(
log['date'].toString(),
style: TextStyle(
fontSize: Theme.of(context)
.textTheme
.titleMedium!
.fontSize,
),
),
const SizedBox(width: 10),
TextButton.icon(
style: TextButton.styleFrom(
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity:
VisualDensity(horizontal: -2, vertical: -2),
),
onPressed: () async {
await Utils.copyText('```\n${log['body']}\n```',
needToast: false);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'已将 ${log['date'].toString()} 复制至剪贴板',
),
),
);
}
},
icon: const Icon(Icons.copy_outlined, size: 16),
label: const Text('复制'),
)
],
),
const SizedBox(height: 5),
Card(
elevation: 1,
margin: EdgeInsets.zero,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(12.0),
child: SelectableText(log['body']),
),
),
TextButton.icon(
onPressed: () async {
await Utils.copyText('```\n${log['body']}\n```',
needToast: false);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'已将 ${log['date'].toString()} 复制至剪贴板',
),
),
);
}
},
icon: const Icon(Icons.copy_outlined, size: 16),
label: const Text('复制'),
)
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 1,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: SelectableText(log['body']),
),
),
),
const Divider(indent: 12, endIndent: 12),
],
);
},
);
},
separatorBuilder: (context, index) => const Divider(
indent: 12,
endIndent: 12,
height: 24,
),
),
)
: errorWidget(),
: scrollErrorWidget(),
);
}
}

View File

@@ -210,9 +210,9 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
const SizedBox(width: 16),
],
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
body: SafeArea(
bottom: false,
child: ListView(
children: [
Padding(
padding: