From 0c8638d423fffd63b92e9f7d4a26d57e0388543c Mon Sep 17 00:00:00 2001 From: Jolie <> Date: Tue, 18 Nov 2025 01:52:05 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9=E5=8F=91=E9=80=81?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E9=94=99=E4=BD=8D=E3=80=82=202.=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=81=8A=E5=A4=A9=E7=94=A8=E6=88=B7=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E3=80=82=203.=20=E4=BC=98=E5=8C=96=E5=A5=BD=E5=8F=8B=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle.kts | 4 +- assets/images/chat_user_bg.png | Bin 0 -> 6472 bytes assets/images/chat_user_bg_bottom.png | Bin 0 -> 9779 bytes assets/images/gift_pic.png | Bin 0 -> 28977 bytes ios/Podfile.lock | 123 ----- .../contents.xcworkspacedata | 10 - lib/controller/message/chat_controller.dart | 98 ++-- lib/generated/assets.dart | 2 + lib/pages/message/chat_page.dart | 320 ++++++++++--- lib/pages/message/conversation_tab.dart | 221 +++++++-- lib/pages/message/friend_tab.dart | 12 +- lib/widget/message/chat_input_bar.dart | 2 +- lib/widget/message/image_item.dart | 153 ++++-- lib/widget/message/message_item.dart | 20 + lib/widget/message/text_item.dart | 20 +- lib/widget/message/video_item.dart | 134 +++++- location_plugin/example/pubspec.lock | 68 +-- pubspec.lock | 444 +++++++++--------- 18 files changed, 992 insertions(+), 639 deletions(-) create mode 100644 assets/images/chat_user_bg.png create mode 100644 assets/images/chat_user_bg_bottom.png create mode 100644 assets/images/gift_pic.png delete mode 100644 ios/Podfile.lock delete mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index caaf320..77dd3e4 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -77,8 +77,8 @@ android { } // 对应:shrinkResources true / minifyEnabled true - isShrinkResources = true - isMinifyEnabled = true + isShrinkResources = false + isMinifyEnabled = false // 对应:proguardFiles "proguard-rules.pro" // 最简单写法: diff --git a/assets/images/chat_user_bg.png b/assets/images/chat_user_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..8027b3182d3dc0fd65bdf7b47b32ecc0e7817465 GIT binary patch literal 6472 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 TJba|c?0@X1p?m6f6LS9n6U%Pr literal 0 HcmV?d00001 diff --git a/assets/images/chat_user_bg_bottom.png b/assets/images/chat_user_bg_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..ede045d23fde6082056208ac1430e893ba05cabf GIT binary patch literal 9779 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 - - - - - - diff --git a/lib/controller/message/chat_controller.dart b/lib/controller/message/chat_controller.dart index 2a7dbe0..d653a37 100644 --- a/lib/controller/message/chat_controller.dart +++ b/lib/controller/message/chat_controller.dart @@ -46,6 +46,7 @@ class ChatController extends GetxController { final EMUserInfo? info = await IMManager.instance.getUserInfo(userId); if (info != null) { userInfo.value = info; + update(); // 通知 GetBuilder 更新 UI if (Get.isLogEnable) { Get.log('获取用户信息成功: ${info.nickName}'); } @@ -70,8 +71,8 @@ class ChatController extends GetxController { content: content, ); - // 将消息添加到列表开头(显示发送中状态) - messages.insert(0, tempMessage); + // 将消息添加到列表末尾(显示发送中状态) + messages.add(tempMessage); update(); // 尝试发送消息 @@ -111,8 +112,8 @@ class ChatController extends GetxController { sendOriginalImage: false, ); - // 将消息添加到列表开头(显示发送中状态) - messages.insert(0, tempMessage); + // 将消息添加到列表末尾(显示发送中状态) + messages.add(tempMessage); update(); // 尝试发送消息 @@ -155,8 +156,8 @@ class ChatController extends GetxController { duration: seconds, ); - // 将消息添加到列表开头(显示发送中状态) - messages.insert(0, tempMessage); + // 将消息添加到列表末尾(显示发送中状态) + messages.add(tempMessage); update(); // 尝试发送消息 @@ -192,25 +193,23 @@ class ChatController extends GetxController { /// 发送视频消息 Future sendVideoMessage(String filePath, int duration) async { - // 如果正在发送,防止重复发送 - if (isSendingVideo.value) { - SmartDialog.showToast('视频正在发送中,请稍候...'); - return false; - } - try { - // 设置发送状态 - isSendingVideo.value = true; - sendingStatus.value = '正在准备视频...'; - update(); - print('🎬 [ChatController] 准备发送视频消息'); print('视频路径: $filePath'); print('视频时长: $duration 秒'); - sendingStatus.value = '正在上传视频...'; + // 先创建消息对象(即使发送失败也要显示在列表中) + final tempMessage = EMMessage.createVideoSendMessage( + targetId: userId, + filePath: filePath, + duration: duration, + ); + + // 将消息添加到列表末尾(显示发送中状态) + messages.add(tempMessage); update(); + // 尝试发送消息(后台上传,消息状态会自动更新) final message = await IMManager.instance.sendVideoMessage( filePath, userId, @@ -218,50 +217,28 @@ class ChatController extends GetxController { ); if (message != null) { - print('✅ [ChatController] 视频消息创建成功'); - print('消息类型: ${message.body.type}'); - - sendingStatus.value = '发送成功'; - update(); - - // 发送成功后将消息添加到列表开头 - messages.insert(0, message); + print('✅ [ChatController] 视频消息发送成功'); + // 发送成功,替换临时消息 + final index = messages.indexWhere((msg) => msg.msgId == tempMessage.msgId); + if (index != -1) { + messages[index] = message; + } update(); - // 更新会话列表 _refreshConversationList(); - - // 显示成功提示 - SmartDialog.showToast('✅ 视频发送成功'); - return true; + } else { + // 发送失败,消息状态会自动变为FAIL + update(); + SmartDialog.showToast('视频发送失败,请点击重发'); + return false; } - - print('❌ [ChatController] 视频消息创建失败'); - sendingStatus.value = '发送失败'; - update(); - - SmartDialog.showToast('❌ 视频消息发送失败,请重试'); - - return false; } catch (e) { - print('❌ [ChatController] 发送视频消息异常: $e'); - - sendingStatus.value = '发送失败: $e'; - update(); - if (Get.isLogEnable) { Get.log('发送视频消息失败: $e'); } - - SmartDialog.showToast('❌ 视频消息发送失败: ${e.toString()}'); - + SmartDialog.showToast('视频发送失败: $e'); return false; - } finally { - // 重置发送状态 - isSendingVideo.value = false; - sendingStatus.value = ''; - update(); } } @@ -289,17 +266,16 @@ class ChatController extends GetxController { .toList(); if (loadMore) { - // 加载更多时,需要去重并添加到列表末尾 - // 因为ListView是reverse的,所以末尾是更旧的消息 + // 加载更多时,需要去重并添加到列表开头(更旧的消息) final existingMsgIds = messages.map((msg) => msg.msgId).toSet(); final newMessages = validMessages .where((msg) => !existingMsgIds.contains(msg.msgId)) .toList(); if (newMessages.isNotEmpty) { - messages.addAll(newMessages); - // 更新游标为最旧的消息ID(列表末尾) - _cursor = newMessages.last.msgId; + messages.insertAll(0, newMessages); + // 更新游标为最旧的消息ID(列表开头) + _cursor = newMessages.first.msgId; if (Get.isLogEnable) { Get.log('加载更多消息成功,新增: ${newMessages.length} 条,总数量: ${messages.length}'); } @@ -313,9 +289,9 @@ class ChatController extends GetxController { } else { // 刷新时替换整个列表 messages.assignAll(validMessages); - // 更新游标为最旧的消息ID(列表末尾) + // 更新游标为最旧的消息ID(列表开头) if (validMessages.isNotEmpty) { - _cursor = validMessages.last.msgId; + _cursor = validMessages.first.msgId; } else { _cursor = null; } @@ -349,8 +325,8 @@ class ChatController extends GetxController { void addReceivedMessage(EMMessage message) { // 检查消息是否已存在(避免重复添加) if (!messages.any((msg) => msg.msgId == message.msgId)) { - // 将新消息添加到列表开头 - messages.insert(0, message); + // 将新消息添加到列表末尾 + messages.add(message); update(); // 更新会话列表 _refreshConversationList(); diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 4d06187..b2a99dc 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -86,6 +86,8 @@ class Assets { static const String imagesCertPhone = 'assets/images/cert_phone.png'; static const String imagesCertRealname = 'assets/images/cert_realname.png'; static const String imagesChatBtn = 'assets/images/chat_btn.png'; + static const String imagesChatUserBg = 'assets/images/chat_user_bg.png'; + static const String imagesChatUserBgBottom = 'assets/images/chat_user_bg_bottom.png'; static const String imagesCheck = 'assets/images/check.png'; static const String imagesCloseArrow = 'assets/images/close_arrow.png'; static const String imagesCustomer = 'assets/images/customer.png'; diff --git a/lib/pages/message/chat_page.dart b/lib/pages/message/chat_page.dart index 6918b16..da0839e 100644 --- a/lib/pages/message/chat_page.dart +++ b/lib/pages/message/chat_page.dart @@ -34,14 +34,28 @@ class _ChatPageState extends State { // 监听滚动,当滚动到顶部时加载更多消息 _scrollController.addListener(() { if (_scrollController.hasClients && - _scrollController.position.pixels >= - _scrollController.position.maxScrollExtent - 100 && + _scrollController.position.pixels <= + _scrollController.position.minScrollExtent + 100 && !_isLoadingMore && _controller.messages.isNotEmpty && _controller.hasMoreMessages()) { _loadMoreMessages(); } }); + + // 监听消息列表变化,自动滚动到底部(跳过用户信息卡片) + _controller.messages.listen((_) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_scrollController.hasClients && _controller.messages.isNotEmpty) { + // 滚动到消息列表的底部(跳过顶部的用户信息卡片) + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: Duration(milliseconds: 300), + curve: Curves.easeOut, + ); + } + }); + }); } @override @@ -84,53 +98,6 @@ class _ChatPageState extends State { ), body: Column( children: [ - // 视频发送状态提示 - Obx(() { - if (controller.isSendingVideo.value) { - return Container( - width: double.infinity, - padding: EdgeInsets.symmetric( - horizontal: 16.w, - vertical: 12.h, - ), - decoration: BoxDecoration( - color: Colors.blue.withOpacity(0.1), - border: Border( - bottom: BorderSide( - color: Colors.blue.withOpacity(0.3), - width: 1, - ), - ), - ), - child: Row( - children: [ - SizedBox( - width: 20.w, - height: 20.w, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - Colors.blue, - ), - ), - ), - SizedBox(width: 12.w), - Expanded( - child: Text( - controller.sendingStatus.value, - style: TextStyle( - fontSize: 14.sp, - color: Colors.blue[700], - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - ); - } - return SizedBox.shrink(); - }), // 消息列表区域 Expanded( child: Container( @@ -143,18 +110,28 @@ class _ChatPageState extends State { behavior: HitTestBehavior.opaque, child: ListView.builder( controller: _scrollController, - reverse: true, - padding: EdgeInsets.all(16.w), - itemCount: controller.messages.length, + reverse: false, + padding: EdgeInsets.only( + top: 16.w, + left: 16.w, + right: 16.w, + bottom: 16.w, + ), + itemCount: controller.messages.length + 1, // 添加用户信息卡片 // 🚀 性能优化:添加缓存范围,减少重建 cacheExtent: 500, // 缓存屏幕外500像素的内容 itemBuilder: (context, index) { - final message = controller.messages[index]; + // 第一个是用户信息卡片 + if (index == 0) { + return _buildUserInfoCard(controller); + } + + final message = controller.messages[index - 1]; final isSentByMe = message.direction == MessageDirection.SEND; - final previousMessage = index > 0 - ? controller.messages[index - 1] + final previousMessage = index > 1 + ? controller.messages[index - 2] : null; // 🚀 性能优化:为每个消息项设置唯一的 key @@ -207,6 +184,239 @@ class _ChatPageState extends State { ); } + // 构建用户信息卡片 + Widget _buildUserInfoCard(ChatController controller) { + final userInfo = controller.userInfo.value; + + // 如果用户信息还未加载,显示占位符 + if (userInfo == null) { + return SizedBox.shrink(); + } + + return Container( + margin: EdgeInsets.only(bottom: 16.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.w), + ), + child: LayoutBuilder( + builder: (context, constraints) { + // 计算按710:351比例的高度 + // 宽度需要考虑 ListView 的 padding(左右各16.w) + final screenWidth = MediaQuery.of(context).size.width; + final availableWidth = screenWidth - 32.w; // 减去左右 padding + final width = availableWidth; + final height = width * (351 / 710); + return Container( + height: height, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.w), + image: DecorationImage( + image: AssetImage(Assets.imagesChatUserBg), + fit: BoxFit.cover, + ), + ), + child: Stack( + children: [ + // 顶层背景图(chat_user_bg_bottom,按710x351比例覆盖整个卡片) + Positioned.fill( + child: ClipRRect( + borderRadius: BorderRadius.circular(16.w), + child: Image.asset( + Assets.imagesChatUserBgBottom, + fit: BoxFit.cover, + ), + ), + ), + // 内容 + Padding( + padding: EdgeInsets.all(16.w), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 头部:名称、标签、箭头 + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 名称和标签 + Wrap( + spacing: 8.w, + runSpacing: 4.w, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + Text( + userInfo.nickName ?? '用户', + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + color: Colors.black87, + ), + ), + // 实名认证标签(和主页一样) + Container( + padding: EdgeInsets.symmetric( + horizontal: 8.w, + vertical: 2.h, + ), + decoration: BoxDecoration( + color: Color(0xFFF3E9FF), + borderRadius: BorderRadius.circular(12.w), + border: Border.all( + width: 1, + color: Color.fromRGBO(117, 98, 249, 0.32), + ), + ), + constraints: BoxConstraints( + minWidth: 40.w, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset( + Assets.imagesVerifiedIcon, + width: 14.w, + height: 12.w, + ), + SizedBox(width: 4.w), + Text( + '实名', + style: TextStyle( + fontSize: 9.sp, + color: Color.fromRGBO(160, 92, 255, 1), + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + // 在线状态标签(和主页一样) + Container( + padding: EdgeInsets.symmetric( + horizontal: 8.w, + vertical: 2.h, + ), + decoration: BoxDecoration( + color: Color.fromRGBO(234, 255, 219, 1), + borderRadius: BorderRadius.circular(12.w), + border: Border.all( + width: 1, + color: Color.fromRGBO(117, 98, 249, 0.32), + ), + ), + child: Text( + '在线', + style: TextStyle( + fontSize: 9.sp, + color: Color.fromRGBO(38, 199, 124, 1), + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + SizedBox(height: 8.h), + // 用户信息:性别图标、年龄、位置、身高 + Row( + children: [ + // 性别图标(默认显示女性图标,可以根据实际数据调整) + Image.asset( + Assets.imagesFemale, + width: 14.w, + height: 14.w, + ), + SizedBox(width: 4.w), + Text( + '19', + style: TextStyle( + fontSize: 12.sp, + color: Colors.grey[700], + ), + ), + SizedBox(width: 12.w), + Text( + '北京', + style: TextStyle( + fontSize: 12.sp, + color: Colors.grey[700], + ), + ), + SizedBox(width: 12.w), + Text( + '160cm', + style: TextStyle( + fontSize: 12.sp, + color: Colors.grey[700], + ), + ), + ], + ), + ], + ), + ), + // 右侧箭头 + Container( + width: 32.w, + height: 32.w, + decoration: BoxDecoration( + color: Colors.grey[200], + shape: BoxShape.circle, + ), + child: Icon( + Icons.arrow_forward_ios, + size: 16.w, + color: Colors.grey[700], + ), + ), + ], + ), + SizedBox(height: 8.h), // 减小间距 + // 个人简介(单行) + Text( + '喜欢在广州的早茶里抢最后一个虾饺,也能在深夜的猎德大桥...', + style: TextStyle( + fontSize: 13.sp, + color: Colors.grey[800], + height: 1.4, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + SizedBox(height: 8.h), // 减小间距 + // 图片画廊 + Row( + children: List.generate(4, (index) { + return Expanded( + child: Container( + margin: EdgeInsets.only( + right: index < 3 ? 8.w : 0, + ), + height: 50.w, // 进一步减小高度避免被裁剪 + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.w), + image: DecorationImage( + image: AssetImage(Assets.imagesAvatarsExample), + fit: BoxFit.cover, + ), + ), + ), + ); + }), + ), + ], + ), + ), + ], + ), + ); + }, + ), + ); + } + // 加载更多消息 Future _loadMoreMessages() async { if (_isLoadingMore) return; diff --git a/lib/pages/message/conversation_tab.dart b/lib/pages/message/conversation_tab.dart index 8124536..9f3346c 100644 --- a/lib/pages/message/conversation_tab.dart +++ b/lib/pages/message/conversation_tab.dart @@ -44,15 +44,16 @@ class _ConversationTabState extends State ); } - if (controller.conversations.isEmpty) { - return const Center(child: Text('暂无会话')); - } - + // 即使列表为空也显示测试项 return ListView.builder( padding: const EdgeInsets.only(top: 8), - itemCount: controller.conversations.length, + itemCount: controller.conversations.length + 1, // 添加测试项 itemBuilder: (context, index) { - final conversation = controller.conversations[index]; + // 第一个是测试项 + if (index == 0) { + return _buildTestConversationItem(); + } + final conversation = controller.conversations[index - 1]; return _buildConversationItem(conversation); }, ); @@ -62,6 +63,139 @@ class _ConversationTabState extends State ); } + // 构建测试会话项 + Widget _buildTestConversationItem() { + final double screenWidth = MediaQuery.of(context).size.width; + final int testUnreadCount = 3; + final String testTime = controller.formatMessageTime( + DateTime.now().millisecondsSinceEpoch, + ); + + final Widget cellContent = Builder( + builder: (cellContext) => GestureDetector( + onTap: () { + TDSwipeCellInherited.of(cellContext)?.cellClick(); + // 跳转到聊天页面,使用测试用户ID + Get.to(ChatPage(userId: 'test_user_001')); + }, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + margin: const EdgeInsets.only( + bottom: 8, + left: 16, + right: 16, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + image: const DecorationImage( + image: AssetImage(Assets.imagesAvatarsExample), + fit: BoxFit.cover, + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Expanded( + child: Text( + '测试用户', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + ), + ), + Text( + testTime, + style: const TextStyle( + fontSize: 12, + color: Colors.grey, + ), + ), + ], + ), + const SizedBox(height: 6), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Expanded( + child: Text( + '这是一条测试消息,用于调试', + style: TextStyle( + fontSize: 14, + color: Colors.grey, + ), + overflow: TextOverflow.ellipsis, + ), + ), + Container( + margin: const EdgeInsets.only(left: 8), + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 2, + ), + decoration: BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.circular(10), + ), + child: Text( + testUnreadCount.toString(), + style: const TextStyle( + fontSize: 12, + color: Colors.white, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ); + + return TDSwipeCell( + slidableKey: const ValueKey('test_conversation'), + groupTag: 'conversation_swipe_group', + right: TDSwipeCellPanel( + extentRatio: 72 / screenWidth, + children: [ + TDSwipeCellAction( + backgroundColor: TDTheme.of(context).errorColor6, + label: '删除', + onPressed: (actionContext) { + Get.snackbar('调试', '删除测试会话'); + }, + ), + ], + ), + cell: cellContent, + ); + } + // 构建会话项 Widget _buildConversationItem(EMConversation conversation) { return FutureBuilder( @@ -125,13 +259,16 @@ class _ConversationTabState extends State Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - userInfo?.nickName ?? '联系人', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.black, + Expanded( + child: Text( + userInfo?.nickName ?? '联系人', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.black, + ), ), ), Text( @@ -145,36 +282,44 @@ class _ConversationTabState extends State ), ], ), - const SizedBox(height: 4), - Text( - controller.getLastMessageContent(message), - style: const TextStyle( - fontSize: 14, - color: Colors.grey, - ), - overflow: TextOverflow.ellipsis, + const SizedBox(height: 6), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Text( + controller.getLastMessageContent(message), + style: const TextStyle( + fontSize: 14, + color: Colors.grey, + ), + overflow: TextOverflow.ellipsis, + ), + ), + if (unreadCount > 0) + Container( + margin: const EdgeInsets.only(left: 8), + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 2, + ), + decoration: BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.circular(10), + ), + child: Text( + unreadCount.toString(), + style: const TextStyle( + fontSize: 12, + color: Colors.white, + ), + ), + ), + ], ), ], ), ), - if (unreadCount > 0) - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 2, - ), - decoration: BoxDecoration( - color: Colors.red, - borderRadius: BorderRadius.circular(10), - ), - child: Text( - unreadCount.toString(), - style: const TextStyle( - fontSize: 12, - color: Colors.white, - ), - ), - ), ], ), ), diff --git a/lib/pages/message/friend_tab.dart b/lib/pages/message/friend_tab.dart index 1c143ff..c26ecd1 100644 --- a/lib/pages/message/friend_tab.dart +++ b/lib/pages/message/friend_tab.dart @@ -173,8 +173,8 @@ class _FriendTabState extends State with TickerProviderStateMixin { Widget _buildTabButton(String title, int index) { final bool isSelected = _tabController.index == index; // 根据索引设置不同的宽高 - final double width = index == 0 ? 72 : 36; - final double height = index == 0 ? 42 : 21; + final double width = index == 0 ? 82 : 60; + final double height = index == 0 ? 30 : 30; return GestureDetector( onTap: () { @@ -188,14 +188,14 @@ class _FriendTabState extends State with TickerProviderStateMixin { child: Container( decoration: BoxDecoration( color: isSelected ? _primaryPurple : Colors.white, - borderRadius: BorderRadius.circular(20), + borderRadius: BorderRadius.circular(28), ), alignment: Alignment.center, child: Text( title, style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, + fontSize: 12, + fontWeight: FontWeight.w700, color: isSelected ? Colors.white : Colors.black87, ), ), @@ -222,7 +222,7 @@ class _FriendTabState extends State with TickerProviderStateMixin { margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.white, + color: Color(0x00FFFFFF), borderRadius: BorderRadius.circular(8), ), child: Row( diff --git a/lib/widget/message/chat_input_bar.dart b/lib/widget/message/chat_input_bar.dart index 33ab1d8..094ab26 100644 --- a/lib/widget/message/chat_input_bar.dart +++ b/lib/widget/message/chat_input_bar.dart @@ -248,7 +248,7 @@ class _ChatInputBarState extends State { vertical: 8.h, ), decoration: BoxDecoration( - color: Colors.blue, + color: Color.fromRGBO(117, 98, 249, 1), borderRadius: BorderRadius.circular(5.h), ), child: Text( diff --git a/lib/widget/message/image_item.dart b/lib/widget/message/image_item.dart index 1857ab9..6d10f04 100644 --- a/lib/widget/message/image_item.dart +++ b/lib/widget/message/image_item.dart @@ -11,12 +11,16 @@ class ImageItem extends StatelessWidget { final bool isSentByMe; final bool showTime; final String formattedTime; + final EMMessage message; // 添加消息对象以获取状态 + final VoidCallback? onResend; // 添加重发回调 const ImageItem({ required this.imageBody, required this.isSentByMe, required this.showTime, required this.formattedTime, + required this.message, + this.onResend, super.key, }); @@ -31,31 +35,48 @@ class ImageItem extends StatelessWidget { horizontal: 16.w, vertical: 8.h, ), - child: Row( - mainAxisAlignment: isSentByMe ? MainAxisAlignment.end : MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (!isSentByMe) _buildAvatar(), - if (!isSentByMe) SizedBox(width: 8.w), - GestureDetector( - onTap: _onImageTap, - child: Container( - margin: EdgeInsets.only(top: 10.h), - decoration: BoxDecoration( - color: isSentByMe ? Color(0xff8E7BF6) : Colors.white, - borderRadius: BorderRadius.only( - topLeft: isSentByMe ? Radius.circular(12.w) : Radius.circular(0), - topRight: isSentByMe ? Radius.circular(0) : Radius.circular(12.w), - bottomLeft: Radius.circular(12.w), - bottomRight: Radius.circular(12.w), + child: Builder( + builder: (context) { + // 计算图片尺寸 + double maxWidth = 180.w; + double width = maxWidth; + double height = width * (304 / 289); // 按289:304比例计算高度 + final imageHeight = height + 10.h; // 加上 margin top (10.h) + + return Row( + mainAxisAlignment: isSentByMe ? MainAxisAlignment.end : MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (!isSentByMe) _buildAvatar(), + if (!isSentByMe) SizedBox(width: 8.w), + // 发送消息时,状态在左侧,与图片垂直居中对齐 + if (isSentByMe) + SizedBox( + height: imageHeight, + child: Center( + child: _buildMessageStatus(), + ), + ), + if (isSentByMe) SizedBox(width: 10.w), + GestureDetector( + onTap: _onImageTap, + child: Container( + margin: EdgeInsets.only(top: 10.h), + decoration: BoxDecoration( + color: isSentByMe ? Color(0xff8E7BF6) : Colors.white, + borderRadius: BorderRadius.circular(18.w), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(18.w), + child: _buildImage(), + ), ), ), - child: _buildImage(), - ), - ), - if (isSentByMe) SizedBox(width: 8.w), - if (isSentByMe) _buildAvatar(), - ], + if (isSentByMe) SizedBox(width: 8.w), + if (isSentByMe) _buildAvatar(), + ], + ); + }, ), ), ], @@ -101,25 +122,11 @@ class ImageItem extends StatelessWidget { // 构建图片 Widget _buildImage() { - // 计算图片尺寸,限制最大宽度为200 - double maxWidth = 200.w; - double maxHeight = 200.w; + // 按289x304比例计算图片尺寸 + // 限制最大宽度为289,高度按比例计算 + double maxWidth = 180.w; double width = maxWidth; - double height = maxHeight; - // 如果有图片尺寸信息,根据比例调整 - if (imageBody.width != null && imageBody.width! > 0 && - imageBody.height != null && imageBody.height! > 0) { - final aspectRatio = imageBody.width! / imageBody.height!; - if (aspectRatio > 1) { - // 宽图 - width = maxWidth; - height = maxWidth / aspectRatio; - } else { - // 高图 - height = maxHeight; - width = maxHeight * aspectRatio; - } - } + double height = width * (304 / 289); // 按289:304比例计算高度 // 尝试显示本地图片 final localPath = imageBody.localPath; if (localPath.isNotEmpty) { @@ -156,24 +163,72 @@ class ImageItem extends StatelessWidget { return _buildErrorContainer(width, height); } - // 构建加载中的容器 + // 构建加载中的容器(网络图片加载时) Widget _buildLoadingContainer(double width, double height) { return Container( width: width, height: height, - padding: EdgeInsets.all(8.w), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8.w), + borderRadius: BorderRadius.circular(18.w), color: Colors.grey[200], ), - alignment: Alignment.center, - child: CircularProgressIndicator( - strokeWidth: 2.w, - color: Colors.grey[400], + child: Center( + child: CircularProgressIndicator( + strokeWidth: 2.w, + valueColor: AlwaysStoppedAnimation( + Colors.grey[400]!, + ), + ), ), ); } + // 构建消息状态(发送中、已发送、失败重发) + Widget _buildMessageStatus() { + // 只对发送的消息显示状态 + if (!isSentByMe) { + return SizedBox.shrink(); + } + + // 检查消息状态 + final status = message.status; + + if (status == MessageStatus.FAIL) { + // 发送失败,显示重发按钮 + return GestureDetector( + onTap: onResend, + child: Container( + width: 20.w, + height: 20.w, + decoration: BoxDecoration( + color: Colors.red.withOpacity(0.1), + shape: BoxShape.circle, + ), + child: Icon( + Icons.refresh, + size: 14.w, + color: Colors.red, + ), + ), + ); + } else if (status == MessageStatus.PROGRESS) { + // 发送中,显示加载动画 + return Container( + width: 16.w, + height: 16.w, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: AlwaysStoppedAnimation( + Colors.grey, + ), + ), + ); + } else { + // 发送成功,不显示任何状态 + return SizedBox.shrink(); + } + } + // 构建错误容器 Widget _buildErrorContainer(double width, double height) { return Container( @@ -181,7 +236,7 @@ class ImageItem extends StatelessWidget { height: height, padding: EdgeInsets.all(8.w), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8.w), + borderRadius: BorderRadius.circular(18.w), color: Colors.grey[200], ), alignment: Alignment.center, diff --git a/lib/widget/message/message_item.dart b/lib/widget/message/message_item.dart index 6fef19f..b29f011 100644 --- a/lib/widget/message/message_item.dart +++ b/lib/widget/message/message_item.dart @@ -53,6 +53,16 @@ class MessageItem extends StatelessWidget { isSentByMe: isSentByMe, showTime: shouldShowTime(), formattedTime: formatMessageTime(message.serverTime), + message: message, + onResend: () { + // 通过Get找到ChatController并调用重发方法 + try { + final controller = Get.find(); + controller.resendMessage(message); + } catch (e) { + print('重发消息失败: $e'); + } + }, ); } // 处理语音消息 @@ -75,6 +85,16 @@ class MessageItem extends StatelessWidget { isSentByMe: isSentByMe, showTime: shouldShowTime(), formattedTime: formatMessageTime(message.serverTime), + message: message, + onResend: () { + // 通过Get找到ChatController并调用重发方法 + try { + final controller = Get.find(); + controller.resendMessage(message); + } catch (e) { + print('重发消息失败: $e'); + } + }, ); } diff --git a/lib/widget/message/text_item.dart b/lib/widget/message/text_item.dart index 989848a..f8ad379 100644 --- a/lib/widget/message/text_item.dart +++ b/lib/widget/message/text_item.dart @@ -36,10 +36,20 @@ class TextItem extends StatelessWidget { ), child: Row( mainAxisAlignment: isSentByMe ? MainAxisAlignment.end : MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ if (!isSentByMe) _buildAvatar(), if (!isSentByMe) SizedBox(width: 8.w), + // 发送消息时,状态在左侧,与消息气泡垂直居中对齐 + if (isSentByMe) + Align( + alignment: Alignment.center, + child: Container( + margin: EdgeInsets.only(top: 10.h), + child: _buildMessageStatus(), + ), + ), + if (isSentByMe) SizedBox(width: 10.w), Container( constraints: BoxConstraints(maxWidth: 240.w), margin: EdgeInsets.only(top: 10.h), @@ -65,8 +75,6 @@ class TextItem extends StatelessWidget { emojiSize: 24.w, ), ), - // 显示发送状态或重发按钮 - if (isSentByMe) _buildMessageStatus(), if (isSentByMe) SizedBox(width: 8.w), if (isSentByMe) _buildAvatar(), ], @@ -130,7 +138,6 @@ class TextItem extends StatelessWidget { child: Container( width: 20.w, height: 20.w, - margin: EdgeInsets.only(right: 4.w), decoration: BoxDecoration( color: Colors.red.withOpacity(0.1), shape: BoxShape.circle, @@ -147,17 +154,16 @@ class TextItem extends StatelessWidget { return Container( width: 16.w, height: 16.w, - margin: EdgeInsets.only(right: 4.w), child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - isSentByMe ? Colors.white70 : Colors.grey, + Colors.grey, ), ), ); } else { // 发送成功,不显示任何状态 - return SizedBox(width: 4.w); + return SizedBox.shrink(); } } } \ No newline at end of file diff --git a/lib/widget/message/video_item.dart b/lib/widget/message/video_item.dart index fed5eeb..d88fcd2 100644 --- a/lib/widget/message/video_item.dart +++ b/lib/widget/message/video_item.dart @@ -7,18 +7,23 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:video_player/video_player.dart'; import 'package:dating_touchme_app/pages/message/video_player_page.dart'; +import 'package:dating_touchme_app/generated/assets.dart'; class VideoItem extends StatefulWidget { final EMVideoMessageBody videoBody; final bool isSentByMe; final bool showTime; final String formattedTime; + final EMMessage message; // 添加消息对象以获取状态 + final VoidCallback? onResend; // 添加重发回调 const VideoItem({ required this.videoBody, required this.isSentByMe, required this.showTime, required this.formattedTime, + required this.message, + this.onResend, super.key, }); @@ -202,24 +207,44 @@ class _VideoItemState extends State { children: [ if (widget.showTime) _buildTimeLabel(), Container( - padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 4.h), - child: Row( - mainAxisAlignment: widget.isSentByMe - ? MainAxisAlignment.end - : MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // 🚀 极致性能优化:无需初始化,直接显示缩略图 - Stack( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), + child: Builder( + builder: (context) { + // 计算视频尺寸 + double maxWidth = 180.w; + double width = maxWidth; + double height = width * (304 / 289); // 按289:304比例计算高度 + final videoHeight = height + 10.h; // 加上 margin top (10.h) + + return Row( + mainAxisAlignment: widget.isSentByMe + ? MainAxisAlignment.end + : MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - GestureDetector( - onTap: _playVideo, - child: Container( - width: 200.w, - height: 150.h, + if (!widget.isSentByMe) _buildAvatar(), + if (!widget.isSentByMe) SizedBox(width: 8.w), + // 发送消息时,状态在左侧,与视频垂直居中对齐 + if (widget.isSentByMe) + SizedBox( + height: videoHeight, + child: Center( + child: _buildMessageStatus(), + ), + ), + if (widget.isSentByMe) SizedBox(width: 10.w), + // 🚀 极致性能优化:无需初始化,直接显示缩略图 + Stack( + children: [ + GestureDetector( + onTap: _playVideo, + child: Container( + margin: EdgeInsets.only(top: 10.h), + width: 180.w, + height: 180.w * (304 / 289), // 按289:304比例计算高度 decoration: BoxDecoration( color: Colors.grey[300], - borderRadius: BorderRadius.circular(12.w), + borderRadius: BorderRadius.circular(18.w), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), @@ -229,7 +254,7 @@ class _VideoItemState extends State { ], ), child: ClipRRect( - borderRadius: BorderRadius.circular(12.w), + borderRadius: BorderRadius.circular(18.w), child: Stack( fit: StackFit.expand, children: [ @@ -328,11 +353,9 @@ class _VideoItemState extends State { if (_isLoadingVideo) Positioned.fill( child: Container( - width: 200.w, - height: 150.h, decoration: BoxDecoration( color: Colors.black.withOpacity(0.5), - borderRadius: BorderRadius.circular(12.w), + borderRadius: BorderRadius.circular(18.w), ), child: Center( child: CircularProgressIndicator( @@ -346,13 +369,78 @@ class _VideoItemState extends State { ), ], ), - ], + if (widget.isSentByMe) SizedBox(width: 8.w), + if (widget.isSentByMe) _buildAvatar(), + ], + ); + }, ), ), ], ); } + // 构建头像 + Widget _buildAvatar() { + return Container( + width: 40.w, + height: 40.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20.w), + image: DecorationImage( + image: AssetImage(Assets.imagesAvatarsExample), + fit: BoxFit.cover, + ), + ), + ); + } + + // 构建消息状态(发送中、已发送、失败重发) + Widget _buildMessageStatus() { + // 只对发送的消息显示状态 + if (!widget.isSentByMe) { + return SizedBox.shrink(); + } + + // 检查消息状态 + final status = widget.message.status; + + if (status == MessageStatus.FAIL) { + // 发送失败,显示重发按钮 + return GestureDetector( + onTap: widget.onResend, + child: Container( + width: 20.w, + height: 20.w, + decoration: BoxDecoration( + color: Colors.red.withOpacity(0.1), + shape: BoxShape.circle, + ), + child: Icon( + Icons.refresh, + size: 14.w, + color: Colors.red, + ), + ), + ); + } else if (status == MessageStatus.PROGRESS) { + // 发送中,显示加载动画 + return Container( + width: 16.w, + height: 16.w, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: AlwaysStoppedAnimation( + Colors.grey, + ), + ), + ); + } else { + // 发送成功,不显示任何状态 + return SizedBox.shrink(); + } + } + // 🚀 性能优化:构建缓存的缩略图 Widget _buildThumbnail() { if (_thumbnailPath == null || _thumbnailPath!.isEmpty) { @@ -375,7 +463,7 @@ class _VideoItemState extends State { // 🚀 使用 CachedNetworkImage 缓存网络图片 return CachedNetworkImage( imageUrl: _thumbnailPath!, - fit: BoxFit.cover, + fit: BoxFit.contain, width: double.infinity, height: double.infinity, placeholder: (context, url) { @@ -410,7 +498,7 @@ class _VideoItemState extends State { print('✅ [VideoItem] 本地缩略图文件存在,开始渲染'); return Image.file( file, - fit: BoxFit.cover, + fit: BoxFit.contain, width: double.infinity, height: double.infinity, // 🚀 设置缓存宽高,减少内存占用 @@ -439,7 +527,7 @@ class _VideoItemState extends State { print('✅ [VideoItem] 视频预览加载成功'); // 🎯 使用 FittedBox 保持视频比例,避免变形 return FittedBox( - fit: BoxFit.cover, + fit: BoxFit.contain, child: SizedBox( width: snapshot.data!.value.size.width, height: snapshot.data!.value.size.height, diff --git a/location_plugin/example/pubspec.lock b/location_plugin/example/pubspec.lock index 36a3835..678892a 100644 --- a/location_plugin/example/pubspec.lock +++ b/location_plugin/example/pubspec.lock @@ -6,7 +6,7 @@ packages: description: name: async sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.13.0" boolean_selector: @@ -14,7 +14,7 @@ packages: description: name: boolean_selector sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.2" characters: @@ -22,7 +22,7 @@ packages: description: name: characters sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" clock: @@ -30,7 +30,7 @@ packages: description: name: clock sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.2" collection: @@ -38,7 +38,7 @@ packages: description: name: collection sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.19.1" cupertino_icons: @@ -46,7 +46,7 @@ packages: description: name: cupertino_icons sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.8" fake_async: @@ -54,7 +54,7 @@ packages: description: name: fake_async sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.3" file: @@ -62,7 +62,7 @@ packages: description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.1" flutter: @@ -80,7 +80,7 @@ packages: description: name: flutter_lints sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.0.0" flutter_test: @@ -98,7 +98,7 @@ packages: description: name: http sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.6.0" http_parser: @@ -106,7 +106,7 @@ packages: description: name: http_parser sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.2" integration_test: @@ -119,7 +119,7 @@ packages: description: name: leak_tracker sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "11.0.2" leak_tracker_flutter_testing: @@ -127,7 +127,7 @@ packages: description: name: leak_tracker_flutter_testing sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.10" leak_tracker_testing: @@ -135,7 +135,7 @@ packages: description: name: leak_tracker_testing sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.2" lints: @@ -143,7 +143,7 @@ packages: description: name: lints sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.1.1" location_plugin: @@ -158,7 +158,7 @@ packages: description: name: matcher sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.12.17" material_color_utilities: @@ -166,7 +166,7 @@ packages: description: name: material_color_utilities sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.11.1" meta: @@ -174,7 +174,7 @@ packages: description: name: meta sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.16.0" path: @@ -182,7 +182,7 @@ packages: description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.9.1" platform: @@ -190,7 +190,7 @@ packages: description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.6" plugin_platform_interface: @@ -198,7 +198,7 @@ packages: description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.8" process: @@ -206,7 +206,7 @@ packages: description: name: process sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.0.5" sky_engine: @@ -219,7 +219,7 @@ packages: description: name: source_span sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.10.1" stack_trace: @@ -227,7 +227,7 @@ packages: description: name: stack_trace sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.12.1" stream_channel: @@ -235,7 +235,7 @@ packages: description: name: stream_channel sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.4" string_scanner: @@ -243,7 +243,7 @@ packages: description: name: string_scanner sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.1" sync_http: @@ -251,7 +251,7 @@ packages: description: name: sync_http sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.3.1" term_glyph: @@ -259,7 +259,7 @@ packages: description: name: term_glyph sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.2" test_api: @@ -267,7 +267,7 @@ packages: description: name: test_api sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.6" typed_data: @@ -275,7 +275,7 @@ packages: description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" vector_math: @@ -283,7 +283,7 @@ packages: description: name: vector_math sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" vm_service: @@ -291,7 +291,7 @@ packages: description: name: vm_service sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "15.0.2" web: @@ -299,7 +299,7 @@ packages: description: name: web sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" webdriver: @@ -307,7 +307,7 @@ packages: description: name: webdriver sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.0" sdks: diff --git a/pubspec.lock b/pubspec.lock index a8c9223..c07ceb2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -6,7 +6,7 @@ packages: description: name: _fe_analyzer_shared sha256: f0bb5d1648339c8308cc0b9838d8456b3cfe5c91f9dc1a735b4d003269e5da9a - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "88.0.0" agora_rtc_engine: @@ -14,7 +14,7 @@ packages: description: name: agora_rtc_engine sha256: "6559294d18ce4445420e19dbdba10fb58cac955cd8f22dbceae26716e194d70e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.5.3" agora_rtm: @@ -22,7 +22,7 @@ packages: description: name: agora_rtm sha256: "3cd8e25ecfccbb2e8ca5a70b173bff080dab782e233f9b40f483adbd31dd38fb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.5" analyzer: @@ -30,7 +30,7 @@ packages: description: name: analyzer sha256: "0b7b9c329d2879f8f05d6c05b32ee9ec025f39b077864bdb5ac9a7b63418a98f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "8.1.1" ansicolor: @@ -38,7 +38,7 @@ packages: description: name: ansicolor sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.3" archive: @@ -46,7 +46,7 @@ packages: description: name: archive sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.7" args: @@ -54,7 +54,7 @@ packages: description: name: args sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.7.0" async: @@ -62,7 +62,7 @@ packages: description: name: async sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.13.0" audioplayers: @@ -70,7 +70,7 @@ packages: description: name: audioplayers sha256: "5441fa0ceb8807a5ad701199806510e56afde2b4913d9d17c2f19f2902cf0ae4" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.5.1" audioplayers_android: @@ -78,7 +78,7 @@ packages: description: name: audioplayers_android sha256: "60a6728277228413a85755bd3ffd6fab98f6555608923813ce383b190a360605" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.2.1" audioplayers_darwin: @@ -86,7 +86,7 @@ packages: description: name: audioplayers_darwin sha256: "0811d6924904ca13f9ef90d19081e4a87f7297ddc19fc3d31f60af1aaafee333" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.3.0" audioplayers_linux: @@ -94,7 +94,7 @@ packages: description: name: audioplayers_linux sha256: f75bce1ce864170ef5e6a2c6a61cd3339e1a17ce11e99a25bae4474ea491d001 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.2.1" audioplayers_platform_interface: @@ -102,7 +102,7 @@ packages: description: name: audioplayers_platform_interface sha256: "0e2f6a919ab56d0fec272e801abc07b26ae7f31980f912f24af4748763e5a656" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.1.1" audioplayers_web: @@ -110,7 +110,7 @@ packages: description: name: audioplayers_web sha256: "1c0f17cec68455556775f1e50ca85c40c05c714a99c5eb1d2d57cc17ba5522d7" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.1.1" audioplayers_windows: @@ -118,7 +118,7 @@ packages: description: name: audioplayers_windows sha256: "4048797865105b26d47628e6abb49231ea5de84884160229251f37dfcbe52fd7" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.2.1" boolean_selector: @@ -126,7 +126,7 @@ packages: description: name: boolean_selector sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.2" build: @@ -134,7 +134,7 @@ packages: description: name: build sha256: dfb67ccc9a78c642193e0c2d94cb9e48c2c818b3178a86097d644acdcde6a8d9 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.2" build_config: @@ -142,7 +142,7 @@ packages: description: name: build_config sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.0" build_daemon: @@ -150,7 +150,7 @@ packages: description: name: build_daemon sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.1" build_runner: @@ -158,7 +158,7 @@ packages: description: name: build_runner sha256: "7b5b569f3df370590a85029148d6fc66c7d0201fc6f1847c07dd85d365ae9fcd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.10.3" built_collection: @@ -166,7 +166,7 @@ packages: description: name: built_collection sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: @@ -174,7 +174,7 @@ packages: description: name: built_value sha256: a30f0a0e38671e89a492c44d005b5545b830a961575bbd8336d42869ff71066d - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "8.12.0" cached_network_image: @@ -182,7 +182,7 @@ packages: description: name: cached_network_image sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.4.1" cached_network_image_platform_interface: @@ -190,7 +190,7 @@ packages: description: name: cached_network_image_platform_interface sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.1" cached_network_image_web: @@ -198,7 +198,7 @@ packages: description: name: cached_network_image_web sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.1" camera: @@ -206,7 +206,7 @@ packages: description: name: camera sha256: dfa8fc5a1adaeb95e7a54d86a5bd56f4bb0e035515354c8ac6d262e35cec2ec8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.10.6" camera_android: @@ -214,23 +214,23 @@ packages: description: name: camera_android sha256: "8397c4fcec4f4dbafdeff994adc6ed16dcaa4a25f02e70e3b8fbe59c9a88807f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.10.10+11" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - sha256: "34bcd5db30e52414f1f0783c5e3f566909fab14141a21b3b576c78bd35382bf6" - url: "https://pub.flutter-io.cn" + sha256: "1a98138e44451c258aea84600135bd5975031382b609752d76a4f5e1b117e5e0" + url: "https://pub.dev" source: hosted - version: "0.9.22+4" + version: "0.9.22+5" camera_platform_interface: dependency: transitive description: name: camera_platform_interface sha256: "98cfc9357e04bad617671b4c1f78a597f25f08003089dd94050709ae54effc63" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.12.0" camera_web: @@ -238,7 +238,7 @@ packages: description: name: camera_web sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.3.5" characters: @@ -246,7 +246,7 @@ packages: description: name: characters sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" checked_yaml: @@ -254,7 +254,7 @@ packages: description: name: checked_yaml sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.4" chewie: @@ -262,7 +262,7 @@ packages: description: name: chewie sha256: "44bcfc5f0dfd1de290c87c9d86a61308b3282a70b63435d5557cfd60f54a69ca" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.13.0" clock: @@ -270,7 +270,7 @@ packages: description: name: clock sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.2" code_builder: @@ -278,7 +278,7 @@ packages: description: name: code_builder sha256: "11654819532ba94c34de52ff5feb52bd81cba1de00ef2ed622fd50295f9d4243" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.11.0" collection: @@ -286,7 +286,7 @@ packages: description: name: collection sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.19.1" common_utils: @@ -294,7 +294,7 @@ packages: description: name: common_utils sha256: c26884339b13ff99b0739e56f4b02090c84054ed9dd3a045435cd24e7b99c2c1 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.0" convert: @@ -302,7 +302,7 @@ packages: description: name: convert sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.2" cross_file: @@ -310,7 +310,7 @@ packages: description: name: cross_file sha256: "942a4791cd385a68ccb3b32c71c427aba508a1bb949b86dff2adbe4049f16239" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.3.5" crypto: @@ -318,7 +318,7 @@ packages: description: name: crypto sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.7" csslib: @@ -326,7 +326,7 @@ packages: description: name: csslib sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.2" cupertino_icons: @@ -334,7 +334,7 @@ packages: description: name: cupertino_icons sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.8" dart_style: @@ -342,7 +342,7 @@ packages: description: name: dart_style sha256: c87dfe3d56f183ffe9106a18aebc6db431fc7c98c31a54b952a77f3d54a85697 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.2" dbus: @@ -350,7 +350,7 @@ packages: description: name: dbus sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.11" decimal: @@ -358,7 +358,7 @@ packages: description: name: decimal sha256: fc706a5618b81e5b367b01dd62621def37abc096f2b46a9bd9068b64c1fa36d0 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.4" dio: @@ -366,7 +366,7 @@ packages: description: name: dio sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.9.0" dio_web_adapter: @@ -374,7 +374,7 @@ packages: description: name: dio_web_adapter sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" easy_localization: @@ -382,7 +382,7 @@ packages: description: name: easy_localization sha256: "2ccdf9db8fe4d9c5a75c122e6275674508fd0f0d49c827354967b8afcc56bbed" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.8" easy_logger: @@ -390,7 +390,7 @@ packages: description: name: easy_logger sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.0.2" easy_refresh: @@ -398,7 +398,7 @@ packages: description: name: easy_refresh sha256: "486e30abfcaae66c0f2c2798a10de2298eb9dc5e0bb7e1dba9328308968cae0c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.4.0" event_bus: @@ -406,7 +406,7 @@ packages: description: name: event_bus sha256: "1a55e97923769c286d295240048fc180e7b0768902c3c2e869fe059aafa15304" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.1" extended_image: @@ -414,7 +414,7 @@ packages: description: name: extended_image sha256: "85199f9233e03abc2ce2e68cbb2991648666af4a527ae4e6250935be8edfddae" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "9.1.0" extended_image_library: @@ -422,7 +422,7 @@ packages: description: name: extended_image_library sha256: e61dafd94400fff6ef7ed1523d445ff3af137f198f3228e4a3107bc5b4bec5d1 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.6" fake_async: @@ -430,7 +430,7 @@ packages: description: name: fake_async sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.3" ffi: @@ -438,7 +438,7 @@ packages: description: name: ffi sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.4" file: @@ -446,7 +446,7 @@ packages: description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.1" file_selector_linux: @@ -454,7 +454,7 @@ packages: description: name: file_selector_linux sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.9.3+2" file_selector_macos: @@ -462,7 +462,7 @@ packages: description: name: file_selector_macos sha256: "88707a3bec4b988aaed3b4df5d7441ee4e987f20b286cddca5d6a8270cab23f2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.9.4+5" file_selector_platform_interface: @@ -470,7 +470,7 @@ packages: description: name: file_selector_platform_interface sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.7.0" file_selector_windows: @@ -478,7 +478,7 @@ packages: description: name: file_selector_windows sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.9.3+4" fixnum: @@ -486,7 +486,7 @@ packages: description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" flustars: @@ -494,7 +494,7 @@ packages: description: name: flustars sha256: "7019ab8d68c0d4759ee122644d91a165d450b0492717f9e7e9d0ce277dcf664b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.1" flutter: @@ -507,7 +507,7 @@ packages: description: name: flutter_cache_manager sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.4.1" flutter_lints: @@ -515,7 +515,7 @@ packages: description: name: flutter_lints sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.0.0" flutter_localizations: @@ -528,7 +528,7 @@ packages: description: name: flutter_native_splash sha256: "4fb9f4113350d3a80841ce05ebf1976a36de622af7d19aca0ca9a9911c7ff002" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.7" flutter_oss_aliyun: @@ -536,7 +536,7 @@ packages: description: name: flutter_oss_aliyun sha256: "8280c1e8dfb792dec6449d1e6052e1d3492b3b3a1dfee456cc41d3f31b4cbc26" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.4.2" flutter_plugin_android_lifecycle: @@ -544,7 +544,7 @@ packages: description: name: flutter_plugin_android_lifecycle sha256: "306f0596590e077338312f38837f595c04f28d6cdeeac392d3d74df2f0003687" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.32" flutter_screenutil: @@ -552,7 +552,7 @@ packages: description: name: flutter_screenutil sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.9.3" flutter_slidable: @@ -560,7 +560,7 @@ packages: description: name: flutter_slidable sha256: a857de7ea701f276fd6a6c4c67ae885b60729a3449e42766bb0e655171042801 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.2" flutter_smart_dialog: @@ -568,7 +568,7 @@ packages: description: name: flutter_smart_dialog sha256: "0852df132cb03fd8fc5144eb404c31eb7eb50c22aecb1cc2504f2f598090d756" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.9.8+9" flutter_swiper_null_safety: @@ -576,7 +576,7 @@ packages: description: name: flutter_swiper_null_safety sha256: "5a855e0080d035c08e82f8b7fd2f106344943a30c9ab483b2584860a2f22eaaf" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.2" flutter_test: @@ -589,20 +589,12 @@ packages: description: flutter source: sdk version: "0.0.0" - fluwx: - dependency: "direct main" - description: - name: fluwx - sha256: "7e92d2000ee49c5262a88c51ea2d22b91a753d5b29df27cc264bb0a115d65373" - url: "https://pub.flutter-io.cn" - source: hosted - version: "5.7.5" frontend_server_client: dependency: transitive description: name: frontend_server_client sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.0" get: @@ -610,7 +602,7 @@ packages: description: name: get sha256: c79eeb4339f1f3deffd9ec912f8a923834bec55f7b49c9e882b8fef2c139d425 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.7.2" get_storage: @@ -618,7 +610,7 @@ packages: description: name: get_storage sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" glob: @@ -626,7 +618,7 @@ packages: description: name: glob sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.3" graphs: @@ -634,7 +626,7 @@ packages: description: name: graphs sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.2" hotreloader: @@ -642,7 +634,7 @@ packages: description: name: hotreloader sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.3.0" html: @@ -650,7 +642,7 @@ packages: description: name: html sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.15.6" http: @@ -658,7 +650,7 @@ packages: description: name: http sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.6.0" http_client_helper: @@ -666,7 +658,7 @@ packages: description: name: http_client_helper sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.0" http_multi_server: @@ -674,7 +666,7 @@ packages: description: name: http_multi_server sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.2" http_parser: @@ -682,7 +674,7 @@ packages: description: name: http_parser sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.2" im_flutter_sdk: @@ -690,7 +682,7 @@ packages: description: name: im_flutter_sdk sha256: "5f81988c5edf14a4e3868b9c47f01de2ee355e2203ae5bd95d7cacfe30e15d97" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.15.2" im_flutter_sdk_android: @@ -698,7 +690,7 @@ packages: description: name: im_flutter_sdk_android sha256: ce4e01f1374a6cf20bb46f6774e1effbde5c014fd1cd3003b6604813e4fe9e71 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.15.2" im_flutter_sdk_interface: @@ -706,7 +698,7 @@ packages: description: name: im_flutter_sdk_interface sha256: "08ad3ce9fc935e24272bce34aebfd9b3c3c30aab2b9e7d4b2e759acf4a4874f5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.15.2" im_flutter_sdk_ios: @@ -714,7 +706,7 @@ packages: description: name: im_flutter_sdk_ios sha256: "11300c086f5821730224932c28860198ef5d879f7941f9158dddee499f7bb60e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.15.2" image: @@ -722,7 +714,7 @@ packages: description: name: image sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.5.4" image_picker: @@ -730,7 +722,7 @@ packages: description: name: image_picker sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.2" image_picker_android: @@ -738,7 +730,7 @@ packages: description: name: image_picker_android sha256: "317a5d961cec5b34e777b9252393f2afbd23084aa6e60fcf601dcf6341b9ebeb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.8.12+23" image_picker_for_web: @@ -746,7 +738,7 @@ packages: description: name: image_picker_for_web sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.0" image_picker_ios: @@ -754,7 +746,7 @@ packages: description: name: image_picker_ios sha256: e675c22790bcc24e9abd455deead2b7a88de4b79f7327a281812f14de1a56f58 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.8.13+1" image_picker_linux: @@ -762,7 +754,7 @@ packages: description: name: image_picker_linux sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.2" image_picker_macos: @@ -770,7 +762,7 @@ packages: description: name: image_picker_macos sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.2+1" image_picker_platform_interface: @@ -778,7 +770,7 @@ packages: description: name: image_picker_platform_interface sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.11.1" image_picker_windows: @@ -786,7 +778,7 @@ packages: description: name: image_picker_windows sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.2" intl: @@ -794,7 +786,7 @@ packages: description: name: intl sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.20.2" io: @@ -802,7 +794,7 @@ packages: description: name: io sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.5" iris_method_channel: @@ -810,7 +802,7 @@ packages: description: name: iris_method_channel sha256: bfb5cfc6c6eae42da8cd1b35977a72d8b8881848a5dfc3d672e4760a907d11a0 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.4" js: @@ -818,7 +810,7 @@ packages: description: name: js sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.2" json_annotation: @@ -826,7 +818,7 @@ packages: description: name: json_annotation sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.9.0" json_serializable: @@ -834,7 +826,7 @@ packages: description: name: json_serializable sha256: "33a040668b31b320aafa4822b7b1e177e163fc3c1e835c6750319d4ab23aa6fe" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.11.1" leak_tracker: @@ -842,7 +834,7 @@ packages: description: name: leak_tracker sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "11.0.2" leak_tracker_flutter_testing: @@ -850,7 +842,7 @@ packages: description: name: leak_tracker_flutter_testing sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.10" leak_tracker_testing: @@ -858,7 +850,7 @@ packages: description: name: leak_tracker_testing sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.2" lean_builder: @@ -866,7 +858,7 @@ packages: description: name: lean_builder sha256: ef5cd5f907157eb7aa87d1704504b5a6386d2cbff88a3c2b3344477bab323ee9 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.1.2" lints: @@ -874,7 +866,7 @@ packages: description: name: lints sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.1.1" location_plugin: @@ -889,7 +881,7 @@ packages: description: name: logging sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.0" matcher: @@ -897,7 +889,7 @@ packages: description: name: matcher sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.12.17" material_color_utilities: @@ -905,7 +897,7 @@ packages: description: name: material_color_utilities sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.11.1" meta: @@ -913,7 +905,7 @@ packages: description: name: meta sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.16.0" mime: @@ -921,7 +913,7 @@ packages: description: name: mime sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.6" nested: @@ -929,7 +921,7 @@ packages: description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.0" octo_image: @@ -937,7 +929,7 @@ packages: description: name: octo_image sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.0" package_config: @@ -945,7 +937,7 @@ packages: description: name: package_config sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" package_info_plus: @@ -953,7 +945,7 @@ packages: description: name: package_info_plus sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "9.0.0" package_info_plus_platform_interface: @@ -961,7 +953,7 @@ packages: description: name: package_info_plus_platform_interface sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.1" path: @@ -969,7 +961,7 @@ packages: description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.9.1" path_drawing: @@ -977,7 +969,7 @@ packages: description: name: path_drawing sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.1" path_parsing: @@ -985,7 +977,7 @@ packages: description: name: path_parsing sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" path_provider: @@ -993,7 +985,7 @@ packages: description: name: path_provider sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.5" path_provider_android: @@ -1001,7 +993,7 @@ packages: description: name: path_provider_android sha256: e122c5ea805bb6773bb12ce667611265980940145be920cd09a4b0ec0285cb16 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.20" path_provider_foundation: @@ -1009,7 +1001,7 @@ packages: description: name: path_provider_foundation sha256: efaec349ddfc181528345c56f8eda9d6cccd71c177511b132c6a0ddaefaa2738 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.3" path_provider_linux: @@ -1017,7 +1009,7 @@ packages: description: name: path_provider_linux sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.1" path_provider_platform_interface: @@ -1025,7 +1017,7 @@ packages: description: name: path_provider_platform_interface sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.2" path_provider_windows: @@ -1033,7 +1025,7 @@ packages: description: name: path_provider_windows sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.0" permission_handler: @@ -1041,7 +1033,7 @@ packages: description: name: permission_handler sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "12.0.1" permission_handler_android: @@ -1049,7 +1041,7 @@ packages: description: name: permission_handler_android sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "13.0.1" permission_handler_apple: @@ -1057,7 +1049,7 @@ packages: description: name: permission_handler_apple sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "9.4.7" permission_handler_html: @@ -1065,7 +1057,7 @@ packages: description: name: permission_handler_html sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.1.3+5" permission_handler_platform_interface: @@ -1073,7 +1065,7 @@ packages: description: name: permission_handler_platform_interface sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.3.0" permission_handler_windows: @@ -1081,7 +1073,7 @@ packages: description: name: permission_handler_windows sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.1" petitparser: @@ -1089,7 +1081,7 @@ packages: description: name: petitparser sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.1" photo_manager: @@ -1097,7 +1089,7 @@ packages: description: name: photo_manager sha256: a0d9a7a9bc35eda02d33766412bde6d883a8b0acb86bbe37dac5f691a0894e8a - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.7.1" photo_manager_image_provider: @@ -1105,7 +1097,7 @@ packages: description: name: photo_manager_image_provider sha256: b6015b67b32f345f57cf32c126f871bced2501236c405aafaefa885f7c821e4f - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" platform: @@ -1113,7 +1105,7 @@ packages: description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.6" plugin_platform_interface: @@ -1121,7 +1113,7 @@ packages: description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.8" pool: @@ -1129,7 +1121,7 @@ packages: description: name: pool sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.2" posix: @@ -1137,7 +1129,7 @@ packages: description: name: posix sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.0.3" protobuf: @@ -1145,7 +1137,7 @@ packages: description: name: protobuf sha256: "2fcc8a202ca7ec17dab7c97d6b6d91cf03aa07fe6f65f8afbb6dfa52cc5bd902" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.1.0" provider: @@ -1153,7 +1145,7 @@ packages: description: name: provider sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.1.5+1" pub_semver: @@ -1161,7 +1153,7 @@ packages: description: name: pub_semver sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" pubspec_parse: @@ -1169,7 +1161,7 @@ packages: description: name: pubspec_parse sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.0" pull_to_refresh: @@ -1177,7 +1169,7 @@ packages: description: name: pull_to_refresh sha256: bbadd5a931837b57739cf08736bea63167e284e71fb23b218c8c9a6e042aad12 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.0" rational: @@ -1185,7 +1177,7 @@ packages: description: name: rational sha256: cb808fb6f1a839e6fc5f7d8cb3b0a10e1db48b3be102de73938c627f0b636336 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.3" record: @@ -1193,7 +1185,7 @@ packages: description: name: record sha256: "6bad72fb3ea6708d724cf8b6c97c4e236cf9f43a52259b654efeb6fd9b737f1f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.1.2" record_android: @@ -1201,7 +1193,7 @@ packages: description: name: record_android sha256: fb54ee4e28f6829b8c580252a9ef49d9c549cfd263b0660ad7eeac0908658e9f - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.4" record_ios: @@ -1209,7 +1201,7 @@ packages: description: name: record_ios sha256: "765b42ac1be019b1674ddd809b811fc721fe5a93f7bb1da7803f0d16772fd6d7" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.4" record_linux: @@ -1217,7 +1209,7 @@ packages: description: name: record_linux sha256: "235b1f1fb84e810f8149cc0c2c731d7d697f8d1c333b32cb820c449bf7bb72d8" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.1" record_macos: @@ -1225,7 +1217,7 @@ packages: description: name: record_macos sha256: "842ea4b7e95f4dd237aacffc686d1b0ff4277e3e5357865f8d28cd28bc18ed95" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.2" record_platform_interface: @@ -1233,7 +1225,7 @@ packages: description: name: record_platform_interface sha256: b0065fdf1ec28f5a634d676724d388a77e43ce7646fb049949f58c69f3fcb4ed - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" record_web: @@ -1241,7 +1233,7 @@ packages: description: name: record_web sha256: "20ac10d56514cb9f8cecc8f3579383084fdfb43b0d04e05a95244d0d76091d90" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.1" record_windows: @@ -1249,7 +1241,7 @@ packages: description: name: record_windows sha256: "223258060a1d25c62bae18282c16783f28581ec19401d17e56b5205b9f039d78" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.7" retrofit: @@ -1257,7 +1249,7 @@ packages: description: name: retrofit sha256: "7d78824afa6eeeaf6ac58220910ee7a97597b39e93360d4bda230b7c6df45089" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.9.0" retrofit_generator: @@ -1265,7 +1257,7 @@ packages: description: name: retrofit_generator sha256: "56df50afab95199dada9e1afbfe5ec228612d03859b250e5e4846c3ebfe50bf7" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "10.1.4" rxdart: @@ -1273,7 +1265,7 @@ packages: description: name: rxdart sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.28.0" sensors_plus: @@ -1281,7 +1273,7 @@ packages: description: name: sensors_plus sha256: "89e2bfc3d883743539ce5774a2b93df61effde40ff958ecad78cd66b1a8b8d52" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.1.2" sensors_plus_platform_interface: @@ -1289,7 +1281,7 @@ packages: description: name: sensors_plus_platform_interface sha256: "58815d2f5e46c0c41c40fb39375d3f127306f7742efe3b891c0b1c87e2b5cd5d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.1" shared_preferences: @@ -1297,7 +1289,7 @@ packages: description: name: shared_preferences sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.5.3" shared_preferences_android: @@ -1305,7 +1297,7 @@ packages: description: name: shared_preferences_android sha256: "34266009473bf71d748912da4bf62d439185226c03e01e2d9687bc65bbfcb713" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.15" shared_preferences_foundation: @@ -1313,7 +1305,7 @@ packages: description: name: shared_preferences_foundation sha256: "1c33a907142607c40a7542768ec9badfd16293bac51da3a4482623d15845f88b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.5.5" shared_preferences_linux: @@ -1321,7 +1313,7 @@ packages: description: name: shared_preferences_linux sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.1" shared_preferences_platform_interface: @@ -1329,7 +1321,7 @@ packages: description: name: shared_preferences_platform_interface sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.1" shared_preferences_web: @@ -1337,7 +1329,7 @@ packages: description: name: shared_preferences_web sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.3" shared_preferences_windows: @@ -1345,7 +1337,7 @@ packages: description: name: shared_preferences_windows sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.1" shelf: @@ -1353,7 +1345,7 @@ packages: description: name: shelf sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.2" shelf_web_socket: @@ -1361,7 +1353,7 @@ packages: description: name: shelf_web_socket sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.0" sky_engine: @@ -1374,7 +1366,7 @@ packages: description: name: source_gen sha256: "9098ab86015c4f1d8af6486b547b11100e73b193e1899015033cb3e14ad20243" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.2" source_helper: @@ -1382,7 +1374,7 @@ packages: description: name: source_helper sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.8" source_span: @@ -1390,7 +1382,7 @@ packages: description: name: source_span sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.10.1" sp_util: @@ -1398,7 +1390,7 @@ packages: description: name: sp_util sha256: "9da43dce5de79c17a787d0626bf01538d63090ca32521200d22a232171c495dc" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.3" sqflite: @@ -1406,7 +1398,7 @@ packages: description: name: sqflite sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.2" sqflite_android: @@ -1414,7 +1406,7 @@ packages: description: name: sqflite_android sha256: ecd684501ebc2ae9a83536e8b15731642b9570dc8623e0073d227d0ee2bfea88 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.2+2" sqflite_common: @@ -1422,7 +1414,7 @@ packages: description: name: sqflite_common sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.5.6" sqflite_darwin: @@ -1430,7 +1422,7 @@ packages: description: name: sqflite_darwin sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.2" sqflite_platform_interface: @@ -1438,7 +1430,7 @@ packages: description: name: sqflite_platform_interface sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.0" stack_trace: @@ -1446,7 +1438,7 @@ packages: description: name: stack_trace sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.12.1" stream_channel: @@ -1454,7 +1446,7 @@ packages: description: name: stream_channel sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.4" stream_transform: @@ -1462,7 +1454,7 @@ packages: description: name: stream_transform sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" string_scanner: @@ -1470,7 +1462,7 @@ packages: description: name: string_scanner sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.1" synchronized: @@ -1478,7 +1470,7 @@ packages: description: name: synchronized sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.4.0" tdesign_flutter: @@ -1486,7 +1478,7 @@ packages: description: name: tdesign_flutter sha256: cf166a5fdbbfd9129305d2c2906633c8d0151bbb2d0a6fbcf901bdd76726a555 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.6" tdesign_flutter_adaptation: @@ -1494,7 +1486,7 @@ packages: description: name: tdesign_flutter_adaptation sha256: "707bbc52ec8b5872ea808500200f402007acf24c03a1cc823a3be2113c1d813a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.32.0" term_glyph: @@ -1502,7 +1494,7 @@ packages: description: name: term_glyph sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.2" test_api: @@ -1510,39 +1502,31 @@ packages: description: name: test_api sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.6" - tobias: - dependency: "direct main" - description: - name: tobias - sha256: "2b5520e622c0d6f04cfb5c9619211f923c97a602e1a3a8954e113e3e0e685c41" - url: "https://pub.flutter-io.cn" - source: hosted - version: "5.3.1" typed_data: dependency: transitive description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" universal_io: dependency: transitive description: name: universal_io - sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" - url: "https://pub.flutter-io.cn" + sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 + url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.1" uuid: dependency: transitive description: name: uuid sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.5.2" vector_math: @@ -1550,7 +1534,7 @@ packages: description: name: vector_math sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" video_player: @@ -1558,7 +1542,7 @@ packages: description: name: video_player sha256: "096bc28ce10d131be80dfb00c223024eb0fba301315a406728ab43dd99c45bdf" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.10.1" video_player_android: @@ -1566,7 +1550,7 @@ packages: description: name: video_player_android sha256: cf768d02924b91e333e2bc1ff928528f57d686445874f383bafab12d0bdfc340 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.8.17" video_player_avfoundation: @@ -1574,7 +1558,7 @@ packages: description: name: video_player_avfoundation sha256: "03fc6d07dba2499588d30887329b399c1fe2d68ce4b7fcff0db79f44a2603f69" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.8.6" video_player_platform_interface: @@ -1582,7 +1566,7 @@ packages: description: name: video_player_platform_interface sha256: "57c5d73173f76d801129d0531c2774052c5a7c11ccb962f1830630decd9f24ec" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.6.0" video_player_web: @@ -1590,7 +1574,7 @@ packages: description: name: video_player_web sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.0" video_thumbnail: @@ -1598,7 +1582,7 @@ packages: description: name: video_thumbnail sha256: "181a0c205b353918954a881f53a3441476b9e301641688a581e0c13f00dc588b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.6" visibility_detector: @@ -1606,7 +1590,7 @@ packages: description: name: visibility_detector sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.4.0+2" vm_service: @@ -1614,7 +1598,7 @@ packages: description: name: vm_service sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "15.0.2" wakelock_plus: @@ -1622,7 +1606,7 @@ packages: description: name: wakelock_plus sha256: "9296d40c9adbedaba95d1e704f4e0b434be446e2792948d0e4aa977048104228" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" wakelock_plus_platform_interface: @@ -1630,7 +1614,7 @@ packages: description: name: wakelock_plus_platform_interface sha256: "036deb14cd62f558ca3b73006d52ce049fabcdcb2eddfe0bf0fe4e8a943b5cf2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.0" watcher: @@ -1638,7 +1622,7 @@ packages: description: name: watcher sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.4" web: @@ -1646,7 +1630,7 @@ packages: description: name: web sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" web_socket: @@ -1654,7 +1638,7 @@ packages: description: name: web_socket sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.1" web_socket_channel: @@ -1662,7 +1646,7 @@ packages: description: name: web_socket_channel sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.3" wechat_assets_picker: @@ -1670,7 +1654,7 @@ packages: description: name: wechat_assets_picker sha256: c307e50394c1e6dfcd5c4701e84efb549fce71444fedcf2e671c50d809b3e2a1 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "9.8.0" wechat_camera_picker: @@ -1678,7 +1662,7 @@ packages: description: name: wechat_camera_picker sha256: "776ce32feda72d84b63425533a27d3b822bfb93cc063d2aef3cc6d788769f36b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.4.0" wechat_picker_library: @@ -1686,7 +1670,7 @@ packages: description: name: wechat_picker_library sha256: "5cb61b9aa935b60da5b043f8446fbb9c5077419f20ccc4856bf444aec4f44bc1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.7" win32: @@ -1694,7 +1678,7 @@ packages: description: name: win32 sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.15.0" xdg_directories: @@ -1702,7 +1686,7 @@ packages: description: name: xdg_directories sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" xml: @@ -1710,7 +1694,7 @@ packages: description: name: xml sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.6.1" xxh3: @@ -1718,7 +1702,7 @@ packages: description: name: xxh3 sha256: "399a0438f5d426785723c99da6b16e136f4953fb1e9db0bf270bd41dd4619916" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.0" yaml: @@ -1726,7 +1710,7 @@ packages: description: name: yaml sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.3" sdks: