Browse Source

feat: 添加桌面端点击刷新

Tony 1 tháng trước cách đây
mục cha
commit
b2f617f80e

+ 21 - 0
lib/app/modules/node/controllers/node_controller.dart

@@ -1,12 +1,14 @@
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import '../../../constants/iconfont/iconfont.dart';
+import '../../../controllers/api_controller.dart';
 import '../../../controllers/core_controller.dart';
 import '../../../data/models/launch/groups.dart';
 import '../../../data/sp/ix_sp.dart';
 
 class NodeController extends GetxController {
   final coreController = Get.find<CoreController>();
+  final ApiController _apiController = Get.find<ApiController>();
   // Groups 数据
   final _groups = Rxn<Groups>();
   Groups? get groups => _groups.value;
@@ -31,6 +33,10 @@ class NodeController extends GetxController {
     return tabTextList[currentTabIndex];
   }
 
+  // 列表刷新状态
+  final _isRefreshing = false.obs;
+  bool get isRefreshing => _isRefreshing.value;
+
   @override
   void onInit() {
     super.onInit();
@@ -110,4 +116,19 @@ class NodeController extends GetxController {
     currentTabIndex = tabIndex;
     coreController.locationSelectionType = tabTextList[tabIndex];
   }
+
+  /// 主动刷新列表
+  void refreshLocations() async {
+    try {
+      _isRefreshing.value = true;
+      final groups = await _apiController.getLocations();
+      updateGroups(groups);
+      _isRefreshing.value = false;
+    } catch (_) {
+      // TODO: 捕捉异常写入日志
+      Future.delayed(const Duration(seconds: 1), () {
+        _isRefreshing.value = false;
+      });
+    }
+  }
 }

+ 35 - 1
lib/app/modules/node/views/node_view.dart

@@ -2,8 +2,11 @@ import 'package:flutter/material.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:get/get.dart';
 import 'package:nomo/config/theme/theme_extensions/theme_extension.dart';
+import 'package:nomo/utils/misc.dart';
+
 import '../../../../config/translations/strings_enum.dart';
 import '../../../base/base_view.dart';
+import '../../../widgets/click_opacity.dart';
 import '../../../widgets/ix_app_bar.dart';
 import '../controllers/node_controller.dart';
 import '../widgets/node_list.dart';
@@ -12,7 +15,23 @@ class NodeView extends BaseView<NodeController> {
   const NodeView({super.key});
 
   @override
-  PreferredSizeWidget? get appBar => IXAppBar(title: Strings.selectServer.tr);
+  PreferredSizeWidget? get appBar => IXAppBar(
+    title: Strings.selectServer.tr,
+    actions: [
+      if (isDesktop)
+        ClickOpacity(
+          child: Padding(
+            padding: EdgeInsets.symmetric(horizontal: 16.w),
+            child: Icon(
+              Icons.refresh,
+              size: 20.w,
+              color: Get.reactiveTheme.hintColor,
+            ),
+          ),
+          onTap: () => controller.refreshLocations(),
+        ),
+    ],
+  );
 
   @override
   Widget buildContent(BuildContext context) {
@@ -25,6 +44,7 @@ class NodeView extends BaseView<NodeController> {
       initialIndex: controller.currentTabIndex, // 恢复上次的 Tab 位置
       child: Column(
         children: [
+          if (isDesktop) _buildRefreshingIndicator(),
           _buildTabs(),
           Expanded(child: _buildTabBarView()),
         ],
@@ -32,6 +52,20 @@ class NodeView extends BaseView<NodeController> {
     );
   }
 
+  Widget _buildRefreshingIndicator() {
+    return Obx(
+      () => controller.isRefreshing
+          ? LinearProgressIndicator(
+              backgroundColor: Get.reactiveTheme.scaffoldBackgroundColor,
+              minHeight: 2.w,
+              valueColor: AlwaysStoppedAnimation<Color>(
+                Get.reactiveTheme.primaryColor,
+              ),
+            )
+          : const SizedBox(height: 2),
+    );
+  }
+
   Widget _buildTabs() {
     return TabBar(
       splashFactory: NoSplash.splashFactory,