Browse Source

[new]增加定位丢失查看原因弹窗&增加轨迹折叠展开功能

zk 5 months ago
parent
commit
ef3fd3b5d6

BIN
assets/images/bg_dialog_track_error.webp


BIN
assets/images/img_track_no_data.webp


+ 12 - 0
assets/string/base/string.xml

@@ -325,4 +325,16 @@
     <string name="track_detail_mobile">移动网络</string>
     <string name="track_detail_error">当前对方定位丢失</string>
     <string name="track_detail_time_proportion">地点占比时长</string>
+    <string name="track_detail_no_data">当前暂无其他更新信息</string>
+    <string name="track_detail_see_error">查看原因</string>
+    <string name="dialog_track_error_title">定位规则</string>
+    <string name="dialog_track_error_tip1">定位权限问题</string>
+    <string name="dialog_track_error_tip2">手机关机</string>
+    <string name="dialog_track_error_tip3">卸载app</string>
+    <string name="dialog_track_error_tip1_desc">请检查对方定位权限是否为始终允许</string>
+    <string name="dialog_track_error_tip2_desc">尝试给TA打电话,确认手机是否关机</string>
+    <string name="dialog_track_error_tip3_desc">
+        若对方卸载app,轨迹行程待TA重新下载恢复定位后,将会重新展示TA行程
+    </string>
+    <string name="dialog_track_error_btn_txt">我知道了</string>
 </resources>

+ 115 - 0
lib/dialog/track_error_tips_dialog.dart

@@ -0,0 +1,115 @@
+import 'package:flutter/cupertino.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:location/resource/assets.gen.dart';
+import 'package:location/resource/colors.gen.dart';
+import 'package:location/resource/string.gen.dart';
+import 'package:location/utils/common_expand.dart';
+
+import '../utils/common_style.dart';
+
+class TrackErrorTipsDialog {
+  static const String _tag = 'TrackErrorTipsDialog';
+
+  static void show() {
+    SmartDialog.show(
+      tag: _tag,
+      maskColor: ColorName.black80,
+      builder: (_) => _TrackErrorTipsView(),
+    );
+  }
+
+  static void dismiss() {
+    SmartDialog.dismiss(tag: _tag);
+  }
+}
+
+class _TrackErrorTipsView extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: 274.w,
+      decoration: BoxDecoration(
+          borderRadius: BorderRadius.circular(16.r),
+          border: Border.all(
+            color: ColorName.white,
+            width: 3.w,
+          ),
+          gradient: LinearGradient(colors: [
+            '#E4E4FF'.color,
+            ColorName.white,
+          ], stops: const [
+            0.0,
+            0.2
+          ], begin: Alignment.topCenter, end: Alignment.bottomCenter)),
+      child: Stack(
+        children: [
+          Assets.images.bgDialogTrackError.image(width: double.infinity),
+          Container(
+            width: double.infinity,
+            padding: EdgeInsets.symmetric(horizontal: 17.w),
+            child: IntrinsicHeight(
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  SizedBox(height: 24.w),
+                  Align(
+                    alignment: Alignment.center,
+                    child: Text(
+                      StringName.dialogTrackErrorTitle,
+                      style: TextStyle(
+                          fontSize: 17.sp,
+                          color: '#333333'.color,
+                          fontWeight: FontWeight.bold),
+                    ),
+                  ),
+                  SizedBox(height: 35.w),
+                  buildTip(StringName.dialogTrackErrorTip1),
+                  buildTipDesc(StringName.dialogTrackErrorTip1Desc),
+                  buildTip(StringName.dialogTrackErrorTip2),
+                  buildTipDesc(StringName.dialogTrackErrorTip2Desc),
+                  buildTip(StringName.dialogTrackErrorTip3),
+                  buildTipDesc(StringName.dialogTrackErrorTip3Desc),
+                  SizedBox(height: 7.w),
+                  GestureDetector(
+                    onTap: () {
+                      TrackErrorTipsDialog.dismiss();
+                    },
+                    child: Container(
+                        decoration: getPrimaryBtnDecoration(100.r),
+                        width: double.infinity,
+                        height: 40.w,
+                        child: Center(
+                            child: Text(StringName.dialogTrackErrorBtnTxt,
+                                style: TextStyle(
+                                    fontSize: 14.sp, color: ColorName.white)))),
+                  ),
+                  SizedBox(height: 20.w),
+                ],
+              ),
+            ),
+          )
+        ],
+      ),
+    );
+  }
+
+  Widget buildTip(String title) {
+    return Container(
+      margin: EdgeInsets.only(bottom: 6.w),
+      child: Text(title,
+          style: TextStyle(
+              fontSize: 13.sp,
+              color: '#404040'.color,
+              fontWeight: FontWeight.bold)),
+    );
+  }
+
+  Widget buildTipDesc(String desc) {
+    return Container(
+      margin: EdgeInsets.only(bottom: 24.w),
+      child:
+          Text(desc, style: TextStyle(fontSize: 12.sp, color: '#666666'.color)),
+    );
+  }
+}

+ 21 - 9
lib/module/track/track_day_detail/track_daily_item.dart

@@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:location/data/bean/track_daily_bean.dart';
 import 'package:location/data/consts/constants.dart';
+import 'package:location/dialog/track_error_tips_dialog.dart';
 import 'package:location/module/track/track_util.dart';
 import 'package:location/resource/assets.gen.dart';
 import 'package:location/resource/colors.gen.dart';
@@ -24,14 +25,14 @@ Widget buildTrackDailyItem(TrackDailyBean bean, bool isEnd) {
           if (bean.status == TrackStatus.moving) {
             return _buildMovingTrackDailyItem(bean);
           } else if (bean.status == TrackStatus.stay) {
-            return _buildStayTrackDailyItem(bean);
-          } else if (bean.status == TrackStatus.abnormal) {
-            return _buildAbnormalTrackDailyItem(bean);
+            return buildStayTrackDailyItem(bean);
+          } else if (bean.status == TrackStatus.error) {
+            return buildErrorTrackDailyItem(bean);
           } else {
             return SizedBox(height: 50.w, child: Text('未知轨迹,请更新最新应用版本'));
           }
         }),
-        if (isEnd) _buildEndPoint(bean)
+        if (isEnd) buildEndPoint(bean)
       ],
     ),
   );
@@ -95,7 +96,8 @@ Widget _buildMovingTrackDailyItem(TrackDailyBean bean) {
   );
 }
 
-Widget _buildStayTrackDailyItem(TrackDailyBean bean) {
+Widget buildStayTrackDailyItem(TrackDailyBean bean,
+    {EdgeInsetsGeometry? contentPadding}) {
   return Column(
     crossAxisAlignment: CrossAxisAlignment.start,
     children: [
@@ -123,7 +125,7 @@ Widget _buildStayTrackDailyItem(TrackDailyBean bean) {
             Expanded(
                 child: Container(
               padding: EdgeInsets.all(10.w),
-              margin: EdgeInsets.only(top: 20.w),
+              margin: contentPadding ?? EdgeInsets.only(top: 20.w),
               decoration: BoxDecoration(
                   borderRadius: BorderRadius.circular(8.r),
                   gradient: LinearGradient(colors: [
@@ -166,7 +168,8 @@ Widget _buildStayTrackDailyItem(TrackDailyBean bean) {
   );
 }
 
-Widget _buildAbnormalTrackDailyItem(TrackDailyBean bean) {
+Widget buildErrorTrackDailyItem(TrackDailyBean bean,
+    {EdgeInsetsGeometry? contentPadding}) {
   return Column(
     crossAxisAlignment: CrossAxisAlignment.start,
     children: [
@@ -195,7 +198,7 @@ Widget _buildAbnormalTrackDailyItem(TrackDailyBean bean) {
                 child: Container(
               height: 50.w,
               padding: EdgeInsets.all(10.w),
-              margin: EdgeInsets.only(top: 41.w, bottom: 7.w),
+              margin: contentPadding ?? EdgeInsets.only(top: 41.w, bottom: 7.w),
               decoration: BoxDecoration(
                   borderRadius: BorderRadius.circular(8.r),
                   gradient: LinearGradient(colors: [
@@ -212,6 +215,15 @@ Widget _buildAbnormalTrackDailyItem(TrackDailyBean bean) {
                           color: '#333333'.color,
                           fontWeight: FontWeight.bold)),
                   SizedBox(width: 10.w),
+                  GestureDetector(
+                    onTap: () {
+                      TrackErrorTipsDialog.show();
+                    },
+                    child: Text(
+                      StringName.trackDetailSeeError,
+                      style: TextStyle(fontSize: 11.sp, color: '#4476FF'.color),
+                    ),
+                  ),
                   Spacer(),
                   Assets.images.imgTrackAiAnalyse.image(width: 73.w),
                   SizedBox(width: 6.w),
@@ -248,7 +260,7 @@ Widget _buildTimeText(int time) {
   );
 }
 
-Widget _buildEndPoint(TrackDailyBean bean) {
+Widget buildEndPoint(TrackDailyBean bean) {
   return Column(
     children: [
       SizedBox(height: 4.w),

+ 47 - 0
lib/module/track/track_day_detail/track_day_detail_controller.dart

@@ -7,8 +7,10 @@ import 'package:location/dialog/loading_dialog.dart';
 import 'package:location/handler/error_handler.dart';
 import 'package:location/module/track/track_controller.dart';
 import 'package:location/resource/string.gen.dart';
+import 'package:location/utils/pair.dart';
 
 import '../../../data/bean/track_days.dart';
+import '../track_status.dart';
 
 class TrackDayDetailController extends BaseController {
   final TrackDays days;
@@ -19,6 +21,9 @@ class TrackDayDetailController extends BaseController {
 
   final RxBool _isExpanded = RxBool(false);
   final RxBool _isRequested = RxBool(false);
+  final RxBool _isHideExpand = RxBool(false);
+
+  bool get isHideExpand => _isHideExpand.value;
 
   bool get isRequested => _isRequested.value;
 
@@ -26,6 +31,11 @@ class TrackDayDetailController extends BaseController {
 
   bool get trackNoData => _trackNoData.value;
 
+  final Rxn<Pair<TrackExpandType, TrackDailyBean>> _expandSituation = Rxn();
+
+  Pair<TrackExpandType, TrackDailyBean>? get expandSituation =>
+      _expandSituation.value;
+
   final TrackController trackController = Get.find<TrackController>();
 
   TrackDayDetailController(this.days, bool isExpand) {
@@ -52,6 +62,11 @@ class TrackDayDetailController extends BaseController {
       _isRequested.value = true;
       _trackNoData.value = (list == null || list.isEmpty == true);
       trackDailyList.assignAll(list ?? []);
+      if (list != null && list.length == 1) {
+        _isExpanded.value = true;
+        _isHideExpand.value = true;
+      }
+      _dealTrackExpandData();
     }).catchError((error) {
       CustomLoadingDialog.hide();
       _isRequested.value = false;
@@ -59,6 +74,38 @@ class TrackDayDetailController extends BaseController {
     });
   }
 
+  void _dealTrackExpandData() {
+    final list = trackDailyList;
+    if (list.isNotEmpty && list.length > 1) {
+      TrackExpandType? expandType;
+      TrackDailyBean? expandBean;
+      for (var i = 0; i < list.length; i++) {
+        final bean = list[i];
+        if (bean.status == TrackStatus.error) {
+          expandType = TrackExpandType.error;
+          expandBean = bean;
+          break;
+        } else if (bean.status == TrackStatus.stay) {
+          if (expandBean == null) {
+            expandType = TrackExpandType.stay;
+            expandBean = bean;
+          }
+          continue;
+        }
+      }
+      if (expandType != null && expandBean != null) {
+        if (expandType == TrackExpandType.error &&
+            list.indexOf(expandBean) == list.length - 1) {
+          expandType = TrackExpandType.errorNow;
+        } else if (expandType == TrackExpandType.stay &&
+            list.indexOf(expandBean) == list.length - 1) {
+          expandType = TrackExpandType.stayNow;
+        }
+        _expandSituation.value = Pair(expandType, expandBean);
+      }
+    }
+  }
+
   void onTrackDetailFoldClick() {
     _isExpanded.value = !_isExpanded.value;
   }

+ 59 - 11
lib/module/track/track_day_detail/track_day_detail_view.dart

@@ -9,7 +9,9 @@ import 'package:location/data/bean/track_days.dart';
 import 'package:location/module/track/track_day_detail/time_proportion/time_proportion_view.dart';
 import 'package:location/module/track/track_day_detail/track_daily_item.dart';
 import 'package:location/module/track/track_day_detail/track_day_detail_controller.dart';
+import 'package:location/module/track/track_status.dart';
 import 'package:location/resource/assets.gen.dart';
+import 'package:location/resource/colors.gen.dart';
 import 'package:location/resource/string.gen.dart';
 import 'package:location/utils/common_expand.dart';
 
@@ -61,21 +63,58 @@ class TrackDayDetailView extends BaseView<TrackDayDetailController> {
             )
           ],
         ),
-        buildFoldView(),
+        _buildFoldBtn(),
       ],
     );
   }
 
+  Widget _buildFoldContentView() {
+    return Obx(() {
+      return Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Builder(builder: (context) {
+            if (controller.expandSituation != null) {
+              if (controller.expandSituation!.first == TrackExpandType.error ||
+                  controller.expandSituation!.first ==
+                      TrackExpandType.errorNow) {
+                return buildErrorTrackDailyItem(
+                    controller.expandSituation!.second,
+                    contentPadding: EdgeInsets.only(top: 46.w, bottom: 12.w));
+              } else {
+                return buildStayTrackDailyItem(
+                    controller.expandSituation!.second,
+                    contentPadding: EdgeInsets.only(top: 35.w));
+              }
+            } else {
+              return SizedBox.shrink();
+            }
+          }),
+          if (controller.expandSituation != null &&
+              (controller.expandSituation?.first == TrackExpandType.error ||
+                  controller.expandSituation?.first == TrackExpandType.stay))
+            buildEndPoint(controller.expandSituation!.second)
+        ],
+      );
+    });
+  }
+
   Widget _buildTrackNoData() {
-    return Container(
-      child: Text('无数据'),
+    return Column(
+      children: [
+        SizedBox(height: 0.048.sh),
+        Assets.images.imgTrackNoData.image(width: 78.5.w),
+        SizedBox(height: 7.w),
+        Text(StringName.trackDetailNoData,
+            style: TextStyle(fontSize: 11.sp, color: ColorName.black60))
+      ],
     );
   }
 
-  Widget buildFoldView() {
+  Widget _buildFoldBtn() {
     return Obx(() {
       return Visibility(
-        visible: !controller.trackNoData,
+        visible: !controller.trackNoData && !controller.isHideExpand,
         child: Positioned(
           top: 2.w,
           right: 5.w,
@@ -118,12 +157,21 @@ class TrackDayDetailView extends BaseView<TrackDayDetailController> {
 
   Widget buildSliverHistoryTrack() {
     return Obx(() {
-      return SliverPadding(
-        padding: EdgeInsets.only(top: 20.w, bottom: 12.w),
-        sliver: SliverList.builder(
-            itemBuilder: buildHistoryTrackItem,
-            itemCount: controller.trackDailyList.length),
-      );
+      if (controller.isExpanded) {
+        return SliverPadding(
+          padding: EdgeInsets.only(top: 20.w, bottom: 12.w),
+          sliver: SliverList.builder(
+              itemBuilder: buildHistoryTrackItem,
+              itemCount: controller.trackDailyList.length),
+        );
+      } else {
+        return SliverPadding(
+            padding: EdgeInsets.only(
+                top: 20.w, bottom: 12.w, left: 12.w, right: 12.w),
+            sliver: SliverToBoxAdapter(
+              child: _buildFoldContentView(),
+            ));
+      }
     });
   }
 

+ 3 - 1
lib/module/track/track_status.dart

@@ -2,5 +2,7 @@
 abstract class TrackStatus {
   static const int moving = 0;
   static const int stay = 1;
-  static const int abnormal = 2;
+  static const int error = 2;
 }
+
+enum TrackExpandType { error, stay, stayNow, errorNow }

+ 11 - 1
lib/resource/assets.gen.dart

@@ -24,6 +24,10 @@ class $AssetsImagesGen {
   AssetGenImage get bgDialogLocationPermissionIos => const AssetGenImage(
       'assets/images/bg_dialog_location_permission_ios.webp');
 
+  /// File path: assets/images/bg_dialog_track_error.webp
+  AssetGenImage get bgDialogTrackError =>
+      const AssetGenImage('assets/images/bg_dialog_track_error.webp');
+
   /// File path: assets/images/bg_friend_item.webp
   AssetGenImage get bgFriendItem =>
       const AssetGenImage('assets/images/bg_friend_item.webp');
@@ -528,11 +532,16 @@ class $AssetsImagesGen {
   AssetGenImage get imgTrackExample =>
       const AssetGenImage('assets/images/img_track_example.webp');
 
+  /// File path: assets/images/img_track_no_data.webp
+  AssetGenImage get imgTrackNoData =>
+      const AssetGenImage('assets/images/img_track_no_data.webp');
+
   /// List of all assets
   List<AssetGenImage> get values => [
         bgAddFriendDialog,
         bgCheckLocationPermission,
         bgDialogLocationPermissionIos,
+        bgDialogTrackError,
         bgFriendItem,
         bgLoginHeadContainer,
         bgMemberHeader,
@@ -658,7 +667,8 @@ class $AssetsImagesGen {
         imgMemberRetainContainer,
         imgMemberUserCancelsContainer,
         imgTrackAiAnalyse,
-        imgTrackExample
+        imgTrackExample,
+        imgTrackNoData
       ];
 }
 

+ 1 - 1
lib/socket/atmob_location_client.dart

@@ -209,7 +209,7 @@ class AtmobLocationClient {
     if (_webSocket == null) {
       return;
     }
-    // _webSocket!.sink.add(msg);
+    _webSocket!.sink.add(msg);
     AtmobLog.d(tag, 'send location: $msg');
   }