feat:更新api模块

This commit is contained in:
2025-11-17 22:36:20 +08:00
parent 504ee073ce
commit 6bba9a488c
17 changed files with 478 additions and 221 deletions

View File

@@ -34,9 +34,9 @@ Future<bool> addMomentCommentApi(int id, String content) {
}
Future<bool> addMomentLikeApi(int id) {
return HttpUtil().post<bool>("/moment/$id/like");
return HttpUtil().post<bool>("/food/moment/$id/like");
}
Future<bool> deleteMomentLikeApi(int id) {
return HttpUtil().delete<bool>("/moment/$id/like");
return HttpUtil().delete<bool>("/food/moment/$id/like");
}

View File

@@ -10,15 +10,15 @@ Future<RecipeDetail> queryRecipeByIdApi(int id) {
}
Future<bool> addRecipeApi(Recipe recipe) {
return HttpUtil().post<bool>("/food/food/recipe", data: recipe);
return HttpUtil().post<bool>("/food/recipe", data: recipe);
}
Future<bool> updateRecipeApi(int id, Recipe recipe) {
return HttpUtil().put<bool>("/food/food/recipe/$id", data: recipe);
return HttpUtil().put<bool>("/food/recipe/$id", data: recipe);
}
Future<bool> deleteRecipeApi(int id) {
return HttpUtil().delete<bool>("/food/food/recipe/$id");
return HttpUtil().delete<bool>("/food/recipe/$id");
}
Future<List<Recipe>> queryRecipeByUserApi(int id) {

View File

@@ -3,6 +3,7 @@ class AppConfig {
// 网络配置
// http://192.168.1.3:8100
// http://14.103.235.151:81/food-service
static const String baseApiUrl = "http://14.103.235.151:81/food-service";
// static const String baseApiUrl = "http://172.29.101.108:8100";
// static const String baseApiUrl = "http://14.103.235.151:81/food-service";
// static const String baseApiUrl = "http://192.168.1.3:8100";
static const String baseApiUrl = "https://cxx0822.iepose.cn/food-api";
}

View File

@@ -106,20 +106,10 @@ List<StatelessWidget> homeActions(BuildContext context) {
// 搜索功能
},
),
IconButton(
icon: Icon(Icons.add, color: Colors.white),
onPressed: () {
Navigator.pushNamed(context, '/recordForm');
},
),
// Builder(
// builder: (BuildContext context) {
// return IconButton(
// icon: Icon(Icons.settings, color: Colors.white),
// onPressed: () {
// Scaffold.of(context).openEndDrawer();
// },
// );
// IconButton(
// icon: Icon(Icons.add, color: Colors.white),
// onPressed: () {
// Navigator.pushNamed(context, '/recordForm');
// },
// ),
];

View File

@@ -56,6 +56,74 @@ class _HomePage extends State<HomePage> {
List<Widget> get tabPages => navItems.map((item) => item.page).toList();
// 显示底部弹窗
void _showBottomSheet() {
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(16),
),
),
builder: (context) => Container(
padding: const EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
'请选择操作',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
ListTile(
leading: Icon(Icons.book, color: Theme.of(context).primaryColor),
title: const Text('新增菜谱'),
onTap: () {
Navigator.pop(context);
_handleAddRecipe();
},
),
ListTile(
leading: Icon(Icons.note_add, color: Theme.of(context).primaryColor),
title: const Text('新增记录'),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, "/recordForm");
},
),
ListTile(
leading: Icon(Icons.group, color: Theme.of(context).primaryColor),
title: const Text('发布朋友圈'),
onTap: () {
Navigator.pop(context);
_handleAddRecord();
},
)
],
),
),
);
}
// 处理添加菜谱
void _handleAddRecipe() {
// 这里添加跳转或处理添加菜谱的逻辑
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('添加菜谱功能')),
);
}
// 处理添加记录
void _handleAddRecord() {
// 这里添加跳转或处理添加记录的逻辑
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('添加记录功能')),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -77,6 +145,13 @@ class _HomePage extends State<HomePage> {
backgroundColor: Color(0xFFF5F5F5),
drawer: const SettingsDrawer(),
body: tabPages[_currentIndex],
floatingActionButton: FloatingActionButton(
backgroundColor: Theme.of(context).primaryColor,
onPressed: _showBottomSheet,
shape: const CircleBorder(),
child: const Icon(Icons.add, color: Colors.white, size: 30),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: NavBar(
navItems: bottomNavItems,
currentIndex: _currentIndex,

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:food_hub_app/api/session.dart';
import 'package:food_hub_app/apis/session.dart';
import 'package:food_hub_app/models/session.dart';
import 'package:food_hub_app/utils/sp_util.dart';
import 'package:food_hub_app/widgets/common/index.dart';

View File

@@ -1,6 +1,6 @@
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:food_hub_app/api/moment.dart';
import 'package:food_hub_app/apis/moment.dart';
import 'package:food_hub_app/models/moment.dart';
import 'package:food_hub_app/widgets/moment/card.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:food_hub_app/api/recipe.dart';
import 'package:food_hub_app/apis/recipe.dart';
import 'package:food_hub_app/models/recipe.dart';
import 'package:food_hub_app/widgets/common/index.dart';

View File

@@ -1,205 +1,194 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:food_hub_app/utils/index.dart';
import 'package:food_hub_app/widgets/common/index.dart';
import 'package:food_hub_app/widgets/common/form.dart';
import 'package:image_picker/image_picker.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import 'package:intl/intl.dart';
import 'dart:io';
class RecordFormPage extends StatefulWidget {
const RecordFormPage({super.key});
@override
State<RecordFormPage> createState() => _RecordFormPage();
State<RecordFormPage> createState() => _RecordFormPageState();
}
class _RecordFormPage extends State<RecordFormPage> {
class _RecordFormPageState extends State<RecordFormPage> {
final _formKey = GlobalKey<FormBuilderState>();
List<TextEditingController> _controller = [];
FormController _formController = FormController();
String _selected_1 = '';
String _selected_2 = '';
String? _initLocalData;
final _focusNode = FocusNode();
static const String _nameField = 'name';
static const String _dateField = 'date';
final ImagePicker _picker = ImagePicker();
XFile? _selectedImage;
/// 整个表单存放的数据
Map<String, dynamic> _formData = {"name": '', "date": '', "photo": ''};
/// 定义整个校验规则
final Map<String, TDFormValidation> _validationRules = {
'name': TDFormValidation(
validate: (value) => value == null || value.isEmpty ? 'empty' : null,
errorMessage: '输入不能为空',
type: TDFormItemType.input,
),
"birth": TDFormValidation(
validate: (value) => value == null || value.isEmpty ? 'empty' : null,
errorMessage: '不能为空',
type: TDFormItemType.dateTimePicker,
),
"photo": TDFormValidation(
validate: (value) => value == null || value.isEmpty ? 'empty' : null,
errorMessage: '不能为空',
type: TDFormItemType.upLoadImg,
),
};
List<TDUploadFile> files = [];
List<TDUploadFile> _onValueChanged(
List<TDUploadFile> fileList,
List<TDUploadFile> value,
TDUploadType event,
) {
switch (event) {
case TDUploadType.add:
fileList.addAll(value);
break;
case TDUploadType.remove:
fileList.removeWhere((element) => element.key == value[0].key);
break;
case TDUploadType.replace:
final firstReplaceFile = value.first;
final index = fileList.indexWhere(
(file) => file.key == firstReplaceFile.key,
);
if (index != -1) {
fileList[index] = firstReplaceFile;
}
break;
}
return fileList;
}
@override
void initState() {
super.initState();
}
File? imageUrl; // 改为单张图片变量
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
void _confirmClick(BuildContext context) {
if (_formKey.currentState?.saveAndValidate() ?? false) {
// showSuccessToast("新增记录成功");
print(_formData);
} else {
TDMessage.showMessage(
context: context,
visible: true,
icon: true,
content: "请先输入信息",
theme: MessageTheme.error,
duration: 3000,
);
}
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
TDFormItem buildNameItem() {
return TDFormItem(
label: '菜谱名称',
name: 'name',
type: TDFormItemType.input,
labelWidth: 82.0,
showErrorMessage: true,
requiredMark: true,
child: TDInput(
leftContentSpace: 0,
inputDecoration: InputDecoration(
hintText: "请输入菜谱名称",
border: InputBorder.none,
hintStyle: TextStyle(color: TDTheme.of(context).grayColor6),
return Scaffold(
appBar: AppBar(
title: const Text('新增记录', style: TextStyle(color: Colors.white)),
backgroundColor: theme.primaryColor,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.pop(context),
),
),
backgroundColor: const Color(0xFFF5F5F5),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(5),
child: Card(
elevation: 0,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(10),
child: _buildFormBuilder(),
),
),
),
backgroundColor: Colors.white,
additionInfoColor: TDTheme.of(context).errorColor6,
showBottomDivider: false,
onChanged: (value) {
_formData['name'] = value;
},
),
);
}
TDFormItem buildDateItem() {
return TDFormItem(
label: '完成时间',
name: 'date',
labelWidth: 82.0,
type: TDFormItemType.dateTimePicker,
contentAlign: TextAlign.left,
tipAlign: TextAlign.left,
hintText: '请选择完成时间',
select: _formData['date'],
selectFn: (BuildContext context) {
DateTime now = DateTime.now();
TDPicker.showDatePicker(
context,
title: '选择时间',
onConfirm: (selected) {
setState(() {
_formData['date'] = parseDatePickerSelected(selected);
});
Navigator.of(context).pop();
},
dateStart: [2000, 01, 01],
dateEnd: [2100, 12, 31],
initialDate: [now.year, now.month, now.day],
);
Widget _buildFormBuilder() {
return FormBuilder(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildFormLabel('菜谱名称', required: true),
const SizedBox(height: 8),
_buildNameTextField(),
const SizedBox(height: 10),
buildFormLabel('完成时间', required: true),
const SizedBox(height: 8),
_buildDateTextField(),
const SizedBox(height: 10),
buildFormLabel('上传图片', required: true),
const SizedBox(height: 10),
_buildImageUploadArea(),
const SizedBox(height: 10),
buildFormButtonGroup(context: context, onConfirm: () => _submitForm),
],
),
);
}
/// 菜谱名称输入框
Widget _buildNameTextField() {
return FormBuilderTextField(
name: _nameField,
focusNode: _focusNode,
decoration: buildInputDecoration(context: context, hintText: '请输入菜谱名称'),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入菜谱名称';
}
return null;
},
);
}
TDFormItem buildImageItem() {
return TDFormItem(
label: '上传图片',
name: 'photo',
labelWidth: 82.0,
type: TDFormItemType.upLoadImg,
child: TDUpload(
files: files,
onError: print,
onValidate: print,
onChange: ((imgList, type) {
files = _onValueChanged(files ?? [], imgList, type);
List imgs = files.map((e) => e.remotePath ?? e.assetPath).toList();
setState(() {});
}),
/// 完成时间选择框
Widget _buildDateTextField() {
return FormBuilderTextField(
name: _dateField,
readOnly: true,
decoration: buildInputDecoration(
context: context,
hintText: '请选择完成时间',
prefixIcon: const Icon(
Icons.calendar_month,
size: 20,
color: Color(0xFF86909C),
),
),
onTap: () => _onSelectDate(),
validator: (value) {
if (value == null || value.isEmpty) {
return '请选择完成时间';
}
return null;
},
);
}
Widget buildFormBtnGroup() {
/// 图片上传区域(预览+上传按钮)
Widget _buildImageUploadArea() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (imageUrl != null)
_buildImagePreviewItem()
else
_buildImageUploadButton(),
],
);
}
Widget _buildImagePreviewItem() {
return Container(
decoration: BoxDecoration(color: TDTheme.of(context).whiteColor1),
child: Padding(
padding: const EdgeInsets.all(10),
child: Row(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
children: [
Expanded(
child: TDButton(
text: '取消',
type: TDButtonType.fill,
theme: TDButtonTheme.light,
shape: TDButtonShape.rectangle,
onTap: () => Navigator.pop(context),
GestureDetector(
onTap: () => _showImagePreview(),
child: Image(
image: FileImage(imageUrl!),
width: 120,
height: 120,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Container(
width: 120,
height: 120,
color: Colors.grey[100],
child: const Center(
child: CircularProgressIndicator(strokeWidth: 2),
),
);
},
),
),
SizedBox(width: 20),
Expanded(
child: TDButton(
text: '提交',
type: TDButtonType.fill,
theme: TDButtonTheme.primary,
shape: TDButtonShape.rectangle,
onTap: () => _confirmClick(context),
Positioned(
top: 6,
right: 6,
child: GestureDetector(
onTap: _removeImage,
child: Container(
width: 24,
height: 24,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 2,
spreadRadius: 0,
),
],
),
child: const Icon(Icons.close, color: Colors.white, size: 16),
),
),
),
],
@@ -208,36 +197,137 @@ class _RecordFormPage extends State<RecordFormPage> {
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('新增记录', style: TextStyle(color: Colors.white)),
backgroundColor: Theme.of(context).primaryColor,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.pop(context)
),
),
backgroundColor: Color(0xFFF5F5F5),
body: Padding(
padding: const EdgeInsets.all(10),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: SingleChildScrollView(
child: TDForm(
formController: _formController,
data: _formData,
rules: _validationRules,
formContentAlign: TextAlign.left,
formShowErrorMessage: true,
onSubmit: () => {},
items: [buildNameItem(), buildDateItem(), buildImageItem()],
btnGroup: [buildFormBtnGroup()],
void _showImagePreview() {
showDialog(
context: context,
barrierColor: Colors.black87, // 半透明黑色背景
builder:
(context) => Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
insetPadding: const EdgeInsets.all(16),
child: GestureDetector(
onTap: () => Navigator.pop(context), // 点击空白处关闭
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
// 预览图添加轻微阴影
boxShadow: [BoxShadow(color: Colors.black38, blurRadius: 10)],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.file(
imageUrl!,
fit: BoxFit.contain, // 保持图片比例
height: MediaQuery.of(context).size.height * 0.7, // 限制最大高度
),
),
),
),
),
);
}
/// 图片上传按钮
Widget _buildImageUploadButton() {
return InkWell(
onTap: _pickImage,
borderRadius: BorderRadius.circular(8),
child: Container(
width: 96,
height: 96,
decoration: BoxDecoration(
color: const Color(0xFFF2F3F5),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: const Color(0xFFDCDFE6), width: 1),
),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.add, color: Color(0xFF86909C), size: 24),
SizedBox(height: 6),
Text(
'添加图片',
style: TextStyle(color: Color(0xFF86909C), fontSize: 13),
),
],
),
),
);
}
/// 选择日期
Future<void> _onSelectDate() async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime(2100),
builder:
(context, child) => Theme(
data: ThemeData.light().copyWith(
primaryColor: Theme.of(context).primaryColor,
colorScheme: ColorScheme.light(
primary: Theme.of(context).primaryColor,
),
buttonTheme: const ButtonThemeData(
textTheme: ButtonTextTheme.primary,
),
),
child: child!,
),
);
if (picked != null) {
_formKey.currentState?.fields[_dateField]?.didChange(
DateFormat('yyyy-MM-dd').format(picked),
);
}
}
/// 选择图片(限制单张)
Future<void> _pickImage() async {
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
if (image != null) {
setState(() {
imageUrl = File(image.path); // 直接覆盖现有图片
});
}
}
/// 移除图片
void _removeImage() {
setState(() {
imageUrl = null;
});
}
/// 提交表单
void _submitForm() {
if (_formKey.currentState?.saveAndValidate() ?? false) {
if (imageUrl == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('请上传图片'),
backgroundColor: Colors.red,
behavior: SnackBarBehavior.floating,
),
);
return;
}
final formData = {
..._formKey.currentState!.value,
'imageUrl': imageUrl?.path, // 单张图片路径
};
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('提交成功!'),
behavior: SnackBarBehavior.floating,
),
);
print('表单数据: $formData');
}
}
}

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:food_hub_app/api/stats.dart';
import 'package:food_hub_app/apis/stats.dart';
import 'package:food_hub_app/models/stats.dart';
import 'package:food_hub_app/widgets/common/chart.dart';
import 'package:food_hub_app/widgets/stats/card.dart';

View File

@@ -0,0 +1,102 @@
import 'package:flutter/material.dart';
/// 通用输入框样式
InputDecoration buildInputDecoration({
required BuildContext context,
required String hintText,
Widget? prefixIcon,
}) {
return InputDecoration(
hintText: hintText,
hintStyle: const TextStyle(
color: Color(0xFF999999),
fontSize: 15,
height: 1.2,
),
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xFFE5E7EB)),
borderRadius: BorderRadius.circular(8),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Theme.of(context).primaryColor, width: 1.5),
borderRadius: BorderRadius.circular(8),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.red, width: 1.5),
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 14),
errorStyle: const TextStyle(fontSize: 12, height: 1, color: Colors.red),
prefixIcon: prefixIcon,
prefixIconConstraints: const BoxConstraints(minWidth: 40),
isDense: true,
);
}
Widget buildFormLabel(String text, {bool required = false}) {
return RichText(
text: TextSpan(
text: text,
style: const TextStyle(
color: Color(0xFF1D2129),
fontSize: 16,
fontWeight: FontWeight.w500,
fontFamily: 'CustomFont',
height: 1.2,
),
children: [
if (required)
const TextSpan(
text: ' *',
style: TextStyle(color: Colors.red, fontSize: 16),
),
],
),
);
}
/// 表单底部按钮组组件
Widget buildFormButtonGroup({
required BuildContext context,
required VoidCallback onConfirm,
}) {
return Row(
children: [
Expanded(child: _buildCancelButton(context)),
const SizedBox(width: 16),
Expanded(child: _buildSubmitButton(context, onConfirm)),
],
);
}
/// 取消按钮
Widget _buildCancelButton(BuildContext context) {
return ElevatedButton(
onPressed: () => Navigator.pop(context), // 直接使用传入的context返回
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: const Color(0xFF4E5969),
side: const BorderSide(color: Color(0xFFDCDFE6)),
padding: const EdgeInsets.symmetric(vertical: 15),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
elevation: 0,
),
child: const Text('取消'),
);
}
/// 提交按钮
Widget _buildSubmitButton(BuildContext context, VoidCallback onConfirm) {
return ElevatedButton(
onPressed: onConfirm,
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).primaryColor, // 使用传入的context获取主题
padding: const EdgeInsets.symmetric(vertical: 15),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
elevation: 0,
),
child: const Text('提交', style: TextStyle(color: Colors.white)),
);
}

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:food_hub_app/api/recipe.dart';
import 'package:food_hub_app/apis/recipe.dart';
import 'package:food_hub_app/models/recipe.dart';
import 'package:food_hub_app/utils/date_util.dart';
import 'package:food_hub_app/utils/index.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:food_hub_app/api/recipe.dart';
import 'package:food_hub_app/apis/recipe.dart';
import 'package:food_hub_app/models/recipe.dart';
import 'package:food_hub_app/widgets/recipe/card.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';

View File

@@ -1,9 +1,8 @@
import 'package:flutter/material.dart';
import 'package:food_hub_app/api/recipe.dart';
import 'package:food_hub_app/apis/recipe.dart';
import 'package:food_hub_app/config/app_config.dart';
import 'package:food_hub_app/models/recipe.dart';
import 'package:food_hub_app/widgets/common/image.dart';
import 'package:food_hub_app/widgets/common/index.dart';
import 'package:food_hub_app/widgets/common/year_selector.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import 'package:timelines_plus/timelines_plus.dart';

View File

@@ -11,7 +11,7 @@ namespace {
///
/// Redefined in case the developer's machine has a Windows SDK older than
/// version 10.0.22000.0.
/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
/// See: https://docs.microsoft.com/windows/win32/apis/dwmapi/ne-dwmapi-dwmwindowattribute
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif