diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index 9c79d0e..5ec4fc3 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -215,8 +215,9 @@ "sensitiveContentCollapsed": "Sensitive content has been collapsed.", "sensitiveContentDescription": "This content has been marked as sensitive, and may not be suitable for all viewers.", "sensitiveContentReveal": "Reveal", - "serverConnecting": "Connecting to server...", - "serverDisconnected": "Lost connection from server", + "serverConnecting": "Connecting...", + "serverDisconnected": "Connection Lost", + "serverConnected": "Connected", "fieldChatAlias": "Channel Alias", "fieldChatAliasHint": "The unique channel alias within the site, used to represent the channel in URL, leave blank to auto generate. Should be URL-Safe.", "fieldChatName": "Name", diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index 0506b4d..9108716 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -213,8 +213,9 @@ "sensitiveContentCollapsed": "敏感内容已折叠。", "sensitiveContentDescription": "此内容已被标记,可能不适合所有人查看。", "sensitiveContentReveal": "显示内容", - "serverConnecting": "正在连接服务器…", - "serverDisconnected": "已与服务器断开连接", + "serverConnecting": "正在连接…", + "serverDisconnected": "已断开连接", + "serverConnected": "已连接", "fieldChatAlias": "频道别名", "fieldChatAliasHint": "全站范围内唯一的频道别名,用于在 URL 中表示该频道,留空则自动生成。应遵循 URL-Safe 的原则。", "fieldChatName": "名称", diff --git a/lib/widgets/connection_indicator.dart b/lib/widgets/connection_indicator.dart index 25a3704..db6d7d2 100644 --- a/lib/widgets/connection_indicator.dart +++ b/lib/widgets/connection_indicator.dart @@ -1,5 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:surface/providers/userinfo.dart'; @@ -18,13 +20,9 @@ class ConnectionIndicator extends StatelessWidget { final ua = context.read(); return GestureDetector( - child: Container( - padding: EdgeInsets.only( - bottom: 8, - top: MediaQuery.of(context).padding.top + 8, - left: 24, - right: 24, - ), + child: Material( + elevation: 2, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), color: Theme.of(context).colorScheme.secondaryContainer, child: ua.isAuthorized ? Row( @@ -32,21 +30,25 @@ class ConnectionIndicator extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ if (ws.isBusy) - Text('serverConnecting').tr().textColor( - Theme.of(context).colorScheme.onSecondaryContainer) + Text('serverConnecting').tr().textColor(Theme.of(context).colorScheme.onSecondaryContainer) else if (!ws.isConnected) - Text('serverDisconnected').tr().textColor( - Theme.of(context).colorScheme.onSecondaryContainer), + Text('serverDisconnected').tr().textColor(Theme.of(context).colorScheme.onSecondaryContainer) + else + Text('serverConnected').tr().textColor(Theme.of(context).colorScheme.onSecondaryContainer), + const Gap(8), + if (ws.isBusy) + const CircularProgressIndicator(strokeWidth: 2.5) + .width(12) + .height(12) + .padding(horizontal: 4, right: 4) + else if (!ws.isConnected) + const Icon(Symbols.power_off, size: 18) + else + const Icon(Symbols.power, size: 18), ], - ) + ).padding(horizontal: 8, vertical: 4) : const SizedBox.shrink(), - ) - .height( - (ws.isBusy || !ws.isConnected) && ua.isAuthorized - ? MediaQuery.of(context).padding.top + 36 - : 0, - animate: true) - .animate( + ).opacity((ws.isBusy || !ws.isConnected) && ua.isAuthorized ? 1 : 0, animate: true).animate( const Duration(milliseconds: 300), Curves.easeInOut, ), diff --git a/lib/widgets/navigation/app_scaffold.dart b/lib/widgets/navigation/app_scaffold.dart index 5cb9387..4e6ba12 100644 --- a/lib/widgets/navigation/app_scaffold.dart +++ b/lib/widgets/navigation/app_scaffold.dart @@ -98,56 +98,58 @@ class AppRootScaffold extends StatelessWidget { iconMouseDown: Theme.of(context).colorScheme.primary, ); + final safeTop = MediaQuery.of(context).padding.top; + return AppBackground( isRoot: true, child: Scaffold( key: globalRootScaffoldKey, - body: Column( + body: Stack( children: [ - if (!kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS)) - Container( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: Theme.of(context).dividerColor, - width: 1 / devicePixelRatio, - ), - ), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: Platform.isMacOS ? MainAxisAlignment.center : MainAxisAlignment.start, - children: [ - WindowTitleBarBox( - child: MoveWindow( - child: Text( - 'Solar Network', - style: GoogleFonts.spaceGrotesk(), - ).padding(horizontal: 12, vertical: 5), + Column( + children: [ + if (!kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS)) + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Theme.of(context).dividerColor, + width: 1 / devicePixelRatio, + ), ), ), - if (!Platform.isMacOS) - Expanded( - child: WindowTitleBarBox( - child: Row( - children: [ - Expanded(child: MoveWindow()), - Row( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: Platform.isMacOS ? MainAxisAlignment.center : MainAxisAlignment.start, + children: [ + WindowTitleBarBox( + child: MoveWindow( + child: Text( + 'Solar Network', + style: GoogleFonts.spaceGrotesk(), + ).padding(horizontal: 12, vertical: 5), + ), + ), + if (!Platform.isMacOS) + MoveWindow( + child: WindowTitleBarBox( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ MinimizeWindowButton(colors: windowButtonColor), MaximizeWindowButton(colors: windowButtonColor), CloseWindowButton(colors: windowButtonColor), ], ), - ], + ), ), - ), - ), - ], - ), - ), - ConnectionIndicator(), - Expanded(child: innerWidget), + ], + ), + ), + Expanded(child: innerWidget), + ], + ), + Positioned(top: safeTop > 0 ? safeTop : 16, right: 8, child: ConnectionIndicator()), ], ), drawer: !isExpandedDrawer ? AppNavigationDrawer() : null,