diff --git a/assets/translations/en.json b/assets/translations/en.json index db1cab0..900b94c 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -415,5 +415,7 @@ "channelDirectMessageDescription": "Direct Message with {}", "fieldCannotBeEmpty": "This field cannot be empty.", "termAcceptLink": "View terms", - "termAcceptNextWithAgree": "By clicking the \"Next\", it means you agree to our terms and its updates." + "termAcceptNextWithAgree": "By clicking the \"Next\", it means you agree to our terms and its updates.", + "unauthorized": "Unauthorized", + "unauthorizedDescription": "Login to explore the entire Solar Network." } diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 6931da4..d35f624 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -415,5 +415,7 @@ "channelDirectMessageDescription": "与 {} 的私聊", "fieldCannotBeEmpty": "此字段不能为空。", "termAcceptLink": "浏览条款", - "termAcceptNextWithAgree": "点击 “下一步”,即表示你同意我们的各项条款,包括其之后的更新。" + "termAcceptNextWithAgree": "点击 “下一步”,即表示你同意我们的各项条款,包括其之后的更新。", + "unauthorized": "未登陆", + "unauthorizedDescription": "登陆以探索整个 Solar Network。" } diff --git a/lib/screens/chat.dart b/lib/screens/chat.dart index c31ba73..99fc8b3 100644 --- a/lib/screens/chat.dart +++ b/lib/screens/chat.dart @@ -13,6 +13,7 @@ import 'package:surface/widgets/account/account_select.dart'; import 'package:surface/widgets/app_bar_leading.dart'; import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/loading_indicator.dart'; +import 'package:surface/widgets/unauthorized_hint.dart'; import 'package:uuid/uuid.dart'; import '../providers/sn_network.dart'; @@ -34,6 +35,12 @@ class _ChatScreenState extends State { Map? _lastMessages; void _refreshChannels() { + final ua = context.read(); + if (!ua.isAuthorized) { + setState(() => _isBusy = false); + return; + } + final chan = context.read(); chan.fetchChannels().listen((channels) async { final lastMessages = await chan.getLastMessages(channels); @@ -112,6 +119,18 @@ class _ChatScreenState extends State { final ud = context.read(); final ua = context.read(); + if (!ua.isAuthorized) { + return Scaffold( + appBar: AppBar( + leading: AutoAppBarLeading(), + title: Text('screenChat').tr(), + ), + body: Center( + child: UnauthorizedHint(), + ), + ); + } + return Scaffold( appBar: AppBar( leading: AutoAppBarLeading(), diff --git a/lib/screens/friend.dart b/lib/screens/friend.dart index c1f2b1a..4c44eb7 100644 --- a/lib/screens/friend.dart +++ b/lib/screens/friend.dart @@ -12,6 +12,9 @@ import 'package:surface/widgets/app_bar_leading.dart'; import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/loading_indicator.dart'; +import '../providers/userinfo.dart'; +import '../widgets/unauthorized_hint.dart'; + const kFriendStatus = { 0: 'friendStatusPending', 1: 'friendStatusActive', @@ -34,6 +37,9 @@ class _FriendScreenState extends State { List _blocks = List.empty(); Future _fetchRelations() async { + final ua = context.read(); + if (!ua.isAuthorized) return; + setState(() => _isBusy = true); try { @@ -51,6 +57,9 @@ class _FriendScreenState extends State { } Future _fetchRequests() async { + final ua = context.read(); + if (!ua.isAuthorized) return; + setState(() => _isBusy = true); try { @@ -68,6 +77,9 @@ class _FriendScreenState extends State { } Future _fetchBlocks() async { + final ua = context.read(); + if (!ua.isAuthorized) return; + setState(() => _isBusy = true); try { @@ -165,6 +177,20 @@ class _FriendScreenState extends State { @override Widget build(BuildContext context) { + final ua = context.read(); + + if (!ua.isAuthorized) { + return Scaffold( + appBar: AppBar( + leading: AutoAppBarLeading(), + title: Text('screenFriend').tr(), + ), + body: Center( + child: UnauthorizedHint(), + ), + ); + } + return Scaffold( appBar: AppBar( leading: AutoAppBarLeading(), diff --git a/lib/screens/notification.dart b/lib/screens/notification.dart index 280890b..21cf51f 100644 --- a/lib/screens/notification.dart +++ b/lib/screens/notification.dart @@ -17,6 +17,9 @@ import 'package:surface/widgets/markdown_content.dart'; import 'package:surface/widgets/post/post_item.dart'; import 'package:very_good_infinite_list/very_good_infinite_list.dart'; +import '../providers/userinfo.dart'; +import '../widgets/unauthorized_hint.dart'; + class NotificationScreen extends StatefulWidget { const NotificationScreen({super.key}); @@ -40,6 +43,9 @@ class _NotificationScreenState extends State { }; Future _fetchNotifications() async { + final ua = context.read(); + if (!ua.isAuthorized) return; + setState(() => _isBusy = true); try { @@ -62,6 +68,9 @@ class _NotificationScreenState extends State { } void _markAllAsRead() async { + final ua = context.read(); + if (!ua.isAuthorized) return; + if (_notifications.isEmpty) return; final confirm = await context.showConfirmDialog( @@ -101,6 +110,9 @@ class _NotificationScreenState extends State { } void _markOneAsRead(SnNotification notification) async { + final ua = context.read(); + if (!ua.isAuthorized) return; + if (notification.readAt != null) return; setState(() => _isSubmitting = true); @@ -131,6 +143,20 @@ class _NotificationScreenState extends State { @override Widget build(BuildContext context) { + final ua = context.read(); + + if (!ua.isAuthorized) { + return Scaffold( + appBar: AppBar( + leading: AutoAppBarLeading(), + title: Text('screenNotification').tr(), + ), + body: Center( + child: UnauthorizedHint(), + ), + ); + } + return Scaffold( appBar: AppBar( leading: AutoAppBarLeading(), diff --git a/lib/screens/realm.dart b/lib/screens/realm.dart index 64ddc8f..d9629c8 100644 --- a/lib/screens/realm.dart +++ b/lib/screens/realm.dart @@ -13,6 +13,9 @@ import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/loading_indicator.dart'; import 'package:surface/widgets/universal_image.dart'; +import '../providers/userinfo.dart'; +import '../widgets/unauthorized_hint.dart'; + class RealmScreen extends StatefulWidget { const RealmScreen({super.key}); @@ -27,6 +30,9 @@ class _RealmScreenState extends State { List? _realms; Future _fetchRealms() async { + final ua = context.read(); + if (!ua.isAuthorized) return; + setState(() => _isBusy = true); try { final sn = context.read(); @@ -75,6 +81,19 @@ class _RealmScreenState extends State { @override Widget build(BuildContext context) { final sn = context.read(); + final ua = context.read(); + + if (!ua.isAuthorized) { + return Scaffold( + appBar: AppBar( + leading: AutoAppBarLeading(), + title: Text('screenRealm').tr(), + ), + body: Center( + child: UnauthorizedHint(), + ), + ); + } return Scaffold( appBar: AppBar( diff --git a/lib/widgets/unauthorized_hint.dart b/lib/widgets/unauthorized_hint.dart new file mode 100644 index 0000000..1ac9654 --- /dev/null +++ b/lib/widgets/unauthorized_hint.dart @@ -0,0 +1,49 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:go_router/go_router.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; +import 'package:surface/widgets/dialog.dart'; + +import '../providers/userinfo.dart'; + +class UnauthorizedHint extends StatelessWidget { + const UnauthorizedHint({super.key}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + child: Container( + constraints: const BoxConstraints(maxWidth: 280), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon(Symbols.login, size: 36), + const Gap(8), + Text( + 'unauthorized', + style: Theme.of(context).textTheme.titleLarge, + ).tr(), + const Gap(8), + Text( + 'unauthorizedDescription', + style: Theme.of(context).textTheme.bodyMedium, + ).tr(), + ], + ), + ), + onTap: () { + GoRouter.of(context).pushNamed('authLogin').then((value) { + if (value == true && context.mounted) { + final ua = context.read(); + context.showSnackbar('loginSuccess'.tr(args: [ + '@${ua.user?.name} (${ua.user?.nick})', + ])); + } + }); + } + ); + } +}