From a1222f462c904075c1f1c7e3bc2797680815d31a Mon Sep 17 00:00:00 2001 From: Predidit <34627277+Predidit@users.noreply.github.com> Date: Thu, 30 Jan 2025 21:34:23 +0800 Subject: [PATCH 1/8] fix danmaku fontsize slider (#670) --- lib/pages/settings/danmaku/danmaku_settings_window.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/settings/danmaku/danmaku_settings_window.dart b/lib/pages/settings/danmaku/danmaku_settings_window.dart index 011318ab..1ae5e355 100644 --- a/lib/pages/settings/danmaku/danmaku_settings_window.dart +++ b/lib/pages/settings/danmaku/danmaku_settings_window.dart @@ -29,7 +29,7 @@ class _DanmakuSettingsWindowState extends State { value: widget.danmakuController.option.fontSize, min: 10, max: Utils.isCompact() ? 32 : 48, - divisions: 22, + divisions: Utils.isCompact() ? 22 : 38, label: widget.danmakuController.option.fontSize.toString(), onChanged: (value) { setState(() => widget.danmakuController.updateOption( From e56375af0e583193247fcf3d7544c9525060dde2 Mon Sep 17 00:00:00 2001 From: ErBW_s Date: Fri, 31 Jan 2025 10:40:19 +0800 Subject: [PATCH 2/8] fix desktop fullscreen tabBody width --- lib/pages/video/video_page.dart | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/pages/video/video_page.dart b/lib/pages/video/video_page.dart index 86578709..05bb9a24 100644 --- a/lib/pages/video/video_page.dart +++ b/lib/pages/video/video_page.dart @@ -390,10 +390,8 @@ class _VideoPageState extends State position: _rightOffsetAnimation, child: SizedBox( height: MediaQuery.of(context).size.height, - width: videoPageController.isFullscreen - ? (Utils.isTablet() - ? MediaQuery.of(context).size.width / 3 - : MediaQuery.of(context).size.height) + width: !isWideScreen + ? MediaQuery.of(context).size.height : (MediaQuery.of(context).size.width / 3 > 420 ? 420 : MediaQuery.of(context).size.width / 3), From 35b84012a88d5ad0630912035d8d693e8fb075e5 Mon Sep 17 00:00:00 2001 From: ErBW_s Date: Fri, 31 Jan 2025 10:41:01 +0800 Subject: [PATCH 3/8] fix comments scroll issue --- lib/pages/player/episode_comments_sheet.dart | 84 ++++++++++++-------- 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/lib/pages/player/episode_comments_sheet.dart b/lib/pages/player/episode_comments_sheet.dart index f82a3f7e..f34bd49a 100644 --- a/lib/pages/player/episode_comments_sheet.dart +++ b/lib/pages/player/episode_comments_sheet.dart @@ -15,7 +15,8 @@ class EpisodeCommentsSheet extends StatefulWidget { State createState() => _EpisodeCommentsSheetState(); } -class _EpisodeCommentsSheetState extends State { +class _EpisodeCommentsSheetState extends State + with AutomaticKeepAliveClientMixin { final infoController = Modular.get(); bool isLoading = false; bool commentsQueryTimeout = false; @@ -56,39 +57,54 @@ class _EpisodeCommentsSheetState extends State { } Widget get episodeCommentsBody { - return SelectionArea( - child: CustomScrollView( - slivers: [ - SliverPadding( - padding: const EdgeInsets.fromLTRB(4, 0, 4, 4), - sliver: Observer(builder: (context) { - if (isLoading) { - return const SliverFillRemaining( - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - if (commentsQueryTimeout) { - return const SliverFillRemaining( - child: Center( - child: Text('空空如也'), - ), - ); - } - return SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - return EpisodeCommentsCard( - commentItem: infoController.episodeCommentsList[index]); - }, - childCount: infoController.episodeCommentsList.length, + return CustomScrollView( + // Scrollbars' movement is not linear so hide it. + scrollBehavior: const ScrollBehavior().copyWith(scrollbars: false), + slivers: [ + SliverPadding( + padding: const EdgeInsets.fromLTRB(4, 0, 4, 4), + sliver: Observer(builder: (context) { + if (isLoading) { + return const SliverFillRemaining( + child: Center( + child: CircularProgressIndicator(), ), ); - }), - ), - ], - ), + } + if (commentsQueryTimeout) { + return const SliverFillRemaining( + child: Center( + child: Text('空空如也'), + ), + ); + } + return SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + // Fix scroll issue caused by height change of network images + // by keeping loaded cards alive. + return KeepAlive( + keepAlive: true, + child: IndexedSemantics( + index: index, + child: SelectionArea( + child: EpisodeCommentsCard( + commentItem: + infoController.episodeCommentsList[index], + ), + ), + ), + ); + }, + childCount: infoController.episodeCommentsList.length, + addAutomaticKeepAlives: false, + addRepaintBoundaries: false, + addSemanticIndexes: false, + ), + ); + }), + ), + ], ); } @@ -192,6 +208,7 @@ class _EpisodeCommentsSheetState extends State { @override Widget build(BuildContext context) { + super.build(context); return Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -199,4 +216,7 @@ class _EpisodeCommentsSheetState extends State { ), ); } + + @override + bool get wantKeepAlive => true; } From 52ac282b790e7908144aa7f7cf5cb8e4cca00c7f Mon Sep 17 00:00:00 2001 From: ErBW_s Date: Fri, 31 Jan 2025 11:06:24 +0800 Subject: [PATCH 4/8] fix mobile switch episode when portrait will break comments --- lib/pages/player/episode_comments_sheet.dart | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/lib/pages/player/episode_comments_sheet.dart b/lib/pages/player/episode_comments_sheet.dart index f34bd49a..226f718d 100644 --- a/lib/pages/player/episode_comments_sheet.dart +++ b/lib/pages/player/episode_comments_sheet.dart @@ -21,17 +21,6 @@ class _EpisodeCommentsSheetState extends State bool isLoading = false; bool commentsQueryTimeout = false; - @override - void initState() { - super.initState(); - if (infoController.episodeCommentsList.isEmpty) { - setState(() { - isLoading = true; - }); - loadComments(widget.episode); - } - } - Future loadComments(int episode) async { commentsQueryTimeout = false; infoController @@ -57,6 +46,12 @@ class _EpisodeCommentsSheetState extends State } Widget get episodeCommentsBody { + if (infoController.episodeCommentsList.isEmpty) { + setState(() { + isLoading = true; + }); + loadComments(widget.episode); + } return CustomScrollView( // Scrollbars' movement is not linear so hide it. scrollBehavior: const ScrollBehavior().copyWith(scrollbars: false), From 53ca31e3e69df68d6f65f89c1d48d5365a49eb95 Mon Sep 17 00:00:00 2001 From: Predidit <34627277+Predidit@users.noreply.github.com> Date: Fri, 31 Jan 2025 13:28:55 +0800 Subject: [PATCH 5/8] fix mismatched episode comments --- lib/pages/video/video_page.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pages/video/video_page.dart b/lib/pages/video/video_page.dart index 05bb9a24..ec2452d8 100644 --- a/lib/pages/video/video_page.dart +++ b/lib/pages/video/video_page.dart @@ -142,6 +142,7 @@ class _VideoPageState extends State _videoURLSubscription.cancel(); _logSubscription.cancel(); playerController.dispose(); + infoController.episodeCommentsList.clear(); Utils.unlockScreenRotation(); super.dispose(); } From 6fd64b74c4f52cb66d0aad4bc62c2e17161b1678 Mon Sep 17 00:00:00 2001 From: garylkz <37288203+garylkz@users.noreply.github.com> Date: Sat, 1 Feb 2025 02:59:29 +0800 Subject: [PATCH 6/8] Implemented default exit behavior setting --- lib/bean/appbar/sys_app_bar.dart | 74 ++++++++++++++++++++++++++------ lib/pages/my/my_page.dart | 39 ++++++++++++++++- lib/utils/storage.dart | 11 +++-- 3 files changed, 106 insertions(+), 18 deletions(-) diff --git a/lib/bean/appbar/sys_app_bar.dart b/lib/bean/appbar/sys_app_bar.dart index 097a429d..fa37a001 100644 --- a/lib/bean/appbar/sys_app_bar.dart +++ b/lib/bean/appbar/sys_app_bar.dart @@ -1,9 +1,11 @@ import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:kazumi/bean/dialog/dialog_helper.dart'; +import 'package:kazumi/utils/storage.dart'; import 'package:kazumi/utils/utils.dart'; -import 'package:flutter/material.dart'; import 'package:window_manager/window_manager.dart'; -import 'package:flutter/services.dart'; class SysAppBar extends StatelessWidget implements PreferredSizeWidget { final double? toolbarHeight; @@ -37,16 +39,62 @@ class SysAppBar extends StatelessWidget implements PreferredSizeWidget { this.bottom}); void _handleCloseEvent() { - KazumiDialog.show( - builder: (context) { + final setting = GStorage.setting; + final exitBehavior = setting.get(SettingBoxKey.exitBehavior); + + switch (exitBehavior) { + case 0: + exit(0); + case 1: + KazumiDialog.dismiss(); + windowManager.hide(); + break; + default: + KazumiDialog.show(builder: (context) { + bool saveExitBehavior = false; // 下次不再询问? + return AlertDialog( title: const Text('退出确认'), - content: const Text('您想要退出 Kazumi 吗?'), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Text('您想要退出 Kazumi 吗?'), + const SizedBox(height: 24), + StatefulBuilder(builder: (context, setState) { + onChanged(value) { + saveExitBehavior = value ?? false; + setState(() {}); + } + + return Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 8, + children: [ + Checkbox( + value: saveExitBehavior, + onChanged: onChanged, + ), + const Text('下次不再询问'), + ], + ); + }), + ], + ), actions: [ TextButton( - onPressed: () => exit(0), child: const Text('退出 Kazumi')), + onPressed: () async { + if (saveExitBehavior) { + await setting.put(SettingBoxKey.exitBehavior, 0); + } + exit(0); + }, + child: const Text('退出 Kazumi')), TextButton( - onPressed: () { + onPressed: () async { + if (saveExitBehavior) { + await setting.put(SettingBoxKey.exitBehavior, 1); + } KazumiDialog.dismiss(); windowManager.hide(); }, @@ -56,6 +104,7 @@ class SysAppBar extends StatelessWidget implements PreferredSizeWidget { ], ); }); + } } @override @@ -88,14 +137,13 @@ class SysAppBar extends StatelessWidget implements PreferredSizeWidget { bottom: bottom, systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: Colors.transparent, - statusBarIconBrightness: Theme.of(context).brightness == - Brightness.light - ? Brightness.dark - : Brightness.light, + statusBarIconBrightness: + Theme.of(context).brightness == Brightness.light + ? Brightness.dark + : Brightness.light, systemNavigationBarColor: Colors.transparent, systemNavigationBarDividerColor: Colors.transparent, - ) - ), + )), ); } diff --git a/lib/pages/my/my_page.dart b/lib/pages/my/my_page.dart index b64eddeb..d38bc47b 100644 --- a/lib/pages/my/my_page.dart +++ b/lib/pages/my/my_page.dart @@ -2,10 +2,12 @@ import 'package:card_settings_ui/card_settings_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:kazumi/bean/appbar/sys_app_bar.dart'; -import 'package:provider/provider.dart'; +import 'package:kazumi/bean/dialog/dialog_helper.dart'; import 'package:kazumi/pages/menu/menu.dart'; import 'package:kazumi/pages/menu/side_menu.dart'; +import 'package:kazumi/utils/storage.dart'; import 'package:kazumi/utils/utils.dart'; +import 'package:provider/provider.dart'; class MyPage extends StatefulWidget { const MyPage({super.key}); @@ -15,6 +17,13 @@ class MyPage extends StatefulWidget { } class _MyPageState extends State { + final exitBehaviorTitles = ['退出 Kazumi', '最小化至托盘', '每次都询问']; + + final setting = GStorage.setting; + + late int exitBehavior = + setting.get(SettingBoxKey.exitBehavior, defaultValue: 2); + dynamic navigationBarState; void onBackPressed(BuildContext context) { @@ -117,6 +126,34 @@ class _MyPageState extends State { SettingsSection( title: const Text('其他'), tiles: [ + SettingsTile.navigation( + leading: const Icon(Icons.exit_to_app), + title: const Text('退出设置'), + description: const Text('设置退出默认行为'), + value: Text(exitBehaviorTitles[exitBehavior]), + onPressed: (_) { + KazumiDialog.show(builder: (context) { + return SimpleDialog( + title: const Text('退出行为'), + children: [ + for (int i = 0; i < 3; i++) + RadioListTile( + value: i, + groupValue: exitBehavior, + onChanged: (int? value) { + exitBehavior = value!; + setting.put( + SettingBoxKey.exitBehavior, value); + Navigator.pop(context); + setState(() {}); + }, + title: Text(exitBehaviorTitles[i]), + ), + ], + ); + }); + }, + ), SettingsTile.navigation( onPressed: (_) { Modular.to.pushNamed('/settings/about/'); diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 89239ba8..101459a7 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -1,11 +1,12 @@ import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:kazumi/modules/bangumi/bangumi_item.dart'; import 'package:kazumi/modules/bangumi/bangumi_tag.dart'; -import 'package:kazumi/modules/history/history_module.dart'; import 'package:kazumi/modules/collect/collect_module.dart'; +import 'package:kazumi/modules/history/history_module.dart'; +import 'package:path_provider/path_provider.dart'; class GStorage { // Don't use favorites box, it's replaced by collectibles. @@ -81,7 +82,8 @@ class GStorage { static Future patchCollectibles(String backupFilePath) async { final backupFile = File(backupFilePath); final backupContent = await backupFile.readAsBytes(); - final tempBox = await Hive.openBox('tempCollectiblesBox', bytes: backupContent); + final tempBox = + await Hive.openBox('tempCollectiblesBox', bytes: backupContent); final tempBoxItems = tempBox.toMap().entries; debugPrint('webDav追番列表长度 ${tempBoxItems.length}'); @@ -135,5 +137,6 @@ class SettingBoxKey { webDavPassword = 'webDavPasswd', lowMemoryMode = 'lowMemoryMode', useDynamicColor = 'useDynamicColor', - defaultSuperResolutionType = 'defaultSuperResolutionType'; + defaultSuperResolutionType = 'defaultSuperResolutionType', + exitBehavior = 'exitBehavior'; } From 3d6d0e3b2177965cf53e59450940ba77833da588 Mon Sep 17 00:00:00 2001 From: garylkz <37288203+garylkz@users.noreply.github.com> Date: Sat, 1 Feb 2025 12:23:57 +0800 Subject: [PATCH 7/8] Moved default exit behavior into about page - Added default value for `exitBehavior` on close event --- lib/bean/appbar/sys_app_bar.dart | 8 ++-- lib/pages/about/about_page.dart | 69 ++++++++++++++++++++++++++------ lib/pages/my/my_page.dart | 37 ----------------- 3 files changed, 60 insertions(+), 54 deletions(-) diff --git a/lib/bean/appbar/sys_app_bar.dart b/lib/bean/appbar/sys_app_bar.dart index fa37a001..4c4d2626 100644 --- a/lib/bean/appbar/sys_app_bar.dart +++ b/lib/bean/appbar/sys_app_bar.dart @@ -40,7 +40,8 @@ class SysAppBar extends StatelessWidget implements PreferredSizeWidget { void _handleCloseEvent() { final setting = GStorage.setting; - final exitBehavior = setting.get(SettingBoxKey.exitBehavior); + final exitBehavior = + setting.get(SettingBoxKey.exitBehavior, defaultValue: 2); switch (exitBehavior) { case 0: @@ -71,10 +72,7 @@ class SysAppBar extends StatelessWidget implements PreferredSizeWidget { crossAxisAlignment: WrapCrossAlignment.center, spacing: 8, children: [ - Checkbox( - value: saveExitBehavior, - onChanged: onChanged, - ), + Checkbox(value: saveExitBehavior, onChanged: onChanged), const Text('下次不再询问'), ], ); diff --git a/lib/pages/about/about_page.dart b/lib/pages/about/about_page.dart index f55b1775..a42877a1 100644 --- a/lib/pages/about/about_page.dart +++ b/lib/pages/about/about_page.dart @@ -1,16 +1,18 @@ import 'dart:io'; + +import 'package:card_settings_ui/card_settings_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:hive/hive.dart'; -import 'package:kazumi/pages/my/my_controller.dart'; -import 'package:kazumi/request/api.dart'; -import 'package:url_launcher/url_launcher.dart'; import 'package:kazumi/bean/appbar/sys_app_bar.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:kazumi/bean/dialog/dialog_helper.dart'; -import 'package:card_settings_ui/card_settings_ui.dart'; -import 'package:kazumi/utils/storage.dart'; +import 'package:kazumi/pages/my/my_controller.dart'; +import 'package:kazumi/request/api.dart'; import 'package:kazumi/utils/mortis.dart'; +import 'package:kazumi/utils/storage.dart'; +import 'package:kazumi/utils/utils.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:url_launcher/url_launcher.dart'; class AboutPage extends StatefulWidget { const AboutPage({super.key}); @@ -20,10 +22,14 @@ class AboutPage extends StatefulWidget { } class _AboutPageState extends State { + final exitBehaviorTitles = ['退出 Kazumi', '最小化至托盘', '每次都询问']; + late dynamic defaultDanmakuArea; late dynamic defaultThemeMode; late dynamic defaultThemeColor; Box setting = GStorage.setting; + late int exitBehavior = + setting.get(SettingBoxKey.exitBehavior, defaultValue: 2); late bool autoUpdate; double _cacheSizeMB = -1; final MyController myController = Modular.get(); @@ -31,8 +37,7 @@ class _AboutPageState extends State { @override void initState() { super.initState(); - autoUpdate = - setting.get(SettingBoxKey.autoUpdate, defaultValue: true); + autoUpdate = setting.get(SettingBoxKey.autoUpdate, defaultValue: true); _getCacheSize(); } @@ -142,7 +147,9 @@ class _AboutPageState extends State { }, title: const Text('开源许可证'), description: const Text('查看所有开源许可证'), - ),],), + ), + ], + ), SettingsSection( title: const Text('外部链接'), tiles: [ @@ -178,7 +185,41 @@ class _AboutPageState extends State { title: const Text('弹幕来源'), description: Text('ID: ${mortis['id']}'), value: const Text('DanDanPlay'), - ),],), + ), + ], + ), + SettingsSection( + title: const Text('默认行为'), + tiles: [ + if (Utils.isDesktop()) + SettingsTile.navigation( + title: const Text('关闭时'), + value: Text(exitBehaviorTitles[exitBehavior]), + onPressed: (_) { + KazumiDialog.show(builder: (context) { + return SimpleDialog( + title: const Text('关闭时'), + children: [ + for (int i = 0; i < 3; i++) + RadioListTile( + value: i, + groupValue: exitBehavior, + onChanged: (int? value) { + exitBehavior = value ?? 2; + setting.put( + SettingBoxKey.exitBehavior, value); + KazumiDialog.dismiss(); + setState(() {}); + }, + title: Text(exitBehaviorTitles[i]), + ), + ], + ); + }); + }, + ), + ], + ), SettingsSection( tiles: [ SettingsTile.navigation( @@ -186,7 +227,9 @@ class _AboutPageState extends State { Modular.to.pushNamed('/settings/about/logs'); }, title: const Text('错误日志'), - ),],), + ), + ], + ), SettingsSection( tiles: [ SettingsTile.navigation( @@ -197,7 +240,9 @@ class _AboutPageState extends State { value: _cacheSizeMB == -1 ? const Text('统计中...') : Text('${_cacheSizeMB.toStringAsFixed(2)}MB'), - ),],), + ), + ], + ), SettingsSection( title: const Text('应用更新'), tiles: [ diff --git a/lib/pages/my/my_page.dart b/lib/pages/my/my_page.dart index d38bc47b..7612fe33 100644 --- a/lib/pages/my/my_page.dart +++ b/lib/pages/my/my_page.dart @@ -2,10 +2,8 @@ import 'package:card_settings_ui/card_settings_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:kazumi/bean/appbar/sys_app_bar.dart'; -import 'package:kazumi/bean/dialog/dialog_helper.dart'; import 'package:kazumi/pages/menu/menu.dart'; import 'package:kazumi/pages/menu/side_menu.dart'; -import 'package:kazumi/utils/storage.dart'; import 'package:kazumi/utils/utils.dart'; import 'package:provider/provider.dart'; @@ -17,13 +15,6 @@ class MyPage extends StatefulWidget { } class _MyPageState extends State { - final exitBehaviorTitles = ['退出 Kazumi', '最小化至托盘', '每次都询问']; - - final setting = GStorage.setting; - - late int exitBehavior = - setting.get(SettingBoxKey.exitBehavior, defaultValue: 2); - dynamic navigationBarState; void onBackPressed(BuildContext context) { @@ -126,34 +117,6 @@ class _MyPageState extends State { SettingsSection( title: const Text('其他'), tiles: [ - SettingsTile.navigation( - leading: const Icon(Icons.exit_to_app), - title: const Text('退出设置'), - description: const Text('设置退出默认行为'), - value: Text(exitBehaviorTitles[exitBehavior]), - onPressed: (_) { - KazumiDialog.show(builder: (context) { - return SimpleDialog( - title: const Text('退出行为'), - children: [ - for (int i = 0; i < 3; i++) - RadioListTile( - value: i, - groupValue: exitBehavior, - onChanged: (int? value) { - exitBehavior = value!; - setting.put( - SettingBoxKey.exitBehavior, value); - Navigator.pop(context); - setState(() {}); - }, - title: Text(exitBehaviorTitles[i]), - ), - ], - ); - }); - }, - ), SettingsTile.navigation( onPressed: (_) { Modular.to.pushNamed('/settings/about/'); From e9acb7e3d72ab8c015f02593734788538867793e Mon Sep 17 00:00:00 2001 From: garylkz <37288203+garylkz@users.noreply.github.com> Date: Sat, 1 Feb 2025 17:05:38 +0800 Subject: [PATCH 8/8] Hide "default action" section on non-desktop platforms as there are no other options for other platforms now --- lib/pages/about/about_page.dart | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/pages/about/about_page.dart b/lib/pages/about/about_page.dart index a42877a1..fcb9cd52 100644 --- a/lib/pages/about/about_page.dart +++ b/lib/pages/about/about_page.dart @@ -188,10 +188,11 @@ class _AboutPageState extends State { ), ], ), - SettingsSection( - title: const Text('默认行为'), - tiles: [ - if (Utils.isDesktop()) + if (Utils.isDesktop()) // 之后如果有非桌面平台的新选项可以移除 + SettingsSection( + title: const Text('默认行为'), + tiles: [ + // if (Utils.isDesktop()) SettingsTile.navigation( title: const Text('关闭时'), value: Text(exitBehaviorTitles[exitBehavior]), @@ -218,8 +219,8 @@ class _AboutPageState extends State { }); }, ), - ], - ), + ], + ), SettingsSection( tiles: [ SettingsTile.navigation(