From d6acb97e40658fff970eba2a25174408dfc138e5 Mon Sep 17 00:00:00 2001 From: ZhuJHua <1624109111@qq.com> Date: Sun, 22 Dec 2024 16:03:18 +0800 Subject: [PATCH] feat(font): add support for custom font Closes #85 --- .../color_dialog/color_dialog_logic.dart | 4 +- lib/components/dialog/dialog.dart | 44 ++ .../font_manage_dialog_logic.dart | 25 + .../font_manage_dialog_view.dart | 55 +++ lib/main.dart | 4 +- lib/pages/edit/edit_logic.dart | 12 +- lib/pages/font/font_logic.dart | 117 ++++- lib/pages/font/font_state.dart | 21 +- lib/pages/font/font_view.dart | 433 +++++++++++++++--- lib/pages/home/diary/diary_logic.dart | 6 + lib/pages/home/setting/setting_logic.dart | 13 +- lib/pages/home/setting/setting_view.dart | 73 +-- lib/src/rust/api/compress.dart | 10 +- lib/src/rust/api/constants.dart | 3 +- lib/src/rust/api/font.dart | 13 + lib/src/rust/api/kmp.dart | 3 +- lib/src/rust/frb_generated.dart | 158 ++++++- lib/src/rust/frb_generated.io.dart | 76 ++- lib/src/rust/frb_generated.web.dart | 62 ++- lib/utils/data/pref.dart | 3 + lib/utils/file_util.dart | 3 + lib/utils/theme_util.dart | 99 ++-- pubspec.lock | 88 ++-- pubspec.yaml | 11 +- rust/Cargo.lock | 96 ++-- rust/Cargo.toml | 7 +- rust/src/api/font.rs | 28 ++ rust/src/api/mod.rs | 3 +- rust/src/frb_generated.rs | 166 ++++++- 29 files changed, 1267 insertions(+), 369 deletions(-) create mode 100644 lib/components/dialog/dialog.dart create mode 100644 lib/components/font_manage_dialog/font_manage_dialog_logic.dart create mode 100644 lib/components/font_manage_dialog/font_manage_dialog_view.dart create mode 100644 lib/src/rust/api/font.dart create mode 100644 rust/src/api/font.rs diff --git a/lib/components/color_dialog/color_dialog_logic.dart b/lib/components/color_dialog/color_dialog_logic.dart index 1b937f8..9d66770 100644 --- a/lib/components/color_dialog/color_dialog_logic.dart +++ b/lib/components/color_dialog/color_dialog_logic.dart @@ -28,7 +28,7 @@ class ColorDialogLogic extends GetxController { state.currentColor = index; settingLogic.state.color = index; update(); - Get.changeTheme(ThemeUtil.buildTheme(Brightness.light)); - Get.changeTheme(ThemeUtil.buildTheme(Brightness.dark)); + Get.changeTheme(await ThemeUtil.buildTheme(Brightness.light)); + Get.changeTheme(await ThemeUtil.buildTheme(Brightness.dark)); } } diff --git a/lib/components/dialog/dialog.dart b/lib/components/dialog/dialog.dart new file mode 100644 index 0000000..cf00c7f --- /dev/null +++ b/lib/components/dialog/dialog.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; + +import '../../common/values/border.dart'; + +class OptionDialog extends StatelessWidget { + final String title; + + final Map options; + + const OptionDialog({super.key, required this.title, required this.options}); + + Widget _buildOption({required String option, required Function onTap, required ColorScheme colorScheme}) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Ink( + decoration: BoxDecoration( + borderRadius: AppBorderRadius.mediumBorderRadius, + color: colorScheme.secondaryContainer, + ), + child: InkWell( + borderRadius: AppBorderRadius.mediumBorderRadius, + onTap: () { + onTap.call(); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Text(option, style: TextStyle(color: colorScheme.onSecondaryContainer)), + ), + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + return SimpleDialog( + title: Text(title), + children: options.entries + .map((entry) => _buildOption(option: entry.key, onTap: entry.value, colorScheme: colorScheme)) + .toList(), + ); + } +} diff --git a/lib/components/font_manage_dialog/font_manage_dialog_logic.dart b/lib/components/font_manage_dialog/font_manage_dialog_logic.dart new file mode 100644 index 0000000..e547fef --- /dev/null +++ b/lib/components/font_manage_dialog/font_manage_dialog_logic.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:mood_diary/utils/log_util.dart'; +import 'package:path/path.dart'; + +class FontManageDialogLogic extends GetxController { + late final TextEditingController fontNameController = + TextEditingController(text: basename(currentFontPath).split('.ttf')[0]); + + final String currentFontPath; + + FontManageDialogLogic({required this.currentFontPath}); + + @override + void onReady() { + LogUtil.printInfo(currentFontPath); + super.onReady(); + } + + @override + void onClose() { + fontNameController.dispose(); + super.onClose(); + } +} diff --git a/lib/components/font_manage_dialog/font_manage_dialog_view.dart b/lib/components/font_manage_dialog/font_manage_dialog_view.dart new file mode 100644 index 0000000..58e4b9e --- /dev/null +++ b/lib/components/font_manage_dialog/font_manage_dialog_view.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:mood_diary/common/values/border.dart'; + +import 'font_manage_dialog_logic.dart'; + +class FontManageDialogComponent extends StatelessWidget { + final String fontPath; + + const FontManageDialogComponent({super.key, required this.fontPath}); + + @override + Widget build(BuildContext context) { + final FontManageDialogLogic logic = Get.put(FontManageDialogLogic(currentFontPath: fontPath)); + final colorScheme = Theme.of(context).colorScheme; + return AlertDialog( + title: const Text('字体管理'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: logic.fontNameController, + decoration: InputDecoration( + fillColor: colorScheme.secondaryContainer, + filled: true, + border: const OutlineInputBorder( + borderRadius: AppBorderRadius.smallBorderRadius, borderSide: BorderSide.none), + ), + ), + ], + ), + actions: [ + TextButton( + onPressed: () {}, + child: Text( + '删除字体', + style: TextStyle(color: colorScheme.error), + ), + ), + TextButton( + onPressed: () { + Get.backLegacy(); + }, + child: const Text('取消'), + ), + TextButton( + onPressed: () { + Get.backLegacy(); + }, + child: const Text('确定'), + ), + ], + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 4d2c690..a4b959f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -93,8 +93,8 @@ void main() async { : mediaQuery; return windowChild; }, - theme: ThemeUtil.buildTheme(Brightness.light), - darkTheme: ThemeUtil.buildTheme(Brightness.dark), + theme: await ThemeUtil.buildTheme(Brightness.light), + darkTheme: await ThemeUtil.buildTheme(Brightness.dark), themeMode: ThemeMode.values[PrefUtil.getValue('themeMode')!], defaultTransition: Transition.cupertino, getPages: AppPages.routes, diff --git a/lib/pages/edit/edit_logic.dart b/lib/pages/edit/edit_logic.dart index 535f877..cbcc12c 100644 --- a/lib/pages/edit/edit_logic.dart +++ b/lib/pages/edit/edit_logic.dart @@ -179,21 +179,24 @@ class EditLogic extends GetxController { void insertNewLine() { final index = quillController.selection.baseOffset; final length = quillController.selection.extentOffset - index; - quillController.replaceText(index, length, const TextIndentEmbed('2'), TextSelection.collapsed(offset: index + 1)); + quillController.replaceText(index, length, const TextIndentEmbed('2'), null); + quillController.moveCursorToPosition(index + 1); } void insertNewImage({required String imagePath}) { final imageBlock = ImageBlockEmbed.fromName(imagePath); final index = quillController.selection.baseOffset; final length = quillController.selection.extentOffset - index; - quillController.replaceText(index, length, imageBlock, TextSelection.collapsed(offset: index + 1)); + quillController.replaceText(index, length, imageBlock, null); + quillController.moveCursorToPosition(index + 1); } void insertNewVideo({required String videoPath}) { final videoBlock = VideoBlockEmbed.fromName(videoPath); final index = quillController.selection.baseOffset; final length = quillController.selection.extentOffset - index; - quillController.replaceText(index, length, videoBlock, TextSelection.collapsed(offset: index + 1)); + quillController.replaceText(index, length, videoBlock, null); + quillController.moveCursorToPosition(index + 1); } Future addNewImage(XFile xFile) async { @@ -471,7 +474,8 @@ class EditLogic extends GetxController { final index = quillController.selection.baseOffset; final length = quillController.selection.extentOffset - index; // 插入音频 Embed - quillController.replaceText(index, length, audioBlock, TextSelection.collapsed(offset: index + 1)); + quillController.replaceText(index, length, audioBlock, null); + quillController.moveCursorToPosition(index + 1); update(['Audio']); } diff --git a/lib/pages/font/font_logic.dart b/lib/pages/font/font_logic.dart index a3d93c5..67c2e8d 100644 --- a/lib/pages/font/font_logic.dart +++ b/lib/pages/font/font_logic.dart @@ -1,43 +1,110 @@ +import 'dart:io'; + +import 'package:chinese_font_library/chinese_font_library.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:mood_diary/src/rust/api/font.dart'; +import 'package:mood_diary/utils/file_util.dart'; +import 'package:path/path.dart'; import '../../utils/data/pref.dart'; +import '../../utils/notice_util.dart'; +import '../../utils/theme_util.dart'; import 'font_state.dart'; class FontLogic extends GetxController with GetSingleTickerProviderStateMixin { final FontState state = FontState(); + @override + void onReady() async { + await getFontList(); + super.onReady(); + } + void changeFontScale(value) { - state.fontScale = value; - update(); + state.fontScale.value = value; + } + + void onVerticalDragStart(DragUpdateDetails details) { + state.bottomSheetHeight.value -= details.delta.dy; + state.bottomSheetHeight.value = state.bottomSheetHeight.value.clamp(state.minHeight, state.maxHeight); + } + + void changeSelectedFontPath({required String path}) { + state.currentFontPath.value = path; + } + + Future getFontList() async { + state.isFetching.value = true; + final filePathList = await FileUtil.getDirFilePath('font'); + for (var filePath in filePathList) { + if (filePath.endsWith('.ttf')) { + //尝试获取字体名称,如果获取失败,不添加到列表 + var fontName = await FontReader.getFontNameFromTtf(ttfFilePath: filePath); + if (fontName != null) { + state.fontMap[filePath] = fontName; + } + } + } + List> fontLoadFutures = []; + // 预加载字体 + for (var entry in state.fontMap.entries) { + fontLoadFutures.add(DynamicFont.file(fontFamily: entry.value, filepath: entry.key).load()); + } + await Future.wait(fontLoadFutures); + + state.isFetching.value = false; + } + + Future addFont() async { + var res = await FilePicker.platform.pickFiles( + dialogTitle: '选择字体,仅支持ttf格式,使用可变字体最佳', + type: FileType.custom, + allowMultiple: false, + allowedExtensions: ['ttf'], + ); + if (res != null) { + var path = res.files.single.path!; + // 检查字体名称,是否已经存在 + var fontName = await FontReader.getFontNameFromTtf(ttfFilePath: path); + if (state.fontMap.containsValue(fontName)) { + NoticeUtil.showToast('字体已存在'); + return; + } + var newPath = FileUtil.getRealPath('font', basename(path)); + File(path).copy(newPath); + await getFontList(); + NoticeUtil.showToast('添加成功'); + } else { + NoticeUtil.showToast('取消文件选择'); + } + } + + //更改字体 + Future changeFontTheme() async { + await PrefUtil.setValue('customFont', state.currentFontPath.value); + Get.changeTheme(await ThemeUtil.buildTheme(Brightness.light)); + Get.changeTheme(await ThemeUtil.buildTheme(Brightness.dark)); } - void changeWeight() { - update(); + //删除字体 + Future deleteFont({required String fontPath}) async { + //如果是当前使用的字体,先切换到默认字体,再删除 + if (state.currentFontPath.value == fontPath) { + state.currentFontPath.value = ''; + await changeFontTheme(); + } + await File(fontPath).delete(); + state.fontMap.remove(fontPath); + NoticeUtil.showToast('删除成功'); } //保存设置 Future saveFontScale() async { - await showDialog( - context: Get.context!, - builder: (context) { - return AlertDialog( - title: const Text('确认修改'), - actions: [ - TextButton( - onPressed: () { - Get.backLegacy(); - }, - child: const Text('取消')), - TextButton( - onPressed: () async { - Get.backLegacy(); - await PrefUtil.setValue('fontScale', state.fontScale); - Get.forceAppUpdate(); - }, - child: const Text('确认')) - ], - ); - }); + await PrefUtil.setValue('fontScale', state.fontScale.value); + await changeFontTheme(); + await Get.forceAppUpdate(); + NoticeUtil.showToast('保存成功'); } } diff --git a/lib/pages/font/font_state.dart b/lib/pages/font/font_state.dart index f0605e5..e130a81 100644 --- a/lib/pages/font/font_state.dart +++ b/lib/pages/font/font_state.dart @@ -1,11 +1,22 @@ +import 'dart:collection'; + +import 'package:get/get.dart'; + import '../../utils/data/pref.dart'; class FontState { - late double fontScale; + RxDouble fontScale = PrefUtil.getValue('fontScale')!.obs; + RxDouble bottomSheetHeight = 300.0.obs; + double minHeight = 200.0; // 最小高度 + double maxHeight = 400.0; // 最大高度 + + // 当前的自定义字体的路径 + RxString currentFontPath = PrefUtil.getValue('customFont')!.obs; + + // 字体路径,名称map + RxMap fontMap = {}.obs; - FontState() { - fontScale = (PrefUtil.getValue('fontScale'))!; + RxBool isFetching = true.obs; - ///Initialize variables - } + FontState(); } diff --git a/lib/pages/font/font_view.dart b/lib/pages/font/font_view.dart index 24445bc..52fbd2b 100644 --- a/lib/pages/font/font_view.dart +++ b/lib/pages/font/font_view.dart @@ -1,91 +1,396 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; +import 'package:marquee/marquee.dart'; +import 'package:mood_diary/common/values/border.dart'; +import 'package:mood_diary/components/loading/loading.dart'; +import 'package:mood_diary/main.dart'; +import 'package:rive_animated_icon/rive_animated_icon.dart'; import 'font_logic.dart'; class FontPage extends StatelessWidget { const FontPage({super.key}); + Widget _buildDefault({ + required bool isSelected, + required Color activeColor, + required Color inactiveColor, + required TextStyle? textStyle, + required Function onTap, + }) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + GestureDetector( + onTap: () { + onTap.call(); + }, + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + decoration: BoxDecoration( + borderRadius: AppBorderRadius.mediumBorderRadius, + border: Border.all(color: isSelected ? activeColor : inactiveColor, width: isSelected ? 2 : 1), + ), + width: 64, + height: 64, + child: const Center( + child: Text('Aa', style: TextStyle(fontSize: 32, fontFamily: '系统字体')), + ), + ), + ), + SizedBox( + width: 60, + height: 24, + child: Center( + child: Text( + '系统字体', + style: textStyle, + ), + ), + ), + ], + ); + } + + Widget _buildFont({ + required bool isSelected, + required String fontName, + required Color activeColor, + required Color inactiveColor, + required TextStyle? textStyle, + required Function onTap, + required Function onLongPress, + }) { + final textPainter = TextPainter( + text: TextSpan(text: fontName, style: textStyle), + textDirection: TextDirection.ltr, + )..layout(); + double textWidth = textPainter.size.width; + double containerWidth = 60.0; + bool shouldMarquee = textWidth > containerWidth; + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + GestureDetector( + onTap: () { + onTap.call(); + }, + onLongPress: () { + HapticFeedback.selectionClick(); + onLongPress.call(); + }, + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + decoration: BoxDecoration( + borderRadius: AppBorderRadius.mediumBorderRadius, + border: Border.all(color: isSelected ? activeColor : inactiveColor, width: isSelected ? 2 : 1), + ), + width: 64, + height: 64, + child: Center( + child: Text('Aa', style: TextStyle(fontSize: 32, fontFamily: fontName)), + ), + ), + ), + SizedBox( + width: containerWidth, + height: 24, + child: Center( + child: shouldMarquee + ? Marquee( + text: fontName, + style: textStyle, + velocity: 20, + blankSpace: 20, + ) + : Text( + fontName, + style: textStyle, + ), + ), + ), + ], + ); + } + + Widget _buildManage({ + required Function() onTap, + required Color color, + required Color iconColor, + }) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + GestureDetector( + onTap: () { + HapticFeedback.selectionClick(); + onTap.call(); + }, + child: Container( + decoration: BoxDecoration(borderRadius: AppBorderRadius.mediumBorderRadius, color: color), + width: 64, + height: 64, + child: Center( + child: LoopingRiveIcon( + riveIcon: RiveIcon.add, + width: 32, + height: 32, + strokeWidth: 4, + color: iconColor, + ), + ), + ), + ), + const SizedBox(height: 24), + ], + ); + } + + static final fontSizeMap = { + 0.8: '超小', + 0.9: '小', + 1.0: '标准', + 1.1: '大', + 1.2: '超大', + }; + @override Widget build(BuildContext context) { final logic = Bind.find(); final state = Bind.find().state; final textStyle = Theme.of(context).textTheme; + final colorScheme = Theme.of(context).colorScheme; + final viewPadding = MediaQuery.viewPaddingOf(context); + final size = MediaQuery.sizeOf(context); + + Widget buildText() { + return ListView( + children: [ + Obx(() { + return Text( + '八月的忧愁', + style: textStyle.titleLarge?.copyWith( + height: 2, + fontFamily: state.fontMap[state.currentFontPath.value] ?? '', + ), + textScaler: TextScaler.linear(state.fontScale.value), + ); + }), + Obx(() { + return Text( + '黄水塘里游着白鸭,\n' + '高粱梗油青的刚高过头,\n' + '这跳动的心怎样安插,\n' + '田里一窄条路,八月里这忧愁?\n' + '天是昨夜雨洗过的,山岗\n' + '照着太阳又留一片影;\n' + '羊跟着放羊的转进村庄,\n' + '一大棵树荫下罩着井,又像是心!\n' + '从没有人说过八月什么话,\n' + '夏天过去了,也不到秋天。\n' + '但我望着田垄,土墙上的瓜,\n' + '仍不明白生活同梦怎样的连牵。', + style: textStyle.bodyMedium?.copyWith( + height: 2, + fontFamily: state.fontMap[state.currentFontPath.value] ?? '', + ), + textScaler: TextScaler.linear(state.fontScale.value), + ); + }), + ], + ); + } + + List buildFontButton() { + return [ + _buildDefault( + isSelected: state.currentFontPath.value == '', + activeColor: colorScheme.primary, + inactiveColor: colorScheme.surfaceContainerHighest, + textStyle: textStyle.labelSmall, + onTap: () { + logic.changeSelectedFontPath(path: ''); + }, + ), + ...state.fontMap.entries.map((e) { + return _buildFont( + isSelected: state.currentFontPath.value == e.key, + fontName: e.value, + activeColor: colorScheme.primary, + inactiveColor: colorScheme.surfaceContainerHighest, + textStyle: textStyle.labelSmall, + onTap: () { + logic.changeSelectedFontPath(path: e.key); + }, + onLongPress: () { + // 显示删除字体对话框 + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('提示'), + content: Text('删除字体 ${e.value} 后,将无法恢复,是否继续?'), + actions: [ + TextButton( + onPressed: () { + Get.backLegacy(); + }, + child: Text(l10n.cancel), + ), + TextButton( + onPressed: () { + logic.deleteFont(fontPath: e.key); + Get.backLegacy(); + }, + child: Text(l10n.ok), + ), + ], + ); + }); + }); + }), + _buildManage( + onTap: logic.addFont, + color: colorScheme.surfaceContainer, + iconColor: colorScheme.onSurface, + ), + ]; + } + + Widget buildOption() { + return ListView( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: size.width < 600 + ? SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Obx(() { + return Row( + spacing: 16, + children: buildFontButton(), + ); + }), + ) + : Wrap( + spacing: 16, + runSpacing: 16, + children: buildFontButton(), + ), + ), + const Divider(endIndent: 24, indent: 24), + ListTile( + title: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [const Text('字体大小'), Text(fontSizeMap[state.fontScale.value] ?? '')], + ), + ), + contentPadding: EdgeInsets.zero, + subtitle: Slider( + value: state.fontScale.value, + min: 0.8, + max: 1.2, + divisions: 4, + onChanged: (value) { + logic.changeFontScale(value); + }, + ), + ), + ], + ); + } + return GetBuilder( builder: (_) { return Scaffold( appBar: AppBar( - title: const Text('字体大小'), + title: const Text('字体'), + backgroundColor: colorScheme.surfaceContainerLow, ), - body: Padding( - padding: const EdgeInsets.symmetric(vertical: 24.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '拖动下方滑块预览字体', - style: textStyle.titleMedium, - ), - Text( - '黄水塘里游着白鸭,\n' - '高粱梗油青的刚高过头,\n' - '这跳动的心怎样安插,\n' - '田里一窄条路,八月里这忧愁?\n' - '天是昨夜雨洗过的,山岗\n' - '照着太阳又留一片影;\n' - '羊跟着放羊的转进村庄,\n' - '一大棵树荫下罩着井,又像是心!\n' - '从没有人说过八月什么话,\n' - '夏天过去了,也不到秋天。\n' - '但我望着田垄,土墙上的瓜,\n' - '仍不明白生活同梦怎样的连牵。', - textAlign: TextAlign.center, - textScaler: TextScaler.linear(state.fontScale), + backgroundColor: colorScheme.surfaceContainerLow, + body: size.width < 600 + ? Obx(() { + return !state.isFetching.value + ? Padding( + padding: EdgeInsets.only(left: 16, right: 16, bottom: state.bottomSheetHeight.value), + child: buildText(), + ) + : const Center( + child: Processing(), + ); + }) + : Obx(() { + return !state.isFetching.value + ? Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 16, right: 16), + child: buildText(), + )), + Expanded(child: buildOption()) + ], + ) + : const Center( + child: Processing(), + ); + }), + resizeToAvoidBottomInset: false, + bottomSheet: Obx(() { + return Visibility( + visible: !state.isFetching.value && size.width < 600, + child: Container( + height: state.bottomSheetHeight.value, + padding: EdgeInsets.only(bottom: viewPadding.bottom), + decoration: ShapeDecoration( + color: colorScheme.surface, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), + ), ), - Column( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Slider( - value: state.fontScale, - min: 0.8, - max: 1.2, - divisions: 4, - label: state.fontScale.toString(), - onChanged: (value) { - logic.changeFontScale(value); - }), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 24.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '小', - textScaler: TextScaler.linear(0.8), - ), - Text( - '标准', - textScaler: TextScaler.linear(1.0), - ), - Text( - '大', - textScaler: TextScaler.linear(1.2), + Center( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onVerticalDragUpdate: logic.onVerticalDragStart, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Container( + width: 68, + height: 5, + decoration: ShapeDecoration( + color: colorScheme.surfaceContainerHighest, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(2.50), + ), + ), ), - ], + ), + ), + ), + Expanded( + child: buildOption(), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: FilledButton( + onPressed: logic.saveFontScale, + child: const Text('应用'), ), ), ], - ) - ], - ), - ), - persistentFooterButtons: [ - FloatingActionButton( - onPressed: () { - logic.saveFontScale(); - }, - child: const Icon(Icons.check), - ) - ], + ), + ), + ); + }), ); }, ); diff --git a/lib/pages/home/diary/diary_logic.dart b/lib/pages/home/diary/diary_logic.dart index 6535d43..b196c52 100644 --- a/lib/pages/home/diary/diary_logic.dart +++ b/lib/pages/home/diary/diary_logic.dart @@ -203,4 +203,10 @@ class DiaryLogic extends GetxController with GetTickerProviderStateMixin { Future toTop() async { await state.innerController.animateTo(0.0, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut); } + + // 更新标题 + void updateTitle() { + state.customTitleName = PrefUtil.getValue('customTitleName')!; + update(['Title']); + } } diff --git a/lib/pages/home/setting/setting_logic.dart b/lib/pages/home/setting/setting_logic.dart index 82a14e7..07c1aba 100644 --- a/lib/pages/home/setting/setting_logic.dart +++ b/lib/pages/home/setting/setting_logic.dart @@ -4,9 +4,9 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:mood_diary/components/dashboard/dashboard_logic.dart'; +import 'package:mood_diary/pages/home/diary/diary_logic.dart'; import 'package:mood_diary/pages/home/home_logic.dart'; import 'package:mood_diary/router/app_routes.dart'; -import 'package:mood_diary/utils/theme_util.dart'; import '../../../utils/data/pref.dart'; import '../../../utils/file_util.dart'; @@ -134,16 +134,7 @@ class SettingLogic extends GetxController { await PrefUtil.setValue('customTitleName', textEditingController.text); Get.backLegacy(); textEditingController.clear(); - NoticeUtil.showToast('重启应用后生效'); + Bind.find().updateTitle(); } } - - //更改字体 - Future changeFontTheme(int value) async { - Get.backLegacy(); - await PrefUtil.setValue('fontTheme', value); - state.fontTheme.value = value; - Get.changeTheme(ThemeUtil.buildTheme(Brightness.light)); - Get.changeTheme(ThemeUtil.buildTheme(Brightness.dark)); - } } diff --git a/lib/pages/home/setting/setting_view.dart b/lib/pages/home/setting/setting_view.dart index 5ebf52c..1af22fe 100644 --- a/lib/pages/home/setting/setting_view.dart +++ b/lib/pages/home/setting/setting_view.dart @@ -204,82 +204,13 @@ class SettingPage extends StatelessWidget { }, ), ListTile( - title: Text(l10n.settingFontSize), + title: Text(l10n.settingFontStyle), leading: const Icon(Icons.format_size_outlined), trailing: const Icon(Icons.chevron_right), onTap: () { logic.toFontSizePage(); }, ), - // ListTile( - // title: Text(l10n.settingFontStyle), - // leading: const Icon(Icons.text_format_outlined), - // trailing: Obx(() { - // return Text( - // switch (state.fontTheme.value) { - // 0 => '思源黑体', - // 1 => '思源宋体', - // int() => throw UnimplementedError(), - // }, - // style: textStyle.bodySmall!.copyWith( - // color: colorScheme.primary, - // ), - // ); - // }), - // onTap: () { - // showDialog( - // context: context, - // builder: (context) { - // return Obx(() { - // return SimpleDialog( - // title: Text(l10n.settingFontStyle), - // children: [ - // SimpleDialogOption( - // child: Row( - // children: [ - // const Text( - // '思源黑体', - // style: - // TextStyle(fontFamily: 'NotoSans SC', fontFamilyFallback: ['NotoSans SC']), - // ), - // const SizedBox( - // width: 10, - // ), - // if (state.fontTheme.value == 0) ...[ - // const Icon(Icons.check), - // ] - // ], - // ), - // onPressed: () { - // logic.changeFontTheme(0); - // }, - // ), - // SimpleDialogOption( - // child: Row( - // children: [ - // const Text( - // '思源宋体', - // style: - // TextStyle(fontFamily: 'NotoSerif SC', fontFamilyFallback: ['NotoSerif SC']), - // ), - // const SizedBox( - // width: 10, - // ), - // if (state.fontTheme.value == 1) ...[ - // const Icon(Icons.check), - // ] - // ], - // ), - // onPressed: () { - // logic.changeFontTheme(1); - // }, - // ), - // ], - // ); - // }); - // }); - // }, - // ), ListTile( title: const Text('自定义首页名称'), leading: const Icon(Icons.drive_file_rename_outline), @@ -457,8 +388,6 @@ class SettingPage extends StatelessWidget { Expanded( child: ListView( cacheExtent: size.height * 2, - addAutomaticKeepAlives: false, - addRepaintBoundaries: false, padding: const EdgeInsets.all(4.0), children: [ buildDashboard(), diff --git a/lib/src/rust/api/compress.dart b/lib/src/rust/api/compress.dart index 6b2d59b..e7e9b30 100644 --- a/lib/src/rust/api/compress.dart +++ b/lib/src/rust/api/compress.dart @@ -3,10 +3,9 @@ // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - import '../frb_generated.dart'; import 'constants.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These functions are ignored because they are not marked as `pub`: `calculate_target_dimensions`, `load_image` @@ -24,8 +23,11 @@ abstract class DynamicImage implements RustOpaqueInterface {} // Rust type: RustOpaqueMoi> abstract class ImageCompress implements RustOpaqueInterface { - static Future contain( - {required String filePath, CompressFormat? compressFormat, int? maxWidth, int? maxHeight, int? quality}) => + static Future contain({required String filePath, + CompressFormat? compressFormat, + int? maxWidth, + int? maxHeight, + int? quality}) => RustLib.instance.api.crateApiCompressImageCompressContain( filePath: filePath, compressFormat: compressFormat, diff --git a/lib/src/rust/api/constants.dart b/lib/src/rust/api/constants.dart index 0d68c66..fb5f738 100644 --- a/lib/src/rust/api/constants.dart +++ b/lib/src/rust/api/constants.dart @@ -3,9 +3,8 @@ // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - import '../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_receiver_is_total_eq`, `eq` diff --git a/lib/src/rust/api/font.dart b/lib/src/rust/api/font.dart new file mode 100644 index 0000000..37b711d --- /dev/null +++ b/lib/src/rust/api/font.dart @@ -0,0 +1,13 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.7.0. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +// Rust type: RustOpaqueMoi> +abstract class FontReader implements RustOpaqueInterface { + static Future getFontNameFromTtf({required String ttfFilePath}) => + RustLib.instance.api.crateApiFontFontReaderGetFontNameFromTtf(ttfFilePath: ttfFilePath); +} diff --git a/lib/src/rust/api/kmp.dart b/lib/src/rust/api/kmp.dart index f4b617c..10e1372 100644 --- a/lib/src/rust/api/kmp.dart +++ b/lib/src/rust/api/kmp.dart @@ -3,9 +3,8 @@ // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - import '../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; Future buildPrefixTable({required List pattern}) => RustLib.instance.api.crateApiKmpBuildPrefixTable(pattern: pattern); diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 02b0bf0..096b519 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -3,16 +3,15 @@ // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - import 'api/compress.dart'; import 'api/constants.dart'; +import 'api/font.dart'; import 'api/kmp.dart'; +import 'dart:async'; +import 'dart:convert'; import 'frb_generated.dart'; import 'frb_generated.io.dart' if (dart.library.js_interop) 'frb_generated.web.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; /// Main entrypoint of the Rust API class RustLib extends BaseEntrypoint { @@ -66,7 +65,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.7.0'; @override - int get rustContentHash => 444186734; + int get rustContentHash => -1743857995; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( stem: 'rust_lib_mood_diary', @@ -76,8 +75,13 @@ class RustLib extends BaseEntrypoint { } abstract class RustLibApi extends BaseApi { - Future crateApiCompressImageCompressContain( - {required String filePath, CompressFormat? compressFormat, int? maxWidth, int? maxHeight, int? quality}); + Future crateApiFontFontReaderGetFontNameFromTtf({required String ttfFilePath}); + + Future crateApiCompressImageCompressContain({required String filePath, + CompressFormat? compressFormat, + int? maxWidth, + int? maxHeight, + int? quality}); Future> crateApiKmpKmpFindMatches({required String text, required List patterns}); @@ -100,6 +104,12 @@ abstract class RustLibApi extends BaseApi { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DynamicImagePtr; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_FontReader; + + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_FontReader; + + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_FontReaderPtr; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_ImageCompress; RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_ImageCompress; @@ -122,8 +132,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }); @override - Future crateApiCompressImageCompressContain( - {required String filePath, CompressFormat? compressFormat, int? maxWidth, int? maxHeight, int? quality}) { + Future crateApiFontFontReaderGetFontNameFromTtf({required String ttfFilePath}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(ttfFilePath, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 1, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: null, + ), + constMeta: kCrateApiFontFontReaderGetFontNameFromTtfConstMeta, + argValues: [ttfFilePath], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiFontFontReaderGetFontNameFromTtfConstMeta => const TaskConstMeta( + debugName: "FontReader_get_font_name_from_ttf", + argNames: ["ttfFilePath"], + ); + + @override + Future crateApiCompressImageCompressContain({required String filePath, + CompressFormat? compressFormat, + int? maxWidth, + int? maxHeight, + int? quality}) { return handler.executeNormal(NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); @@ -132,7 +168,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_i_32(maxWidth, serializer); sse_encode_opt_box_autoadd_i_32(maxHeight, serializer); sse_encode_opt_box_autoadd_u_8(quality, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 1, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 2, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -156,7 +192,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(text, serializer); sse_encode_list_String(patterns, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 2, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 3, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -180,7 +216,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(text, serializer); sse_encode_Map_String_String(replacements, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 3, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 4, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -203,7 +239,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_Char(pattern, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 4, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 5, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_usize_strict, @@ -235,7 +271,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(dstWidth, serializer); sse_encode_compress_format(compressFormat, serializer); sse_encode_u_8(quality, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 5, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 6, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -259,7 +295,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(text, serializer); sse_encode_String(pattern, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 6, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 7, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_usize_strict, @@ -282,6 +318,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_DynamicImage => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_FontReader => + wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader; + + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_FontReader => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_ImageCompress => wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress; @@ -300,6 +342,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return AnyhowException(raw as String); } + @protected + FontReader dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return FontReaderImpl.frbInternalDcoDecode(raw as List); + } + @protected ImageCompress dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( dynamic raw) { @@ -338,6 +387,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return DynamicImageImpl.frbInternalDcoDecode(raw as List); } + @protected + FontReader dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return FontReaderImpl.frbInternalDcoDecode(raw as List); + } + @protected ImageCompress dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -416,6 +471,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (raw as List).map(dco_decode_record_string_string).toList(); } + @protected + String? dco_decode_opt_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_String(raw); + } + @protected CompressFormat? dco_decode_opt_box_autoadd_compress_format(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -478,6 +539,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return AnyhowException(inner); } + @protected + FontReader sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return FontReaderImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + @protected ImageCompress sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( SseDeserializer deserializer) { @@ -520,6 +588,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return DynamicImageImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } + @protected + FontReader sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return FontReaderImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + @protected ImageCompress sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( SseDeserializer deserializer) { @@ -621,6 +696,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + String? sse_decode_opt_String(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_String(deserializer)); + } else { + return null; + } + } + @protected CompressFormat? sse_decode_opt_box_autoadd_compress_format(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -697,6 +783,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.message, serializer); } + @protected + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + FontReader self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize((self as FontReaderImpl).frbInternalSseEncode(move: true), serializer); + } + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ImageCompress self, SseSerializer serializer) { @@ -737,6 +830,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_usize((self as DynamicImageImpl).frbInternalSseEncode(move: null), serializer); } + @protected + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + FontReader self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize((self as FontReaderImpl).frbInternalSseEncode(move: null), serializer); + } + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ImageCompress self, SseSerializer serializer) { @@ -828,6 +928,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_String(String? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_String(self, serializer); + } + } + @protected void sse_encode_opt_box_autoadd_compress_format(CompressFormat? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -911,6 +1021,22 @@ class DynamicImageImpl extends RustOpaque implements DynamicImage { ); } +@sealed +class FontReaderImpl extends RustOpaque implements FontReader { + // Not to be used by end users + FontReaderImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); + + // Not to be used by end users + FontReaderImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + + static final _kStaticData = RustArcStaticData( + rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_FontReader, + rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_FontReader, + rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_FontReaderPtr, + ); +} + @sealed class ImageCompressImpl extends RustOpaque implements ImageCompress { // Not to be used by end users diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 211a9cf..b8840d7 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -3,16 +3,15 @@ // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field -import 'dart:async'; -import 'dart:convert'; -import 'dart:ffi' as ffi; - -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; - import 'api/compress.dart'; import 'api/constants.dart'; +import 'api/font.dart'; import 'api/kmp.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'dart:ffi' as ffi; import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; abstract class RustLibApiImplPlatform extends BaseApiImpl { RustLibApiImplPlatform({ @@ -25,6 +24,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DynamicImagePtr => wire ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImagePtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_FontReaderPtr => + wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReaderPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_ImageCompressPtr => wire ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompressPtr; @@ -34,6 +36,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException dco_decode_AnyhowException(dynamic raw); + @protected + FontReader dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + dynamic raw); + @protected ImageCompress dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( dynamic raw); @@ -54,6 +60,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected DynamicImage dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage(dynamic raw); + @protected + FontReader dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader(dynamic raw); + @protected ImageCompress dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress(dynamic raw); @@ -93,6 +102,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List<(String, String)> dco_decode_list_record_string_string(dynamic raw); + @protected + String? dco_decode_opt_String(dynamic raw); + @protected CompressFormat? dco_decode_opt_box_autoadd_compress_format(dynamic raw); @@ -120,6 +132,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); + @protected + FontReader sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + SseDeserializer deserializer); + @protected ImageCompress sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( SseDeserializer deserializer); @@ -142,6 +158,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { DynamicImage sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage( SseDeserializer deserializer); + @protected + FontReader sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + SseDeserializer deserializer); + @protected ImageCompress sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( SseDeserializer deserializer); @@ -182,6 +202,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List<(String, String)> sse_decode_list_record_string_string(SseDeserializer deserializer); + @protected + String? sse_decode_opt_String(SseDeserializer deserializer); + @protected CompressFormat? sse_decode_opt_box_autoadd_compress_format(SseDeserializer deserializer); @@ -212,6 +235,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_AnyhowException(AnyhowException self, SseSerializer serializer); + @protected + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + FontReader self, SseSerializer serializer); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ImageCompress self, SseSerializer serializer); @@ -234,6 +261,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage( DynamicImage self, SseSerializer serializer); + @protected + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + FontReader self, SseSerializer serializer); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ImageCompress self, SseSerializer serializer); @@ -274,6 +305,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_record_string_string(List<(String, String)> self, SseSerializer serializer); + @protected + void sse_encode_opt_String(String? self, SseSerializer serializer); + @protected void sse_encode_opt_box_autoadd_compress_format(CompressFormat? self, SseSerializer serializer); @@ -343,6 +377,36 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImagePtr .asFunction)>(); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ffi.Pointer ptr, + ) { + return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ptr, + ); + } + + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReaderPtr = + _lookup)>>( + 'frbgen_mood_diary_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader'); + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader = + _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReaderPtr + .asFunction)>(); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ffi.Pointer ptr, + ) { + return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ptr, + ); + } + + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReaderPtr = + _lookup)>>( + 'frbgen_mood_diary_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader'); + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader = + _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReaderPtr + .asFunction)>(); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ffi.Pointer ptr, ) { diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 4f1c489..a891205 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -6,15 +6,14 @@ // Static analysis wrongly picks the IO variant, thus ignore this // ignore_for_file: argument_type_not_assignable -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart'; - import 'api/compress.dart'; import 'api/constants.dart'; +import 'api/font.dart'; import 'api/kmp.dart'; +import 'dart:async'; +import 'dart:convert'; import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart'; abstract class RustLibApiImplPlatform extends BaseApiImpl { RustLibApiImplPlatform({ @@ -27,6 +26,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DynamicImagePtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_FontReaderPtr => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_ImageCompressPtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress; @@ -36,6 +38,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException dco_decode_AnyhowException(dynamic raw); + @protected + FontReader dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + dynamic raw); + @protected ImageCompress dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( dynamic raw); @@ -56,6 +62,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected DynamicImage dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage(dynamic raw); + @protected + FontReader dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader(dynamic raw); + @protected ImageCompress dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress(dynamic raw); @@ -95,6 +104,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List<(String, String)> dco_decode_list_record_string_string(dynamic raw); + @protected + String? dco_decode_opt_String(dynamic raw); + @protected CompressFormat? dco_decode_opt_box_autoadd_compress_format(dynamic raw); @@ -122,6 +134,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); + @protected + FontReader sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + SseDeserializer deserializer); + @protected ImageCompress sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( SseDeserializer deserializer); @@ -144,6 +160,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { DynamicImage sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage( SseDeserializer deserializer); + @protected + FontReader sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + SseDeserializer deserializer); + @protected ImageCompress sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( SseDeserializer deserializer); @@ -184,6 +204,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List<(String, String)> sse_decode_list_record_string_string(SseDeserializer deserializer); + @protected + String? sse_decode_opt_String(SseDeserializer deserializer); + @protected CompressFormat? sse_decode_opt_box_autoadd_compress_format(SseDeserializer deserializer); @@ -214,6 +237,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_AnyhowException(AnyhowException self, SseSerializer serializer); + @protected + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + FontReader self, SseSerializer serializer); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ImageCompress self, SseSerializer serializer); @@ -236,6 +263,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage( DynamicImage self, SseSerializer serializer); + @protected + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + FontReader self, SseSerializer serializer); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ImageCompress self, SseSerializer serializer); @@ -276,6 +307,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_record_string_string(List<(String, String)> self, SseSerializer serializer); + @protected + void sse_encode_opt_String(String? self, SseSerializer serializer); + @protected void sse_encode_opt_box_autoadd_compress_format(CompressFormat? self, SseSerializer serializer); @@ -321,6 +355,18 @@ class RustLibWire implements BaseWire { .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage( ptr); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + int ptr) => + wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + int ptr) => + wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ptr); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( int ptr) => wasmModule @@ -354,6 +400,12 @@ extension type RustLibWasmModule._(JSObject _) implements JSObject { rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDynamicImage( int ptr); + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader(int ptr); + + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader(int ptr); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( int ptr); diff --git a/lib/utils/data/pref.dart b/lib/utils/data/pref.dart index 85b8dec..d6d5039 100644 --- a/lib/utils/data/pref.dart +++ b/lib/utils/data/pref.dart @@ -85,6 +85,8 @@ class PrefUtil { 'showWritingTime', // 展示字数统计 'showWordCount', + // 自定义字体 + 'customFont', }; static Future initPref() async { @@ -180,6 +182,7 @@ class PrefUtil { await _prefs.setBool('autoCategory', _prefs.getBool('autoCategory') ?? false); await _prefs.setBool('showWritingTime', _prefs.getBool('showWritingTime') ?? true); await _prefs.setBool('showWordCount', _prefs.getBool('showWordCount') ?? true); + await _prefs.setString('customFont', _prefs.getString('customFont') ?? ''); } static Future setValue(String key, T value) async { diff --git a/lib/utils/file_util.dart b/lib/utils/file_util.dart index 675aab0..ff8f9af 100644 --- a/lib/utils/file_util.dart +++ b/lib/utils/file_util.dart @@ -48,6 +48,9 @@ class FileUtil { await createDir(join(_filePath, 'image')); await createDir(join(_filePath, 'audio')); await createDir(join(_filePath, 'video')); + + // 字体文件夹 + await createDir(join(_filePath, 'font')); } static Future createDir(String path) async { diff --git a/lib/utils/theme_util.dart b/lib/utils/theme_util.dart index 845f378..8450b97 100644 --- a/lib/utils/theme_util.dart +++ b/lib/utils/theme_util.dart @@ -5,6 +5,7 @@ import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/internal.dart'; import 'package:mood_diary/common/values/colors.dart'; +import '../src/rust/api/font.dart'; import 'data/pref.dart'; class ThemeUtil { @@ -16,7 +17,7 @@ class ThemeUtil { return Color((await DynamicColorPlugin.getCorePalette())!.primary.get(40)); } - static ThemeData buildTheme(Brightness brightness) { + static Future buildTheme(Brightness brightness) async { final color = PrefUtil.getValue('color'); var seedColor = switch (color) { 0 => AppColor.themeColorList[0], @@ -24,63 +25,52 @@ class ThemeUtil { 2 => AppColor.themeColorList[2], 3 => AppColor.themeColorList[3], 4 => AppColor.themeColorList[4], - // -1为系统配色,如果选了-1,肯定有 _ => Color(PrefUtil.getValue('systemColor')!) }; - // 添加 fontVariations 的函数 - TextTheme addFontVariationsToTextTheme(TextTheme baseTheme) { + final customFont = PrefUtil.getValue('customFont')!; + String? fontFamily; + + // 加载自定义字体 + if (customFont.isNotEmpty) { + fontFamily = await FontReader.getFontNameFromTtf(ttfFilePath: customFont); + if (fontFamily != null) { + await DynamicFont.file(fontFamily: fontFamily, filepath: customFont).load(); + } + } + // 字体变体应用到 TextTheme 的函数 + TextTheme applyFontVariations(TextTheme baseTheme, String? fontFamily) { + const fontVariation = FontVariation('wght', 400); return baseTheme.copyWith( - displayLarge: baseTheme.displayLarge?.copyWith( - fontVariations: [const FontVariation('wght', 400)], - ), - displayMedium: baseTheme.displayMedium?.copyWith( - fontVariations: [const FontVariation('wght', 400)], - ), - displaySmall: baseTheme.displaySmall?.copyWith( - fontVariations: [const FontVariation('wght', 400)], - ), - headlineLarge: baseTheme.headlineLarge?.copyWith( - fontVariations: [const FontVariation('wght', 500)], - ), - headlineMedium: baseTheme.headlineMedium?.copyWith( - fontVariations: [const FontVariation('wght', 500)], - ), - headlineSmall: baseTheme.headlineSmall?.copyWith( - fontVariations: [const FontVariation('wght', 500)], - ), - titleLarge: baseTheme.titleLarge?.copyWith( - fontVariations: [const FontVariation('wght', 600)], - ), - titleMedium: baseTheme.titleMedium?.copyWith( - fontVariations: [const FontVariation('wght', 500)], - ), - titleSmall: baseTheme.titleSmall?.copyWith( - fontVariations: [const FontVariation('wght', 400)], - ), - bodyLarge: baseTheme.bodyLarge?.copyWith( - fontVariations: [const FontVariation('wght', 400)], - ), - bodyMedium: baseTheme.bodyMedium?.copyWith( - fontVariations: [const FontVariation('wght', 400)], - ), - bodySmall: baseTheme.bodySmall?.copyWith( - fontVariations: [const FontVariation('wght', 300)], - ), - labelLarge: baseTheme.labelLarge?.copyWith( - fontVariations: [const FontVariation('wght', 500)], - ), - labelMedium: baseTheme.labelMedium?.copyWith( - fontVariations: [const FontVariation('wght', 400)], - ), - labelSmall: baseTheme.labelSmall?.copyWith( - fontVariations: [const FontVariation('wght', 300)], - ), + displayLarge: baseTheme.displayLarge?.copyWith(fontFamily: fontFamily, fontVariations: [fontVariation]), + displayMedium: baseTheme.displayMedium?.copyWith(fontFamily: fontFamily, fontVariations: [fontVariation]), + displaySmall: baseTheme.displaySmall?.copyWith(fontFamily: fontFamily, fontVariations: [fontVariation]), + headlineLarge: baseTheme.headlineLarge + ?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 500)]), + headlineMedium: baseTheme.headlineMedium + ?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 500)]), + headlineSmall: baseTheme.headlineSmall + ?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 500)]), + titleLarge: + baseTheme.titleLarge?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 600)]), + titleMedium: + baseTheme.titleMedium?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 500)]), + titleSmall: + baseTheme.titleSmall?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 400)]), + bodyLarge: baseTheme.bodyLarge?.copyWith(fontFamily: fontFamily, fontVariations: [fontVariation]), + bodyMedium: baseTheme.bodyMedium?.copyWith(fontFamily: fontFamily, fontVariations: [fontVariation]), + bodySmall: + baseTheme.bodySmall?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 300)]), + labelLarge: + baseTheme.labelLarge?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 500)]), + labelMedium: baseTheme.labelMedium?.copyWith(fontFamily: fontFamily, fontVariations: [fontVariation]), + labelSmall: + baseTheme.labelSmall?.copyWith(fontFamily: fontFamily, fontVariations: [const FontVariation('wght', 300)]), ); } - // 创建基础的 ThemeData - var themeData = ThemeData( + // 基础主题 + return ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: seedColor, brightness: brightness, @@ -88,10 +78,11 @@ class ThemeUtil { ), materialTapTargetSize: MaterialTapTargetSize.padded, brightness: brightness, + textTheme: applyFontVariations( + brightness == Brightness.light ? Typography.material2021().black : Typography.material2021().white, + fontFamily, + ), ); - - // 使用系统中文字体的扩展 - return themeData.useSystemChineseFont(brightness); } static DefaultStyles getInstance(BuildContext context) { diff --git a/pubspec.lock b/pubspec.lock index 277b26e..b751ece 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -282,10 +282,10 @@ packages: dependency: transitive description: name: built_value - sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2" url: "https://pub.flutter-io.cn" source: hosted - version: "8.9.2" + version: "8.9.3" cached_network_image: dependency: "direct main" description: @@ -574,6 +574,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" + fading_edge_scrollview: + dependency: transitive + description: + name: fading_edge_scrollview + sha256: "1f84fe3ea8e251d00d5735e27502a6a250e4aa3d3b330d3fdcb475af741464ef" + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.1.1" fake_async: dependency: transitive description: @@ -666,10 +674,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: "74959b99b92b9eebeed1a4049426fd67c4abc3c5a0f4d12e2877097d6a11ae08" + sha256: c724234b05e378383e958f3e82ca84a3e1e3c06a0898462044dd8a24b1ee9864 url: "https://pub.flutter-io.cn" source: hosted - version: "0.69.2" + version: "0.70.0" flat_buffers: dependency: transitive description: @@ -892,26 +900,26 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398" + sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e" url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.23" + version: "2.0.24" flutter_quill: dependency: "direct main" description: name: flutter_quill - sha256: "97ca7ecf6177c45c171f4efa19bc5ea684bba43c53d973fbc8f38453ac5bd747" + sha256: eccdd58b650b055d7b42d69a43d93d0044b87e97b5a74ae37ea0abf8b256e0b8 url: "https://pub.flutter-io.cn" source: hosted - version: "11.0.0-dev.16" + version: "11.0.0-dev.17" flutter_quill_delta_from_html: dependency: transitive description: name: flutter_quill_delta_from_html - sha256: "63873b5391b56daa999ce8fa7dd23dfd7d0417a70e00a647ba450f4a8988afd0" + sha256: "3809961f59b323e3ff368921c8f4a2ae559ff05a6bd132e565d7e6180db868e8" url: "https://pub.flutter-io.cn" source: hosted - version: "1.4.3" + version: "1.4.5" flutter_quill_extensions: dependency: "direct main" description: @@ -1062,10 +1070,10 @@ packages: dependency: transitive description: name: gotrue - sha256: b9541c62edc0ee1fddf2c95364251b8076a93bcdbc3ad27f14a633d187e89ccc + sha256: d6362dff9a54f8c1c372bb137c858b4024c16407324d34e6473e59623c9b9f50 url: "https://pub.flutter-io.cn" source: hosted - version: "2.11.0" + version: "2.11.1" graphs: dependency: transitive description: @@ -1294,10 +1302,10 @@ packages: dependency: transitive description: name: lints - sha256: "4a16b3f03741e1252fda5de3ce712666d010ba2122f8e912c94f9f7b90e1a4c3" + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 url: "https://pub.flutter-io.cn" source: hosted - version: "5.1.0" + version: "5.1.1" lists: dependency: transitive description: @@ -1394,6 +1402,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.3.2+6" + marquee: + dependency: "direct main" + description: + name: marquee + sha256: a87e7e80c5d21434f90ad92add9f820cf68be374b226404fe881d2bba7be0862 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.0" matcher: dependency: transitive description: @@ -1798,10 +1814,10 @@ packages: dependency: transitive description: name: pubspec_parse - sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.0" + version: "1.4.0" quill_native_bridge: dependency: transitive description: @@ -1878,10 +1894,10 @@ packages: dependency: transitive description: name: realtime_client - sha256: "173c3dc40922bb0ae19a558ae1a0acf7b28ec8a458b54390c499bbe5ff15f049" + sha256: "1bfcb7455fdcf15953bf18ac2817634ea5b8f7f350c7e8c9873141a3ee2c3e9c" url: "https://pub.flutter-io.cn" source: hosted - version: "2.4.0" + version: "2.4.1" record: dependency: "direct main" description: @@ -2078,10 +2094,10 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "95f9997ca1fb9799d494d0cb2a780fd7be075818d59f00c43832ed112b158a82" + sha256: "3c7e73920c694a436afaf65ab60ce3453d91f84208d761fbd83fc21182134d93" url: "https://pub.flutter-io.cn" source: hosted - version: "2.3.3" + version: "2.3.4" shared_preferences_android: dependency: transitive description: @@ -2259,10 +2275,10 @@ packages: dependency: transitive description: name: storage_client - sha256: "833666edcd804aaf434f3b13165fd553a8c6371a488618a58be8914856795c04" + sha256: d80d34f0aa60e5199646bc301f5750767ee37310c2ecfe8d4bbdd29351e09ab0 url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.0" + version: "2.3.0" stream_channel: dependency: transitive description: @@ -2291,34 +2307,34 @@ packages: dependency: transitive description: name: supabase - sha256: ecdfb226c483f05fd10425304de744144dfdda2f33d14151d2604cebe8c6d077 + sha256: ea3daaf4fc76df9bf42ca00142f8d07b94400943a93d563e87f5575ea78f1c2c url: "https://pub.flutter-io.cn" source: hosted - version: "2.6.0" + version: "2.6.1" supabase_flutter: dependency: "direct main" description: name: supabase_flutter - sha256: bdbc6770e0e91db0b9d931f41ea4ee311d8819f539743f47e8cc795b492be75a + sha256: e8b321706a9b88c60f5fe695305f34917ad2ee55aea0b3af987638c7b0793e13 url: "https://pub.flutter-io.cn" source: hosted - version: "2.8.1" + version: "2.8.2" syncfusion_flutter_core: dependency: transitive description: name: syncfusion_flutter_core - sha256: b1071c698b502e7d55f91352a8b82d42f49f4c96e523d43b6fade5d5af710048 + sha256: f6d1e8c08361aed6fb7f7b6f327cbd190464e1c717c6152d59866b2f0bb90ffd url: "https://pub.flutter-io.cn" source: hosted - version: "28.1.33" + version: "28.1.35" syncfusion_flutter_sliders: dependency: "direct main" description: name: syncfusion_flutter_sliders - sha256: c5978a10c5b97e982e59ca485de86673e0d3a67ea34e2245c7f7fdf9109cbc5f + sha256: "1851f23464d6e76ef3320a6c005ce40d2684aff8d93fa0bf77d722e9af2c1f8e" url: "https://pub.flutter-io.cn" source: hosted - version: "28.1.33" + version: "28.1.35" synchronized: dependency: transitive description: @@ -2579,18 +2595,18 @@ packages: dependency: transitive description: name: wakelock_plus - sha256: bf4ee6f17a2fa373ed3753ad0e602b7603f8c75af006d5b9bdade263928c0484 + sha256: "36c88af0b930121941345306d259ec4cc4ecca3b151c02e3a9e71aede83c615e" url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.8" + version: "1.2.10" wakelock_plus_platform_interface: dependency: transitive description: name: wakelock_plus_platform_interface - sha256: "422d1cdbb448079a8a62a5a770b69baa489f8f7ca21aef47800c726d404f9d16" + sha256: "70e780bc99796e1db82fe764b1e7dcb89a86f1e5b3afb1db354de50f2e41eb7a" url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "1.2.2" watcher: dependency: transitive description: @@ -2683,10 +2699,10 @@ packages: dependency: transitive description: name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce url: "https://pub.flutter-io.cn" source: hosted - version: "3.1.2" + version: "3.1.3" yet_another_json_isolate: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3cdb3fe..c58ad3b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: logger: 2.5.0 flutter_drawing_board: 0.9.5 flutter_displaymode: 0.6.0 - fl_chart: 0.69.2 + fl_chart: 0.70.0 file_picker: 8.1.6 local_auth: 2.3.0 local_auth_android: 1.0.46 @@ -27,7 +27,7 @@ dependencies: photo_view: 0.15.0 package_info_plus: 8.1.2 uuid: 4.5.1 - flutter_quill: 11.0.0-dev.16 + flutter_quill: 11.0.0-dev.17 share_plus: 10.1.3 url_launcher: 6.3.1 archive: 3.6.1 @@ -35,7 +35,7 @@ dependencies: markdown_widget: 2.3.2+6 flutter_colorpicker: 1.1.0 geolocator: 13.0.2 - shared_preferences: 2.3.3 + shared_preferences: 2.3.4 isar: 4.0.0-dev.14 isar_flutter_libs: 4.0.0-dev.14 fluttertoast: 8.2.10 @@ -44,7 +44,7 @@ dependencies: record: 5.2.0 duration: 4.0.3 dynamic_color: 1.7.0 - supabase_flutter: 2.8.1 + supabase_flutter: 2.8.2 bitsdojo_window: 0.1.6 intl: 0.19.0 collection: 1.19.0 @@ -73,7 +73,7 @@ dependencies: objectbox: 4.0.3 faker: 2.2.0 flutter_rust_bridge: 2.7.0 - syncfusion_flutter_sliders: 28.1.33 + syncfusion_flutter_sliders: 28.1.35 flutter_quill_extensions: 11.0.0-dev.7 connectivity_plus: 6.1.1 image_picker_android: 0.8.12+18 @@ -99,6 +99,7 @@ dependencies: ref: feature/add-new-component network_info_plus: 6.1.2 scrollable_positioned_list: 0.3.8 + marquee: 2.3.0 flutter_localizations: sdk: flutter rust_lib_mood_diary: diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 9c1102b..b202e4d 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arbitrary" @@ -104,9 +104,9 @@ checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "av1-grain" @@ -193,9 +193,9 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -211,12 +211,13 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cc" -version = "1.0.83" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -262,9 +263,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -281,9 +282,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -381,7 +382,7 @@ dependencies = [ "bit_field", "half", "lebe", - "miniz_oxide 0.8.0", + "miniz_oxide 0.8.2", "rayon-core", "smallvec", "zune-inflate", @@ -389,9 +390,9 @@ dependencies = [ [[package]] name = "fast_image_resize" -version = "5.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66a61fbfc84ef99a839499cf9e5a7c2951d2da874ea00f29ee938bc50d1b396" +checksum = "ec7890c03bc18abd95e18d972f6f8f19ecc792cc01f208f060b3764a672de9e2" dependencies = [ "bytemuck", "cfg-if", @@ -417,7 +418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide 0.8.2", ] [[package]] @@ -600,9 +601,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -663,9 +664,9 @@ checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -729,9 +730,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libfuzzer-sys" @@ -751,9 +752,9 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loop9" @@ -786,9 +787,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minimal-lexical" @@ -807,9 +808,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", "simd-adler32", @@ -957,7 +958,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.0", + "miniz_oxide 0.8.2", ] [[package]] @@ -1171,6 +1172,7 @@ dependencies = [ "fast_image_resize", "flutter_rust_bridge", "image", + "ttf-parser", ] [[package]] @@ -1181,18 +1183,18 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -1208,6 +1210,12 @@ dependencies = [ "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1240,9 +1248,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -1270,18 +1278,18 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "thiserror" -version = "1.0.55" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3de26b0965292219b4287ff031fcba86837900fe9cd2b34ea8ad893c0953d2" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.55" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "268026685b2be38d7103e9e507c938a1fcb3d7e6eb15e87870b617bf37b6d581" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -1353,6 +1361,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + [[package]] name = "typenum" version = "1.17.0" @@ -1361,9 +1375,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "v_frame" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 03e6261..6b97be8 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["cdylib", "staticlib"] [dependencies] flutter_rust_bridge = "=2.7.0" image = "0.25.5" -fast_image_resize = { version = "5.0.0", features = ["image"] } -anyhow = "1.0.93" -bytemuck = "1.16.3" +fast_image_resize = { version = "5.1.0", features = ["image"] } +anyhow = "1.0.94" +bytemuck = "1.21.0" +ttf-parser = "0.25.1" diff --git a/rust/src/api/font.rs b/rust/src/api/font.rs new file mode 100644 index 0000000..e71606c --- /dev/null +++ b/rust/src/api/font.rs @@ -0,0 +1,28 @@ +use flutter_rust_bridge::frb; +use std::fs::File; +use std::io::Read; +use ttf_parser::{name_id, Face}; + +#[frb(opaque)] +pub struct FontReader; + +impl FontReader { + pub fn get_font_name_from_ttf(ttf_file_path: String) -> Option { + let file = File::open(ttf_file_path); + match file { + Ok(mut f) => { + let mut data = Vec::new(); + if f.read_to_end(&mut data).is_ok() { + let font = Face::parse(&data, 0).ok()?; + font.names() + .into_iter() + .find(|name| name.name_id == name_id::FULL_NAME && name.is_unicode()) + .and_then(|name| name.to_string()) + } else { + None + } + } + Err(_) => None, + } + } +} diff --git a/rust/src/api/mod.rs b/rust/src/api/mod.rs index 883b255..c58c7a0 100644 --- a/rust/src/api/mod.rs +++ b/rust/src/api/mod.rs @@ -1,3 +1,4 @@ pub mod compress; pub mod constants; -pub mod kmp; \ No newline at end of file +pub mod kmp; +pub mod font; \ No newline at end of file diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 478f1e8..16f34a7 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -26,11 +26,12 @@ // Section: imports use crate::api::compress::*; +use crate::api::font::*; use crate::api::kmp::*; use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; use flutter_rust_bridge::{Handler, IntoIntoDart}; - +use image::DynamicImage; // Section: boilerplate flutter_rust_bridge::frb_generated_boilerplate!( @@ -39,7 +40,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.7.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 444186734; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1743857995; // Section: executor @@ -47,6 +48,41 @@ flutter_rust_bridge::frb_generated_default_handler!(); // Section: wire_funcs +fn wire__crate__api__font__FontReader_get_font_name_from_ttf_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "FontReader_get_font_name_from_ttf", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_ttf_file_path = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let output_ok = Result::<_, ()>::Ok( + crate::api::font::FontReader::get_font_name_from_ttf(api_ttf_file_path), + )?; + Ok(output_ok) + })()) + } + }, + ) +} fn wire__crate__api__compress__ImageCompress_contain_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -305,6 +341,9 @@ fn wire__crate__api__kmp__kmp_search_impl( flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); @@ -322,6 +361,16 @@ impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { } } +impl SseDecode for FontReader { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , + >>::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); + } +} + impl SseDecode for ImageCompress { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -366,6 +415,16 @@ impl SseDecode } } +impl SseDecode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return decode_rust_opaque_moi(inner); + } +} + impl SseDecode for RustOpaqueMoi> { @@ -472,6 +531,17 @@ impl SseDecode for Vec<(String, String)> { } } +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode(deserializer)); + } else { + return None; + } + } +} + impl SseDecode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -558,17 +628,23 @@ fn pde_ffi_dispatcher_primary_impl( ) { // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { - 1 => wire__crate__api__compress__ImageCompress_contain_impl( + 1 => wire__crate__api__font__FontReader_get_font_name_from_ttf_impl( port, ptr, rust_vec_len, data_len, ), - 2 => wire__crate__api__kmp__Kmp_find_matches_impl(port, ptr, rust_vec_len, data_len), - 3 => wire__crate__api__kmp__Kmp_replace_with_kmp_impl(port, ptr, rust_vec_len, data_len), - 4 => wire__crate__api__kmp__build_prefix_table_impl(port, ptr, rust_vec_len, data_len), - 5 => wire__crate__api__compress__compress_impl(port, ptr, rust_vec_len, data_len), - 6 => wire__crate__api__kmp__kmp_search_impl(port, ptr, rust_vec_len, data_len), + 2 => wire__crate__api__compress__ImageCompress_contain_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 3 => wire__crate__api__kmp__Kmp_find_matches_impl(port, ptr, rust_vec_len, data_len), + 4 => wire__crate__api__kmp__Kmp_replace_with_kmp_impl(port, ptr, rust_vec_len, data_len), + 5 => wire__crate__api__kmp__build_prefix_table_impl(port, ptr, rust_vec_len, data_len), + 6 => wire__crate__api__compress__compress_impl(port, ptr, rust_vec_len, data_len), + 7 => wire__crate__api__kmp__kmp_search_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -587,6 +663,21 @@ fn pde_ffi_dispatcher_sync_impl( // Section: rust2dart +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for FontReader { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + // Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { @@ -647,6 +738,13 @@ impl SseEncode for flutter_rust_bridge::for_generated::anyhow::Error { } } +impl SseEncode for FontReader { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); + } +} + impl SseEncode for ImageCompress { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -689,6 +787,17 @@ impl SseEncode } } +impl SseEncode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + let (ptr, size) = self.sse_encode_raw(); + ::sse_encode(ptr, serializer); + ::sse_encode(size, serializer); + } +} + impl SseEncode for RustOpaqueMoi> { @@ -790,6 +899,16 @@ impl SseEncode for Vec<(String, String)> { } } +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + impl SseEncode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -873,6 +992,7 @@ mod io { use super::*; use crate::api::compress::*; + use crate::api::font::*; use crate::api::kmp::*; use flutter_rust_bridge::for_generated::byteorder::{ NativeEndian, ReadBytesExt, WriteBytesExt, @@ -898,6 +1018,20 @@ mod io { MoiArc::>::decrement_strong_count(ptr as _); } + #[no_mangle] + pub extern "C" fn frbgen_mood_diary_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[no_mangle] + pub extern "C" fn frbgen_mood_diary_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[no_mangle] pub extern "C" fn frbgen_mood_diary_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ptr: *const std::ffi::c_void, @@ -926,7 +1060,6 @@ mod io { MoiArc::>::decrement_strong_count(ptr as _); } } -use image::DynamicImage; #[cfg(not(target_family = "wasm"))] pub use io::*; @@ -940,6 +1073,7 @@ mod web { use super::*; use crate::api::compress::*; + use crate::api::font::*; use crate::api::kmp::*; use flutter_rust_bridge::for_generated::byteorder::{ NativeEndian, ReadBytesExt, WriteBytesExt, @@ -967,6 +1101,20 @@ mod web { MoiArc::>::decrement_strong_count(ptr as _); } + #[wasm_bindgen] + pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[wasm_bindgen] + pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerFontReader( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[wasm_bindgen] pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerImageCompress( ptr: *const std::ffi::c_void,