From fa291f621746f7a6d3bbdda5d980aefc2695f94b Mon Sep 17 00:00:00 2001 From: Cierra_Runis <2864283875@qq.com> Date: Wed, 27 Sep 2023 15:50:13 +0800 Subject: [PATCH] =?UTF-8?q?Revise=F0=9F=93=96&=20Feature=F0=9F=8C=8D=201.?= =?UTF-8?q?=20=F0=9F=93=96Update=20packages=202.=20=F0=9F=8C=8DYou=20can?= =?UTF-8?q?=20add=20background=20image=20at=20Home=20Page=20now?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/database/config.dart | 2 + lib/database/config.g.dart | 214 +++++++++++++++++++++++++++++- lib/database/isar_service.dart | 6 +- lib/index.dart | 1 + lib/l10n/intl/messages_en.dart | 4 + lib/l10n/intl/messages_ja.dart | 2 + lib/l10n/intl/messages_zh_CN.dart | 2 + lib/l10n/intl_en.arb | 4 +- lib/l10n/intl_ja.arb | 4 +- lib/l10n/intl_zh_CN.arb | 4 +- lib/l10n/l10n.dart | 20 +++ lib/pages/home_page.dart | 29 +++- lib/pages/setting_page.dart | 39 +++++- pubspec.lock | 12 +- pubspec.yaml | 4 +- 15 files changed, 324 insertions(+), 23 deletions(-) diff --git a/lib/database/config.dart b/lib/database/config.dart index b8702fb4..42ca3b5c 100644 --- a/lib/database/config.dart +++ b/lib/database/config.dart @@ -12,4 +12,6 @@ class Config { /// 主题模式 (不可为空) @enumerated ThemeMode themeMode; + + String? backgroundImagePath; } diff --git a/lib/database/config.g.dart b/lib/database/config.g.dart index 61dec380..1446cef1 100644 --- a/lib/database/config.g.dart +++ b/lib/database/config.g.dart @@ -17,8 +17,13 @@ const ConfigSchema = CollectionSchema( name: r'Config', id: -3644000870443854999, properties: { - r'themeMode': PropertySchema( + r'backgroundImagePath': PropertySchema( id: 0, + name: r'backgroundImagePath', + type: IsarType.string, + ), + r'themeMode': PropertySchema( + id: 1, name: r'themeMode', type: IsarType.byte, enumMap: _ConfigthemeModeEnumValueMap, @@ -44,6 +49,12 @@ int _configEstimateSize( Map> allOffsets, ) { var bytesCount = offsets.last; + { + final value = object.backgroundImagePath; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } return bytesCount; } @@ -53,7 +64,8 @@ void _configSerialize( List offsets, Map> allOffsets, ) { - writer.writeByte(offsets[0], object.themeMode.index); + writer.writeString(offsets[0], object.backgroundImagePath); + writer.writeByte(offsets[1], object.themeMode.index); } Config _configDeserialize( @@ -64,9 +76,10 @@ Config _configDeserialize( ) { final object = Config( themeMode: - _ConfigthemeModeValueEnumMap[reader.readByteOrNull(offsets[0])] ?? + _ConfigthemeModeValueEnumMap[reader.readByteOrNull(offsets[1])] ?? ThemeMode.system, ); + object.backgroundImagePath = reader.readStringOrNull(offsets[0]); object.id = id; return object; } @@ -79,6 +92,8 @@ P _configDeserializeProp

( ) { switch (propertyId) { case 0: + return (reader.readStringOrNull(offset)) as P; + case 1: return (_ConfigthemeModeValueEnumMap[reader.readByteOrNull(offset)] ?? ThemeMode.system) as P; default: @@ -185,6 +200,160 @@ extension ConfigQueryWhere on QueryBuilder { } extension ConfigQueryFilter on QueryBuilder { + QueryBuilder + backgroundImagePathIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'backgroundImagePath', + )); + }); + } + + QueryBuilder + backgroundImagePathIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'backgroundImagePath', + )); + }); + } + + QueryBuilder + backgroundImagePathEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'backgroundImagePath', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + backgroundImagePathGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'backgroundImagePath', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + backgroundImagePathLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'backgroundImagePath', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + backgroundImagePathBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'backgroundImagePath', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + backgroundImagePathStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'backgroundImagePath', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + backgroundImagePathEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'backgroundImagePath', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + backgroundImagePathContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'backgroundImagePath', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + backgroundImagePathMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'backgroundImagePath', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + backgroundImagePathIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'backgroundImagePath', + value: '', + )); + }); + } + + QueryBuilder + backgroundImagePathIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'backgroundImagePath', + value: '', + )); + }); + } + QueryBuilder idEqualTo(Id value) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( @@ -296,6 +465,18 @@ extension ConfigQueryObject on QueryBuilder {} extension ConfigQueryLinks on QueryBuilder {} extension ConfigQuerySortBy on QueryBuilder { + QueryBuilder sortByBackgroundImagePath() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'backgroundImagePath', Sort.asc); + }); + } + + QueryBuilder sortByBackgroundImagePathDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'backgroundImagePath', Sort.desc); + }); + } + QueryBuilder sortByThemeMode() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'themeMode', Sort.asc); @@ -310,6 +491,18 @@ extension ConfigQuerySortBy on QueryBuilder { } extension ConfigQuerySortThenBy on QueryBuilder { + QueryBuilder thenByBackgroundImagePath() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'backgroundImagePath', Sort.asc); + }); + } + + QueryBuilder thenByBackgroundImagePathDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'backgroundImagePath', Sort.desc); + }); + } + QueryBuilder thenById() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'id', Sort.asc); @@ -336,6 +529,14 @@ extension ConfigQuerySortThenBy on QueryBuilder { } extension ConfigQueryWhereDistinct on QueryBuilder { + QueryBuilder distinctByBackgroundImagePath( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'backgroundImagePath', + caseSensitive: caseSensitive); + }); + } + QueryBuilder distinctByThemeMode() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'themeMode'); @@ -350,6 +551,13 @@ extension ConfigQueryProperty on QueryBuilder { }); } + QueryBuilder + backgroundImagePathProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'backgroundImagePath'); + }); + } + QueryBuilder themeModeProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'themeMode'); diff --git a/lib/database/isar_service.dart b/lib/database/isar_service.dart index 47bb6e8c..5e85e784 100644 --- a/lib/database/isar_service.dart +++ b/lib/database/isar_service.dart @@ -46,9 +46,8 @@ class IsarService { // } /// 创建 `Stream` 监听所有 `editing` 为 `true` 的日记 - Stream> listenToDiariesEditing({int delayed = 300}) async* { + Stream> listenToDiariesEditing() async* { final isar = await _db; - await Future.delayed(Duration(milliseconds: delayed)); yield* isar.diarys .filter() .editingEqualTo(true) @@ -62,9 +61,8 @@ class IsarService { } /// 监听所有非编辑中的日记 - Stream> listenToAllDiaries({int delayed = 300}) async* { + Stream> listenToAllDiaries() async* { final isar = await _db; - await Future.delayed(Duration(milliseconds: delayed)); yield* isar.diarys .filter() .editingEqualTo(false) diff --git a/lib/index.dart b/lib/index.dart index 994f61d0..3e87a988 100644 --- a/lib/index.dart +++ b/lib/index.dart @@ -22,6 +22,7 @@ export 'package:flutter/gestures.dart'; export 'dart:async' show Timer, StreamSubscription; export 'dart:convert'; export 'dart:io'; +export 'dart:ui' show ImageFilter; /// 外部包相关 export 'package:another_flushbar/flushbar.dart'; // 提示框 diff --git a/lib/l10n/intl/messages_en.dart b/lib/l10n/intl/messages_en.dart index 41c686cd..028bb29a 100644 --- a/lib/l10n/intl/messages_en.dart +++ b/lib/l10n/intl/messages_en.dart @@ -66,6 +66,8 @@ class MessageLookup extends MessageLookupByLibrary { "back": MessageLookupByLibrary.simpleMessage("Back"), "backAgainToExit": MessageLookupByLibrary.simpleMessage("Go Back Again To Exit"), + "backgroundImage": + MessageLookupByLibrary.simpleMessage("Background Image"), "buttonVibration": MessageLookupByLibrary.simpleMessage("Button vibration"), "cancel": MessageLookupByLibrary.simpleMessage("Cancel"), @@ -135,6 +137,8 @@ class MessageLookup extends MessageLookupByLibrary { "moodText": m1, "morePage": MessageLookupByLibrary.simpleMessage("More"), "noData": MessageLookupByLibrary.simpleMessage("No Data"), + "noImageSelected": + MessageLookupByLibrary.simpleMessage("No Image Selected"), "notYetCompleted": MessageLookupByLibrary.simpleMessage("Not Yet Completed"), "pleaseBackToHomePage": diff --git a/lib/l10n/intl/messages_ja.dart b/lib/l10n/intl/messages_ja.dart index abbc827b..62ba4eff 100644 --- a/lib/l10n/intl/messages_ja.dart +++ b/lib/l10n/intl/messages_ja.dart @@ -63,6 +63,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("画像を削除してもよろしいですか?"), "back": MessageLookupByLibrary.simpleMessage("戻る"), "backAgainToExit": MessageLookupByLibrary.simpleMessage("もう一度戻って終了します"), + "backgroundImage": MessageLookupByLibrary.simpleMessage("背景画像"), "buttonVibration": MessageLookupByLibrary.simpleMessage("ボタン振動"), "cancel": MessageLookupByLibrary.simpleMessage("キャンセル"), "changeDate": MessageLookupByLibrary.simpleMessage("日付を変える"), @@ -126,6 +127,7 @@ class MessageLookup extends MessageLookupByLibrary { "moodText": m1, "morePage": MessageLookupByLibrary.simpleMessage("詳細"), "noData": MessageLookupByLibrary.simpleMessage("データ無し"), + "noImageSelected": MessageLookupByLibrary.simpleMessage("画像が選択されていません"), "notYetCompleted": MessageLookupByLibrary.simpleMessage("まだ完成していません"), "pleaseBackToHomePage": MessageLookupByLibrary.simpleMessage("ホームページに戻ってください"), diff --git a/lib/l10n/intl/messages_zh_CN.dart b/lib/l10n/intl/messages_zh_CN.dart index f6cbb909..141e3309 100644 --- a/lib/l10n/intl/messages_zh_CN.dart +++ b/lib/l10n/intl/messages_zh_CN.dart @@ -62,6 +62,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("确定删除图片吗?"), "back": MessageLookupByLibrary.simpleMessage("返回"), "backAgainToExit": MessageLookupByLibrary.simpleMessage("再次返回以退出"), + "backgroundImage": MessageLookupByLibrary.simpleMessage("背景图像"), "buttonVibration": MessageLookupByLibrary.simpleMessage("按钮振动"), "cancel": MessageLookupByLibrary.simpleMessage("取消"), "changeDate": MessageLookupByLibrary.simpleMessage("修改日期"), @@ -114,6 +115,7 @@ class MessageLookup extends MessageLookupByLibrary { "moodText": m1, "morePage": MessageLookupByLibrary.simpleMessage("更多"), "noData": MessageLookupByLibrary.simpleMessage("无数据"), + "noImageSelected": MessageLookupByLibrary.simpleMessage("未选择图片"), "notYetCompleted": MessageLookupByLibrary.simpleMessage("暂未完成"), "pleaseBackToHomePage": MessageLookupByLibrary.simpleMessage("请回到主页"), "pleaseThinkTwiceAboutDeletingTheDiary": diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index bbb2f40b..13c56ab8 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -112,5 +112,7 @@ "backAgainToExit": "Go Back Again To Exit", "hiToKoToProvider": "This service is provided by Hitokoto「一言」", "hiToKoToFetching": "Fetching 「一言」...", - "thisDayLastYear": "This Day Last Year" + "thisDayLastYear": "This Day Last Year", + "backgroundImage": "Background Image", + "noImageSelected": "No Image Selected" } \ No newline at end of file diff --git a/lib/l10n/intl_ja.arb b/lib/l10n/intl_ja.arb index 20a532e5..c1ccbed4 100644 --- a/lib/l10n/intl_ja.arb +++ b/lib/l10n/intl_ja.arb @@ -112,5 +112,7 @@ "backAgainToExit": "もう一度戻って終了します", "hiToKoToProvider": "このサービスは、Hitokoto「一言」が提供しています", "hiToKoToFetching": "「一言」を取得中", - "thisDayLastYear": "去年の今日" + "thisDayLastYear": "去年の今日", + "backgroundImage": "背景画像", + "noImageSelected": "画像が選択されていません" } \ No newline at end of file diff --git a/lib/l10n/intl_zh_CN.arb b/lib/l10n/intl_zh_CN.arb index 9e46458c..977ffeb6 100644 --- a/lib/l10n/intl_zh_CN.arb +++ b/lib/l10n/intl_zh_CN.arb @@ -112,5 +112,7 @@ "backAgainToExit": "再次返回以退出", "hiToKoToProvider": "该服务由 Hitokoto「一言」 提供", "hiToKoToFetching": "正在获取「一言」", - "thisDayLastYear": "去年今日" + "thisDayLastYear": "去年今日", + "backgroundImage": "背景图像", + "noImageSelected": "未选择图片" } \ No newline at end of file diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart index 1c561f3a..b7162265 100644 --- a/lib/l10n/l10n.dart +++ b/lib/l10n/l10n.dart @@ -877,6 +877,26 @@ class MercuriusL10N { args: [], ); } + + /// `Background Image` + String get backgroundImage { + return Intl.message( + 'Background Image', + name: 'backgroundImage', + desc: '', + args: [], + ); + } + + /// `No Image Selected` + String get noImageSelected { + return Intl.message( + 'No Image Selected', + name: 'noImageSelected', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index fbb23fe7..4ba98c1a 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -13,6 +13,7 @@ class _MercuriusHomePageState extends ConsumerState { @override Widget build(BuildContext context) { final MercuriusL10N l10n = MercuriusL10N.of(context); + final path = ref.watch(mercuriusPathProvider); return Scaffold( appBar: AppBar( @@ -26,8 +27,32 @@ class _MercuriusHomePageState extends ConsumerState { ), actions: PlatformWindowsManager.getActions(), ), - body: DiaryListViewWidget( - controller: controller, + body: StreamBuilder( + stream: isarService.listenToConfig(), + builder: (context, snapshot) { + if (snapshot.hasData) { + return Container( + decoration: path.when( + loading: () => null, + error: (error, stackTrace) => null, + data: (data) => BoxDecoration( + image: DecorationImage( + opacity: 0.8, + image: FileImage( + File('$data/image/${snapshot.data?.backgroundImagePath}'), + ), + fit: BoxFit.cover, + ), + ), + ), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3), + child: DiaryListViewWidget(controller: controller), + ), + ); + } + return const MercuriusLoadingWidget(); + }, ), floatingActionButton: const MercuriusFloatingDiaryButtonWidget(), ); diff --git a/lib/pages/setting_page.dart b/lib/pages/setting_page.dart index ea726a65..e27612b6 100644 --- a/lib/pages/setting_page.dart +++ b/lib/pages/setting_page.dart @@ -17,6 +17,7 @@ class SettingPage extends StatelessWidget { BasedListSection( children: [ _ThemeSelectListItem(), + _BackgroundImageListTile(), ], ), ], @@ -26,6 +27,40 @@ class SettingPage extends StatelessWidget { } } +class _BackgroundImageListTile extends StatelessWidget { + const _BackgroundImageListTile(); + + @override + Widget build(BuildContext context) { + final MercuriusL10N l10n = MercuriusL10N.of(context); + + return StreamBuilder( + stream: isarService.listenToConfig(), + builder: (context, snapshot) { + if (snapshot.hasData) { + Config config = snapshot.data!; + return BasedListTile( + leadingIcon: Icons.flip_to_back_rounded, + titleText: l10n.backgroundImage, + detailText: config.backgroundImagePath ?? l10n.noImageSelected, + onTap: () async { + String? path = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => const GalleryPage(readOnly: true), + ), + ); + Mercurius.printLog(path); + isarService.saveConfig(config..backgroundImagePath = path); + }, + ); + } + return const MercuriusLoadingWidget(); + }, + ); + } +} + class _ThemeSelectListItem extends ConsumerWidget { const _ThemeSelectListItem(); @@ -48,9 +83,7 @@ class _ThemeSelectListItem extends ConsumerWidget { : l10n.alwaysBright, onTap: () => showDialog( context: context, - builder: (context) { - return const MercuriusThemeSelectorWidget(); - }, + builder: (context) => const MercuriusThemeSelectorWidget(), ), ); } diff --git a/pubspec.lock b/pubspec.lock index 5b9cc7ac..1de79012 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1118,18 +1118,18 @@ packages: dependency: "direct main" description: name: syncfusion_flutter_charts - sha256: b1c706cea163059ecfe89132ca078f83d31e54cc99ecd1fabe4810e1b1dacc95 + sha256: a545f93f76f2822985a7481c9a6664e989268768215485009eb0e40d35822c34 url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" syncfusion_flutter_core: dependency: transitive description: name: syncfusion_flutter_core - sha256: aea119c8117953fa5decf4a313b431e556b0959cd35ff88f8fbdc0eda9bedb06 + sha256: "295954bc4bda923c88f361da35611801b56f4258179aa355730b236e4ae3ec60" url: "https://pub.dev" source: hosted - version: "23.1.36" + version: "23.1.38" system_tray: dependency: "direct main" description: @@ -1278,10 +1278,10 @@ packages: dependency: "direct main" description: name: vibration - sha256: d81f665bcb201f586c295a21f3fe8f1cb6dc32c81a213a99e9c714ec8e811ce5 + sha256: ab6d26f6694ae0cf702b6d3d1b399570f2911eddb1132c8f82eeacb71a08ece2 url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.8.2" vm_service: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 01ad08a8..dd055260 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,10 +42,10 @@ dependencies: share_plus: ^7.1.0 # 分享 sticky_and_expandable_list: ^1.1.3 # 粘性头部与分组列表 system_tray: ^2.0.3 # 系统托盘 - syncfusion_flutter_charts: ^23.1.36 # 图表 + syncfusion_flutter_charts: ^23.1.38 # 图表 url_launcher: ^6.1.14 # 打开外部链接 unicons: ^2.1.1 # 图标 - vibration: ^1.8.1 # 振动反馈 + vibration: ^1.8.2 # 振动反馈 window_manager: ^0.3.6 # 窗口管理 dev_dependencies: