diff --git a/lib/l10n/app_ja-oj.arb b/lib/l10n/app_ja-oj.arb index e10be7c48..001cae97d 100644 --- a/lib/l10n/app_ja-oj.arb +++ b/lib/l10n/app_ja-oj.arb @@ -94,23 +94,31 @@ "thrownError": "なにか様子がおかしいですわね…", "exportedFileNotFound": "ここにMiriaの設定ファイル見つかりませんでしたわよ", - "importCompleted": "インポート終わりましたわ。", + "importCompleted": "インポート終わりましたわ", "confirmOverwrite": "ここにもうあるようですけれど……上書きいたしますの?", + "exportCompleted": "エクスポート終わりましたわ", "pleaseInputSomething": "なにか入れてくださいまし?", - "pleaseAddVoteChoice": "投票の選択肢を2つ以上入れてくださまいし?", + "pleaseAddVoteChoice": "投票の選択肢を2つ以上入れてくださいまし?", "pleaseSpecifyExpirationDate": "投票がいつまでか入れてくださいまし?", "pleaseSpecifyExpirationDuration": "投票期間を入れてくださいまし?", "cannotMentionToRemoteInLocalOnlyNote": "連合切られているのに他のサーバーの人がメンションに含まれているようですわ", "cannotPublicReplyToPrivateNote": "リプライが{visibility}のようでして……パブリックにはできませんこと", + "unexpectedSensitive": "上げようとしたファイルがサーバーから、センシティブと思われたようですわね", + "staySensitive": "センシティブのままにしますわ", + "memoDescription": "メモしたいことをお書きくださいまし", "confirmCreateBlock": "ブロックなさりますの?", + "confirmUnfollow": "フォロー解除なさりますの?", "unsupportedFile": "対応してないファイルのようですわ", "unsupportedFileWithFilename": "{filename}は対応してないファイルのようですわ", "failedFileSave": "ファイルの保存に失敗したようですわね…", + "invitedReversi": "{users}から招待されているようですわ", + "nonInvitedReversi": "招待されていないようですわね…", + "nothingHere": "ここには何もありませんわ" diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index 450abd219..2de9d8039 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -990,6 +990,13 @@ "unsupportedFile": "対応してないファイルやわ", "unsupportedFileWithFilename": "{filename}は対応してないファイルやわ", + "@unsupportedFileWithFilename": { + "placeholders": { + "filename": { + "type": "String" + } + } + }, "failedFileSave": "ファイルの保存に失敗したみたいや", "misskeyGames": "Misskey Games", diff --git a/lib/main.dart b/lib/main.dart index cdce35502..49c2547ea 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -130,8 +130,8 @@ class Miria extends HookConsumerWidget with WidgetsBindingObserver { GlobalCupertinoLocalizations.delegate, ], builder: (context, widget) { - return DialogScope( - child: AppThemeScope( + return AppThemeScope( + child: DialogScope( child: SharingIntentListener( router: appRouter, child: ErrorDialogListener( diff --git a/lib/repository/import_export_repository.dart b/lib/repository/import_export_repository.dart index 6ef46dbd2..ef2ffb28a 100644 --- a/lib/repository/import_export_repository.dart +++ b/lib/repository/import_export_repository.dart @@ -12,6 +12,7 @@ import "package:miria/model/exported_setting.dart"; import "package:miria/model/tab_setting.dart"; import "package:miria/providers.dart"; import "package:miria/router/app_router.dart"; +import "package:miria/view/common/modal_indicator.dart"; import "package:miria/view/dialogs/simple_confirm_dialog.dart"; import "package:miria/view/dialogs/simple_message_dialog.dart"; import "package:miria/view/settings_page/import_export_page/folder_select_dialog.dart"; @@ -68,41 +69,50 @@ class ImportExportRepository extends ChangeNotifier { } final importFile = alreadyExists.sortedBy((file) => file.createdAt).last; + try { + IndicatorView.showIndicator(context); - final response = await reader(dioProvider) - .get(importFile.url, options: Options(responseType: ResponseType.json)); + final response = await reader(dioProvider).get(importFile.url, + options: Options(responseType: ResponseType.json)); - final json = jsonDecode(response.data); + final json = jsonDecode(response.data); - final importedSettings = ExportedSetting.fromJson(json); + final importedSettings = ExportedSetting.fromJson(json); - // アカウント設定よみこみ - final accounts = reader(accountsProvider); - for (final accountSetting in importedSettings.accountSettings) { - // この端末でログイン済みのアカウントであれば - if (accounts.any((account) => account.acct == accountSetting.acct)) { - await reader(accountSettingsRepositoryProvider).save(accountSetting); + // アカウント設定よみこみ + final accounts = reader(accountsProvider); + for (final accountSetting in importedSettings.accountSettings) { + // この端末でログイン済みのアカウントであれば + if (accounts.any((account) => account.acct == accountSetting.acct)) { + await reader(accountSettingsRepositoryProvider).save(accountSetting); + } } - } - // 全般設定 - await reader(generalSettingsRepositoryProvider) - .update(importedSettings.generalSettings); + // 全般設定 + await reader(generalSettingsRepositoryProvider) + .update(importedSettings.generalSettings); - // タブ設定 - final tabSettings = []; + // タブ設定 + final tabSettings = []; - for (final tabSetting in importedSettings.tabSettings) { - final account = accounts - .firstWhereOrNull((account) => tabSetting.acct == account.acct); + for (final tabSetting in importedSettings.tabSettings) { + final account = accounts + .firstWhereOrNull((account) => tabSetting.acct == account.acct); - if (account == null) { - continue; - } + if (account == null) { + continue; + } - tabSettings.add(tabSetting); + tabSettings.add(tabSetting); + } + await reader(tabSettingsRepositoryProvider).save(tabSettings); + } catch (e) { + rethrow; + } finally { + if (context.mounted) { + IndicatorView.hideIndicator(context); + } } - await reader(tabSettingsRepositoryProvider).save(tabSettings); if (!context.mounted) return; await SimpleMessageDialog.show(context, S.of(context).importCompleted); @@ -163,16 +173,24 @@ class ImportExportRepository extends ChangeNotifier { }; if (!context.mounted) return; - await reader(misskeyProvider(account)).drive.files.createAsBinary( - DriveFilesCreateRequest( - folderId: folder?.id, - name: "miria.json", - comment: S.of(context).exportedFileComment, - force: true, - ), - Uint8List.fromList(utf8.encode(jsonEncode(data))), - ); - + try { + IndicatorView.showIndicator(context); + await reader(misskeyProvider(account)).drive.files.createAsBinary( + DriveFilesCreateRequest( + folderId: folder?.id, + name: "miria.json", + comment: S.of(context).exportedFileComment, + force: true, + ), + Uint8List.fromList(utf8.encode(jsonEncode(data))), + ); + } catch (e) { + rethrow; + } finally { + if (context.mounted) { + IndicatorView.hideIndicator(context); + } + } if (!context.mounted) return; await SimpleMessageDialog.show(context, S.of(context).exportCompleted); } diff --git a/lib/router/app_router.gr.dart b/lib/router/app_router.gr.dart index bda93569c..77adfa2a4 100644 --- a/lib/router/app_router.gr.dart +++ b/lib/router/app_router.gr.dart @@ -43,6 +43,7 @@ abstract class _$AppRouter extends RootStackRouter { key: args.key, host: args.host, remoteHost: args.remoteHost, + showWithoutLogin: args.showWithoutLogin, ), ); }, @@ -107,12 +108,13 @@ abstract class _$AppRouter extends RootStackRouter { final args = routeData.argsAs(); return AutoRoutePage( routeData: routeData, - child: AntennaSettingsDialog( + child: WrappedRoute( + child: AntennaSettingsDialog( account: args.account, key: args.key, title: args.title, initialSettings: args.initialSettings, - ), + )), ); }, AppInfoRoute.name: (routeData) { @@ -666,6 +668,7 @@ abstract class _$AppRouter extends RootStackRouter { child: UserControlDialog( account: args.account, response: args.response, + host: args.host, key: args.key, )), ); @@ -871,6 +874,7 @@ class AccountSelectRoute extends PageRouteInfo { Key? key, String? host, String? remoteHost, + bool showWithoutLogin = true, List? children, }) : super( AccountSelectRoute.name, @@ -878,6 +882,7 @@ class AccountSelectRoute extends PageRouteInfo { key: key, host: host, remoteHost: remoteHost, + showWithoutLogin: showWithoutLogin, ), initialChildren: children, ); @@ -893,6 +898,7 @@ class AccountSelectRouteArgs { this.key, this.host, this.remoteHost, + this.showWithoutLogin = true, }); final Key? key; @@ -901,9 +907,11 @@ class AccountSelectRouteArgs { final String? remoteHost; + final bool showWithoutLogin; + @override String toString() { - return 'AccountSelectRouteArgs{key: $key, host: $host, remoteHost: $remoteHost}'; + return 'AccountSelectRouteArgs{key: $key, host: $host, remoteHost: $remoteHost, showWithoutLogin: $showWithoutLogin}'; } } @@ -3037,6 +3045,7 @@ class UserControlRoute extends PageRouteInfo { UserControlRoute({ required Account account, required UserDetailed response, + String? host, Key? key, List? children, }) : super( @@ -3044,6 +3053,7 @@ class UserControlRoute extends PageRouteInfo { args: UserControlRouteArgs( account: account, response: response, + host: host, key: key, ), initialChildren: children, @@ -3059,6 +3069,7 @@ class UserControlRouteArgs { const UserControlRouteArgs({ required this.account, required this.response, + this.host, this.key, }); @@ -3066,11 +3077,13 @@ class UserControlRouteArgs { final UserDetailed response; + final String? host; + final Key? key; @override String toString() { - return 'UserControlRouteArgs{account: $account, response: $response, key: $key}'; + return 'UserControlRouteArgs{account: $account, response: $response, host: $host, key: $key}'; } } diff --git a/lib/state_notifier/common/misskey_notes/misskey_note_notifier.dart b/lib/state_notifier/common/misskey_notes/misskey_note_notifier.dart index 6d99789d0..38e82a16c 100644 --- a/lib/state_notifier/common/misskey_notes/misskey_note_notifier.dart +++ b/lib/state_notifier/common/misskey_notes/misskey_note_notifier.dart @@ -191,7 +191,7 @@ class MisskeyNoteNotifier extends _$MisskeyNoteNotifier { await navigateToNoteDetailPage(note, account: selectedAccount); } - Future openUserInOtherAccount(User user) async { + Future openUserInOtherAccount(User user, String? host) async { final accountContext = ref.read(accountContextProvider); final selectedAccount = await ref.read(appRouterProvider).push( AccountSelectRoute( @@ -203,6 +203,21 @@ class MisskeyNoteNotifier extends _$MisskeyNoteNotifier { ); if (selectedAccount == null) return; + if (user.host == null) { + switch (user) { + case UserLite(): + user = user.copyWith(host: host ?? accountContext.getAccount.host); + + case UserDetailedNotMe(): + user = user.copyWith(host: host ?? accountContext.getAccount.host); + + case UserDetailedNotMeWithRelations(): + user = user.copyWith(host: host ?? accountContext.getAccount.host); + + case MeDetailed(): + user = user.copyWith(host: host ?? accountContext.getAccount.host); + } + } await navigateToUserPage(user, account: selectedAccount); } } diff --git a/lib/state_notifier/common/misskey_notes/misskey_note_notifier.g.dart b/lib/state_notifier/common/misskey_notes/misskey_note_notifier.g.dart index 3939ee944..e6772d1fd 100644 --- a/lib/state_notifier/common/misskey_notes/misskey_note_notifier.g.dart +++ b/lib/state_notifier/common/misskey_notes/misskey_note_notifier.g.dart @@ -7,7 +7,7 @@ part of 'misskey_note_notifier.dart'; // ************************************************************************** String _$misskeyNoteNotifierHash() => - r'5edd4690a767107f9c8a30e6b480a74de4e83d74'; + r'e4ba06422429aea1857ed3758ee47b762ee064a8'; /// See also [MisskeyNoteNotifier]. @ProviderFor(MisskeyNoteNotifier) diff --git a/lib/view/common/account_select_dialog.dart b/lib/view/common/account_select_dialog.dart index 9690447fa..5767f3786 100644 --- a/lib/view/common/account_select_dialog.dart +++ b/lib/view/common/account_select_dialog.dart @@ -11,7 +11,12 @@ import "package:miria/view/common/misskey_notes/mfm_text.dart"; @RoutePage() class AccountSelectDialog extends HookConsumerWidget { - const AccountSelectDialog({super.key, this.host, this.remoteHost}); + const AccountSelectDialog({ + super.key, + this.host, + this.remoteHost, + this.showWithoutLogin = true, + }); /// nullではないとき, 指定されたサーバーのアカウントのみ表示する final String? host; @@ -19,6 +24,9 @@ class AccountSelectDialog extends HookConsumerWidget { /// 相手先のホスト final String? remoteHost; + // 相手先のサーバで開く(ログインなし)を表示 + final bool showWithoutLogin; + @override Widget build(BuildContext context, WidgetRef ref) { final accounts = ref.watch(accountsProvider); @@ -41,7 +49,7 @@ class AccountSelectDialog extends HookConsumerWidget { height: MediaQuery.of(context).size.height * 0.8, child: ListView( children: [ - if (remoteHost != null) + if (showWithoutLogin && remoteHost != null) switch (navigateAsRemote.value) { AsyncLoading() => const Center( child: CircularProgressIndicator.adaptive(), diff --git a/lib/view/common/misskey_notes/link_navigator.dart b/lib/view/common/misskey_notes/link_navigator.dart index 95760cc3b..24752d0b0 100644 --- a/lib/view/common/misskey_notes/link_navigator.dart +++ b/lib/view/common/misskey_notes/link_navigator.dart @@ -107,7 +107,11 @@ class LinkNavigator { ); } else if (uri.pathSegments.length == 1 && uri.pathSegments.first.startsWith("@")) { - await onMentionTap(context, ref, uri.pathSegments.first, host); + final userName = ("@".allMatches(uri.pathSegments.first).length == 1) + ? "${uri.pathSegments.first}@${uri.host}" + : uri.pathSegments.first; + + await onMentionTap(context, ref, userName, host); } else { if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); diff --git a/lib/view/common/misskey_notes/renote_modal_sheet.dart b/lib/view/common/misskey_notes/renote_modal_sheet.dart index ae9f4f7a6..7810364d2 100644 --- a/lib/view/common/misskey_notes/renote_modal_sheet.dart +++ b/lib/view/common/misskey_notes/renote_modal_sheet.dart @@ -101,6 +101,7 @@ class RenoteOtherAccountNotifier extends _$RenoteOtherAccountNotifier { note.user.host != this.account.host && note.user.host != null ? note.user.host : null, + showWithoutLogin: false, ), ); if (selectedAccount == null) return; diff --git a/lib/view/common/misskey_notes/renote_modal_sheet.g.dart b/lib/view/common/misskey_notes/renote_modal_sheet.g.dart index ba6e0aa48..cbd6bd499 100644 --- a/lib/view/common/misskey_notes/renote_modal_sheet.g.dart +++ b/lib/view/common/misskey_notes/renote_modal_sheet.g.dart @@ -431,7 +431,7 @@ class _RenoteChannelNotifierProviderElement } String _$renoteOtherAccountNotifierHash() => - r'6ce80b97d6f49aa3302dfd27b2b1b8242dc559cb'; + r'055ec79f4f828ccd3a5756ada8f254f273336c83'; abstract class _$RenoteOtherAccountNotifier extends BuildlessAutoDisposeNotifier?> { diff --git a/lib/view/common/note_file_dialog/image_viewer.dart b/lib/view/common/note_file_dialog/image_viewer.dart index df00114bf..80cfb5fe6 100644 --- a/lib/view/common/note_file_dialog/image_viewer.dart +++ b/lib/view/common/note_file_dialog/image_viewer.dart @@ -79,7 +79,9 @@ class ImageViewer extends HookConsumerWidget { }, onDoubleTap: () { if (provider.scale != 1.0) { - resetScale(); + if (provider.scale == provider.lastScale) { + resetScale(); + } } else { final position = ref .read(imageViewerInfoNotifierProvider) diff --git a/lib/view/login_page/mi_auth_login.dart b/lib/view/login_page/mi_auth_login.dart index 3195b938a..81b6d892e 100644 --- a/lib/view/login_page/mi_auth_login.dart +++ b/lib/view/login_page/mi_auth_login.dart @@ -1,6 +1,7 @@ import "package:auto_route/auto_route.dart"; import "package:flutter/material.dart"; import "package:flutter_gen/gen_l10n/app_localizations.dart"; +import "package:flutter_hooks/flutter_hooks.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:miria/providers.dart"; @@ -12,45 +13,23 @@ import "package:miria/view/common/modal_indicator.dart"; import "package:miria/view/login_page/centraing_widget.dart"; import "package:miria/view/login_page/misskey_server_list_dialog.dart"; -class MiAuthLogin extends ConsumerStatefulWidget { +class MiAuthLogin extends HookConsumerWidget { const MiAuthLogin({super.key}); @override - ConsumerState createState() => MiAuthLoginState(); -} - -class MiAuthLoginState extends ConsumerState { - final serverController = TextEditingController(); - bool isAuthed = false; - - @override - void dispose() { - serverController.dispose(); - super.dispose(); - } + Widget build(BuildContext context, WidgetRef ref) { + final serverController = useTextEditingController(); + final isAuthed = useState(false); - Future login() async { - try { - IndicatorView.showIndicator(context); - await ref - .read(accountRepositoryProvider.notifier) - .validateMiAuth(toAscii(serverController.text)); - if (!mounted) return; - await context.pushRoute( - TimeLineRoute( - initialTabSetting: - ref.read(tabSettingsRepositoryProvider).tabSettings.first, - ), - ); - } catch (e) { - rethrow; - } finally { - IndicatorView.hideIndicator(context); - } - } + useEffect( + () { + return () { + serverController.dispose(); + }; + }, + const [], + ); - @override - Widget build(BuildContext context) { return CenteringWidget( child: Column( mainAxisSize: MainAxisSize.min, @@ -97,16 +76,21 @@ class MiAuthLoginState extends ConsumerState { Container(), ElevatedButton( onPressed: () async { - await ref - .read(accountRepositoryProvider.notifier) - .openMiAuth(toAscii(serverController.text)) - .expectFailure(context); - setState(() { - isAuthed = true; - }); + try { + IndicatorView.showIndicator(context); + await ref + .read(accountRepositoryProvider.notifier) + .openMiAuth(toAscii(serverController.text)) + .expectFailure(context); + } catch (e) { + rethrow; + } finally { + IndicatorView.hideIndicator(context); + } + isAuthed.value = true; }, child: Text( - isAuthed + isAuthed.value ? S.of(context).reauthorizate : S.of(context).authorizate, ), @@ -119,12 +103,32 @@ class MiAuthLoginState extends ConsumerState { Container(), ], ), - if (isAuthed) + if (isAuthed.value) TableRow( children: [ Container(), ElevatedButton( - onPressed: () async => login().expectFailure(context), + onPressed: () async { + try { + IndicatorView.showIndicator(context); + await ref + .read(accountRepositoryProvider.notifier) + .validateMiAuth(toAscii(serverController.text)); + if (!context.mounted) return; + await context.pushRoute( + TimeLineRoute( + initialTabSetting: ref + .read(tabSettingsRepositoryProvider) + .tabSettings + .first, + ), + ); + } catch (e) { + rethrow; + } finally { + IndicatorView.hideIndicator(context); + } + }.expectFailure(context), child: Text(S.of(context).didAuthorize), ), ], diff --git a/lib/view/note_modal_sheet/note_modal_sheet.dart b/lib/view/note_modal_sheet/note_modal_sheet.dart index 09bdffa5f..8b7243a67 100644 --- a/lib/view/note_modal_sheet/note_modal_sheet.dart +++ b/lib/view/note_modal_sheet/note_modal_sheet.dart @@ -240,6 +240,7 @@ class NoteModalSheet extends ConsumerWidget implements AutoRouteWrapper { UserControlRoute( account: accountContext.postAccount, response: value, + host: ref.read(misskeyGetContextProvider).host, ), ); case null: diff --git a/lib/view/note_modal_sheet/note_modal_sheet.g.dart b/lib/view/note_modal_sheet/note_modal_sheet.g.dart index 39a63ab2b..653d1e5fc 100644 --- a/lib/view/note_modal_sheet/note_modal_sheet.g.dart +++ b/lib/view/note_modal_sheet/note_modal_sheet.g.dart @@ -7,7 +7,7 @@ part of 'note_modal_sheet.dart'; // ************************************************************************** String _$noteModalSheetNotifierHash() => - r'6e16e66d1e8ce6671ac6ba8bd9bb208c9b7b6652'; + r'7d2d5ee4f994089c0ae3b3b1fcbbec8ad53c8db9'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/view/notification_page/notification_page.dart b/lib/view/notification_page/notification_page.dart index 476b5d9f9..61e4924c2 100644 --- a/lib/view/notification_page/notification_page.dart +++ b/lib/view/notification_page/notification_page.dart @@ -401,6 +401,7 @@ class NotificationItem extends ConsumerWidget { if (type is FollowRequestAccepted && type.message != null) SimpleMfmText( S.of(context).messageForFollower(type.message ?? ""), + emojis: type.user?.emojis ?? {}, ) ], ), diff --git a/lib/view/notification_page/notification_page_data.dart b/lib/view/notification_page/notification_page_data.dart index 15a83fd7e..3d90bc1b7 100644 --- a/lib/view/notification_page/notification_page_data.dart +++ b/lib/view/notification_page/notification_page_data.dart @@ -64,8 +64,11 @@ class MentionQuoteNotificationData extends NotificationData { sealed class FollowNotificationDataType { String Function(BuildContext, String) get name; static final follow = _Follow(); - factory FollowNotificationDataType.followRequestAccepted(String? message) => - FollowRequestAccepted(message); + factory FollowNotificationDataType.followRequestAccepted( + String? message, + User? user, + ) => + FollowRequestAccepted(message, user); static final receiveFollowRequest = _ReceiveFollowRequest(); } @@ -77,7 +80,8 @@ class _Follow implements FollowNotificationDataType { class FollowRequestAccepted implements FollowNotificationDataType { final String? message; - FollowRequestAccepted(this.message); + final User? user; + FollowRequestAccepted(this.message, this.user); @override String Function(BuildContext context, String userName) get name => (context, userName) => @@ -241,7 +245,9 @@ extension INotificationsResponseExtension on Iterable { user: element.user, createdAt: element.createdAt, type: FollowNotificationDataType.followRequestAccepted( - element.message), + element.message, + element.user, + ), id: element.id, ), ); diff --git a/lib/view/user_page/user_control_dialog.dart b/lib/view/user_page/user_control_dialog.dart index 48ec542ff..2971dab39 100644 --- a/lib/view/user_page/user_control_dialog.dart +++ b/lib/view/user_page/user_control_dialog.dart @@ -31,10 +31,12 @@ enum UserControl { class UserControlDialog extends HookConsumerWidget implements AutoRouteWrapper { final Account account; final UserDetailed response; + final String? host; const UserControlDialog({ required this.account, required this.response, + this.host, super.key, }); @@ -105,7 +107,7 @@ class UserControlDialog extends HookConsumerWidget implements AutoRouteWrapper { final openUserInOtherAccount = useAsync( () async => ref .read(misskeyNoteNotifierProvider.notifier) - .openUserInOtherAccount(response), + .openUserInOtherAccount(response, host), ); final isLoading = [ diff --git a/lib/view/user_page/user_detail.dart b/lib/view/user_page/user_detail.dart index 8ead69bb1..e7b9d77ac 100644 --- a/lib/view/user_page/user_detail.dart +++ b/lib/view/user_page/user_detail.dart @@ -142,6 +142,7 @@ class UserDetail extends ConsumerWidget { UserControlRoute( account: ref.read(accountContextProvider).postAccount, response: response, + host: ref.read(misskeyGetContextProvider).host, ), ), icon: const Icon(Icons.more_vert), diff --git a/lib/view/user_page/user_notes.dart b/lib/view/user_page/user_notes.dart index 1ae064318..504b46f4a 100644 --- a/lib/view/user_page/user_notes.dart +++ b/lib/view/user_page/user_notes.dart @@ -113,11 +113,11 @@ class UserNotes extends HookConsumerWidget { result.year, result.month, result.day, - 23, - 59, - 59, - 999, - ); + result.hour, + result.minute, + 0, + 0, + ).subtract(const Duration(milliseconds: 1)); } }, icon: const Icon(Icons.date_range),