From 49d1d607ce8e76805c6195945d2f7511e7e7c439 Mon Sep 17 00:00:00 2001
From: LittleSheep <littlesheep.code@hotmail.com>
Date: Sun, 8 Dec 2024 15:25:59 +0800
Subject: [PATCH] :sparkles: Auth check

---
 assets/translations/en.json        |  4 ++-
 assets/translations/zh.json        |  4 ++-
 lib/screens/chat.dart              | 19 ++++++++++++
 lib/screens/friend.dart            | 26 ++++++++++++++++
 lib/screens/notification.dart      | 26 ++++++++++++++++
 lib/screens/realm.dart             | 19 ++++++++++++
 lib/widgets/unauthorized_hint.dart | 49 ++++++++++++++++++++++++++++++
 7 files changed, 145 insertions(+), 2 deletions(-)
 create mode 100644 lib/widgets/unauthorized_hint.dart

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<ChatScreen> {
   Map<int, SnChatMessage>? _lastMessages;
 
   void _refreshChannels() {
+    final ua = context.read<UserProvider>();
+    if (!ua.isAuthorized) {
+      setState(() => _isBusy = false);
+      return;
+    }
+
     final chan = context.read<ChatChannelProvider>();
     chan.fetchChannels().listen((channels) async {
       final lastMessages = await chan.getLastMessages(channels);
@@ -112,6 +119,18 @@ class _ChatScreenState extends State<ChatScreen> {
     final ud = context.read<UserDirectoryProvider>();
     final ua = context.read<UserProvider>();
 
+    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<FriendScreen> {
   List<SnRelationship> _blocks = List.empty();
 
   Future<void> _fetchRelations() async {
+    final ua = context.read<UserProvider>();
+    if (!ua.isAuthorized) return;
+
     setState(() => _isBusy = true);
 
     try {
@@ -51,6 +57,9 @@ class _FriendScreenState extends State<FriendScreen> {
   }
 
   Future<void> _fetchRequests() async {
+    final ua = context.read<UserProvider>();
+    if (!ua.isAuthorized) return;
+
     setState(() => _isBusy = true);
 
     try {
@@ -68,6 +77,9 @@ class _FriendScreenState extends State<FriendScreen> {
   }
 
   Future<void> _fetchBlocks() async {
+    final ua = context.read<UserProvider>();
+    if (!ua.isAuthorized) return;
+
     setState(() => _isBusy = true);
 
     try {
@@ -165,6 +177,20 @@ class _FriendScreenState extends State<FriendScreen> {
 
   @override
   Widget build(BuildContext context) {
+    final ua = context.read<UserProvider>();
+
+    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<NotificationScreen> {
   };
 
   Future<void> _fetchNotifications() async {
+    final ua = context.read<UserProvider>();
+    if (!ua.isAuthorized) return;
+
     setState(() => _isBusy = true);
 
     try {
@@ -62,6 +68,9 @@ class _NotificationScreenState extends State<NotificationScreen> {
   }
 
   void _markAllAsRead() async {
+    final ua = context.read<UserProvider>();
+    if (!ua.isAuthorized) return;
+
     if (_notifications.isEmpty) return;
 
     final confirm = await context.showConfirmDialog(
@@ -101,6 +110,9 @@ class _NotificationScreenState extends State<NotificationScreen> {
   }
 
   void _markOneAsRead(SnNotification notification) async {
+    final ua = context.read<UserProvider>();
+    if (!ua.isAuthorized) return;
+
     if (notification.readAt != null) return;
 
     setState(() => _isSubmitting = true);
@@ -131,6 +143,20 @@ class _NotificationScreenState extends State<NotificationScreen> {
 
   @override
   Widget build(BuildContext context) {
+    final ua = context.read<UserProvider>();
+
+    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<RealmScreen> {
   List<SnRealm>? _realms;
 
   Future<void> _fetchRealms() async {
+    final ua = context.read<UserProvider>();
+    if (!ua.isAuthorized) return;
+
     setState(() => _isBusy = true);
     try {
       final sn = context.read<SnNetworkProvider>();
@@ -75,6 +81,19 @@ class _RealmScreenState extends State<RealmScreen> {
   @override
   Widget build(BuildContext context) {
     final sn = context.read<SnNetworkProvider>();
+    final ua = context.read<UserProvider>();
+
+    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<UserProvider>();
+            context.showSnackbar('loginSuccess'.tr(args: [
+              '@${ua.user?.name} (${ua.user?.nick})',
+            ]));
+          }
+        });
+      }
+    );
+  }
+}