diff --git a/summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/settings_page/components/host_setting.dart b/summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/settings_page/components/host_setting.dart index ac75e2d8e..74b79e3e8 100644 --- a/summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/settings_page/components/host_setting.dart +++ b/summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/settings_page/components/host_setting.dart @@ -11,6 +11,8 @@ class _SetHostDialogState extends State<_SetHostDialog> { final hostEditingController = TextEditingController(text: MaxKeyPersistent.instance.host); + bool isTesting = false; + /// true: 连接成功;false:链接失败 bool testResult = true; String? testDesc; @@ -35,26 +37,41 @@ class _SetHostDialogState extends State<_SetHostDialog> { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextButton( - onPressed: () async { - final result = await MaxKey.instance - .maxKeyNetworkTest(host: hostEditingController.text); - setState(() { - testResult = result; - testDesc = result - ? AppLocalizations.of(context)! - .settingsPageHostSettingDialogTestSucceed - : AppLocalizations.of(context)! - .settingsPageHostSettingDialogTestFail; - }); - }, - child: Text(AppLocalizations.of(context)!.settingsPageHostSettingDialogTestBtn), + TextButton.icon( + onPressed: isTesting + ? null + : () async { + setState(() { + isTesting = true; + }); + final result = await MaxKey.instance + .maxKeyNetworkTest(host: hostEditingController.text); + setState(() { + isTesting = false; + testResult = result; + testDesc = result + ? AppLocalizations.of(context)! + .settingsPageHostSettingDialogTestSucceed + : AppLocalizations.of(context)! + .settingsPageHostSettingDialogTestFail; + }); + }, + icon: isTesting + ? const SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : null, + label: Text(AppLocalizations.of(context)! + .settingsPageHostSettingDialogTestBtn), ), Row( children: [ TextButton( onPressed: Navigator.of(context).pop, - child: Text(AppLocalizations.of(context)!.settingsPageHostSettingDialogCancleBtn), + child: Text(AppLocalizations.of(context)! + .settingsPageHostSettingDialogCancleBtn), ), const SizedBox(width: 8.0), TextButton( @@ -66,7 +83,8 @@ class _SetHostDialogState extends State<_SetHostDialog> { Navigator.of(context).pop(); } }, - child: Text(AppLocalizations.of(context)!.settingsPageHostSettingDialogConfirmBtn), + child: Text(AppLocalizations.of(context)! + .settingsPageHostSettingDialogConfirmBtn), ), ], ) diff --git a/summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/user_page/page.dart b/summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/user_page/page.dart index 93a62a71c..9fc01a3f6 100644 --- a/summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/user_page/page.dart +++ b/summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/user_page/page.dart @@ -34,7 +34,7 @@ class UserPage extends StatelessWidget { _UserCard(user: user!), _UserPageButtonTile( title: AppLocalizations.of(context)!.userPageUserInfoBtn, - trailing: Icons.info, + trailing: const Icon(Icons.info), onTap: () async { final userInfo = await MaxKey.instance.usersService .getFullUserInfo(); @@ -55,23 +55,13 @@ class UserPage extends StatelessWidget { const SizedBox(height: 8.0), _UserPageButtonTile( title: AppLocalizations.of(context)!.userPageSettingsBtn, - trailing: Icons.settings, + trailing: const Icon(Icons.settings), onTap: () { context.push(RoutePath.settingsPage); }, ), const SizedBox(height: 8.0), - _UserPageButtonTile( - title: AppLocalizations.of(context)!.userPageLogoutBtn, - trailing: Icons.logout, - onTap: () async { - await MaxKey.instance.authnService.logout(); - - if (context.mounted) { - context.pushReplacement(RoutePath.loginPage); - } - }, - ) + const _LogoutBtn(), ]), ), ), @@ -79,17 +69,56 @@ class UserPage extends StatelessWidget { } } +class _LogoutBtn extends StatefulWidget { + const _LogoutBtn({super.key}); + + @override + State<_LogoutBtn> createState() => _LogoutBtnState(); +} + +class _LogoutBtnState extends State<_LogoutBtn> { + bool isLogouting = false; + @override + Widget build(BuildContext context) { + return _UserPageButtonTile( + title: AppLocalizations.of(context)!.userPageLogoutBtn, + trailing: isLogouting + ? const SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : const Icon(Icons.logout), + onTap: isLogouting + ? null + : () async { + setState(() { + isLogouting = true; + }); + await MaxKey.instance.authnService.logout(); + setState(() { + isLogouting = false; + }); + if (context.mounted) { + Navigator.of(context).pop(); + context.pushReplacement(RoutePath.loginPage); + } + }, + ); + } +} + class _UserPageButtonTile extends StatelessWidget { const _UserPageButtonTile({ super.key, required this.title, required this.trailing, - required this.onTap, + this.onTap, }); final String title; - final IconData trailing; - final void Function() onTap; + final Widget trailing; + final void Function()? onTap; @override Widget build(BuildContext context) { @@ -100,7 +129,7 @@ class _UserPageButtonTile extends StatelessWidget { ), tileColor: scheme.surfaceContainer, title: Text(title), - trailing: Icon(trailing), + trailing: trailing, onTap: onTap, ); }