diff --git a/docs/voice-room-emoji-plan.md b/docs/voice-room-emoji-plan.md new file mode 100644 index 0000000..4122409 --- /dev/null +++ b/docs/voice-room-emoji-plan.md @@ -0,0 +1,335 @@ +# Voice Room Emoji Package Plan + +## Goal + +This document only records a feasible implementation plan. No business code is changed in this round. + +Requirement summary: + +- Add an emoji package button next to the voice-room chat entry. +- The emoji package button and text chat must open the same bottom composer sheet. +- Emoji packages are shown only on mic seats. +- Emoji packages must not appear in room chat messages, including the `All`, `Chat`, and `Gift` tabs. +- Wait for final backend data and UI assets before starting the real implementation. + +## Current Codebase Status + +The current project already has several reusable pieces, so the feature is feasible and does not need a brand-new architecture. + +Reusable entry points: + +- Bottom area layout: `lib/ui_kit/widgets/room/room_bottom_widget.dart` +- Chat composer popup: `lib/ui_kit/widgets/room/room_msg_input.dart` +- Seat emoji display: `lib/modules/room/seat/sc_seat_item.dart` +- Room RTM send/receive: `lib/services/audio/rtm_manager.dart` +- Seat transient state: `lib/services/audio/rtc_manager.dart` +- Seat model: `lib/shared/business_logic/models/res/mic_res.dart` +- Emoji material API: `lib/shared/data_sources/sources/repositories/sc_room_repository_imp.dart` +- Emoji material model: `lib/shared/business_logic/models/res/sc_room_emoji_res.dart` +- Existing room message type: `lib/app/constants/sc_room_msg_type.dart` + +Confirmed reusable behavior in current code: + +- `SCRoomMsgType.emoticons` already exists. +- The room receiver already handles `EMOTICONS` separately and calls `RtcProvider.starPlayEmoji(msg)`. +- `SCSeatItem` already has an `Emoticons` widget with queueing, fade animation, and auto-dismiss. +- The project already has `/material/emoji/all`, and the response model already supports category + emoji list. + +## Recommended Architecture + +Recommended direction: keep one composer sheet and support two entry modes. + +Recommended entry modes: + +- `text` mode: opened from the existing chat entry, keyboard focused by default. +- `emojiPackage` mode: opened from the new emoji package button, keyboard hidden by default, emoji package panel open by default. + +Recommended widget strategy: + +- Reuse `RoomMsgInput` instead of creating a second bottom sheet. +- Add an input parameter such as `initialMode` or `initialPanel`. +- Keep the text input area as the same top row. +- Use the lower content area to switch between text helper emoji and room emoji package content. + +Why this is the best fit: + +- It matches the requirement that text chat and emoji package use the same bottom popup. +- It keeps interaction and style in one place. +- It avoids future drift between two different room composer implementations. + +## Recommended Interaction Flow + +### 1. Bottom bar + +Add a new emoji package button next to the room chat entry in `RoomBottomWidget`. + +Recommended behavior: + +- Tap chat entry: open `RoomMsgInput(initialMode: text)`. +- Tap emoji package button: open `RoomMsgInput(initialMode: emojiPackage)`. +- If the current user is not on mic, the emoji package button can either be disabled or show a toast such as "Take a mic first". + +Important layout note: + +- `RoomBottomWidget` currently uses hard-coded width math for the bottom bar and for `_resolveGiftCenterX(...)`. +- After adding one more action button, the row layout and gift floating button center calculation both need to be updated together. +- If only the row is changed and `_resolveGiftCenterX(...)` is not updated, the floating gift button can become visually misaligned. + +### 2. Composer sheet + +Recommended sheet structure: + +- Top area: existing input field, send button, and keyboard/emoji switch logic. +- Bottom area in `text` mode: current text emoji helper can remain for typing unicode emoji. +- Bottom area in `emojiPackage` mode: category tabs + emoji package grid from backend data. + +Recommended send interaction for emoji package: + +- Tapping an emoji package item sends immediately. +- The sheet should stay open after sending so the user can send multiple emoji packages continuously. +- If UI later wants tap-to-close, that can be a product choice, but continuous sending is the safer default for room interaction. + +### 3. Seat-only display + +Emoji package messages should not enter room chat lists. + +Recommended rule: + +- Text messages still follow the existing room chat path. +- Emoji package clicks trigger seat animation only. +- No new item should be inserted into `roomAllMsgList`, `roomChatMsgList`, or `roomGiftMsgList`. + +## Recommended Send Path + +### Recommended payload shape + +The smallest-change plan is to reuse the existing room custom message structure: + +```dart +Msg( + groupId: roomAccount, + type: SCRoomMsgType.emoticons, + msg: emoji.sourceUrl, + number: currentSeatIndex, + user: currentUserProfile, + role: currentUserRole, +) +``` + +Recommended field meaning: + +- `type`: `EMOTICONS` +- `msg`: selected emoji resource URL +- `number`: current seat index +- `user`: sender profile, for consistency with existing room messages + +### Why not send it as a normal chat message + +Because `RtmProvider.addMsg(...)` always inserts the message into `roomAllMsgList` first. + +Current receive side is already good enough: + +- In `_newGroupMsg(...)`, `EMOTICONS` goes directly to `RtcProvider.starPlayEmoji(msg)` and then `return`. +- That means remote users will not see emoji package content in room chat. + +Current sender side still needs care during implementation: + +- If the sender uses `dispatchMessage(...)` with default `addLocal: true`, the local sender will still push one item into `roomAllMsgList`. +- That would violate the requirement that emoji packages must not show in chat. + +Recommended implementation behavior later: + +- Build the `Msg`. +- First do a local optimistic seat display by calling `RtcProvider.starPlayEmoji(msg)`. +- Then call `dispatchMessage(msg, addLocal: false)`. + +This gives the sender instant seat feedback while keeping the chat list clean. + +## Recommended Seat Resolution Rule + +When sending an emoji package, determine the seat index at send time, not when the sheet is opened. + +Recommended lookup: + +- Use `RtcProvider.userOnMaiInIndex(currentUserId)` when the user taps an emoji item. + +Reason: + +- The user may switch mic seats after opening the popup. +- Using the latest seat index avoids showing the emoji on the wrong seat. + +If the returned seat index is `-1`: + +- Do not send. +- Show a toast telling the user that only users on mic can use emoji packages. + +## Backend Dependency Assessment + +### Material data + +The project already has `/material/emoji/all` and the local model already supports: + +- category name +- category cover +- category-level ownership state +- category-level amount +- emoji list +- emoji cover URL +- emoji source URL + +This means the current backend structure is already close to the requirement shown in the design. + +Backend items to confirm before development: + +- Whether `/material/emoji/all` is the final interface for this feature +- Whether category ordering is controlled by backend +- Whether each category has a tab icon or cover ready for UI +- Whether `coverUrl` is the correct image for the grid cell +- Whether `sourceUrl` is the real image used on the mic seat +- Whether ownership is category-level only or item-level + +If ownership later becomes item-level, the current model may need extension because it currently looks category-oriented. + +### No extra send API is strictly required + +For the minimal-change version, no new HTTP send API is needed. + +Recommended transport: + +- Use the existing room RTM custom message channel. +- Reuse `EMOTICONS` as the message type. + +This keeps the feature aligned with the current room event architecture. + +## Optional Sync Decision + +There are two possible product definitions for emoji package state: + +### Option A: transient RTM-only state + +Behavior: + +- Emoji package is only an instant seat effect. +- Users who join mid-animation do not need to recover the current emoji state. + +Pros: + +- Smallest frontend change +- No need for backend seat-state persistence +- Best fit for the current codebase + +Recommended default: + +- Yes. This should be the first implementation choice unless product explicitly wants state recovery. + +### Option B: recoverable seat state + +Behavior: + +- If a user joins the room late or reconnects, they can still see the currently active emoji package on the seat during its valid duration. + +If product wants this, backend and model changes are needed: + +- mic list response needs to include active emoji state +- active emoji state should include at least resource URL and expiration timing +- frontend model parsing needs to be updated + +Important current gap: + +- `MicRes.fromJson(...)` does not parse `emojiPath` +- `MicRes.toJson()` also does not serialize `emojiPath` + +So if the final backend plan depends on seat polling or room re-entry recovery, this model area will need a small follow-up patch during implementation. + +## Current Code Caveats To Remember + +### 1. `RoomMsgInput` is text-first today + +Current behavior: + +- It always autofocuses the text field. +- It only supports the local text emoji helper based on `SCEmojiDatas.smileys`. + +Meaning for future implementation: + +- It needs a mode parameter so opening from the emoji package button can skip keyboard autofocus and show the package panel first. + +### 2. Seat emoji display currently uses an implicit field contract + +Current behavior in `RtcProvider.starPlayEmoji(msg)`: + +- It writes `emojiPath: msg.msg` +- It writes `type: msg.type` +- It writes `number: msg.msg` + +Current behavior in `SCSeatItem.Emoticons`: + +- For dice and RPS, `number` is treated like a result value +- For other types, `number` is treated like an image URL + +Meaning: + +- The current image emoji path works because the code uses a field-reuse convention. +- Later implementation should stay compatible with this path unless the seat overlay model is cleaned up in one pass. + +### 3. Emoji cache utility exists but is not wired into the room sheet yet + +`SCAppGeneralManager` already has: + +- `emojiByTab` +- `emojiAll()` + +But this is not currently connected to the room composer. + +Recommended later choice: + +- Either reuse `SCAppGeneralManager` for caching +- Or load emoji package data directly inside the room sheet and cache locally there + +Either is feasible. Reusing the manager is better if the same materials are used in multiple room surfaces. + +## Suggested Development Sequence Later + +When backend and UI are ready, the development order should be: + +1. Add the new emoji package button in `RoomBottomWidget` and adjust layout math together with `_resolveGiftCenterX(...)`. +2. Refactor `RoomMsgInput` into one shared room composer with `text` and `emojiPackage` entry modes. +3. Wire the sheet to load emoji categories and emoji items from `/material/emoji/all`. +4. Add on-mic gating and resolve seat index at click time. +5. On emoji package click, do local optimistic seat playback. +6. Send RTM `EMOTICONS` with `addLocal: false`. +7. Verify that `All`, `Chat`, and `Gift` tabs remain unchanged after sending. +8. If product wants reconnect recovery, then patch `MicRes` parsing and seat sync logic. + +## Acceptance Checklist + +- New emoji package button appears next to the room chat entry. +- Chat entry and emoji package button open the same bottom composer sheet. +- Opening from chat goes to text mode. +- Opening from emoji package goes to emoji package mode. +- Only users on mic can send emoji packages. +- Sender sees the emoji package on their own seat immediately. +- Other users see the emoji package on the sender's seat. +- Emoji package sending does not create new rows in `All`, `Chat`, or `Gift`. +- Existing text chat sending is not affected. +- Existing gift floating button remains visually centered after the new button is added. +- Repeated emoji package taps queue and play correctly on the seat. + +## Final Recommendation + +This feature is feasible with low-to-medium implementation risk because the project already has the key building blocks: + +- shared room composer entry +- room RTM custom message channel +- `EMOTICONS` message type +- seat emoji playback widget +- emoji material API + +Recommended final direction: + +- Reuse the existing room composer popup +- Reuse `EMOTICONS` as the transport type +- Use seat-index-based RTM payload +- Do local optimistic seat playback +- Do not insert emoji package messages into any chat list +- Treat backend seat-state recovery as optional, not mandatory diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 0f28cd6..223ca63 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -502,7 +502,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = S9X2AJ2US9; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -511,7 +511,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.1; + MARKETING_VERSION = 1.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.org.yumiparty; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -693,7 +693,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = F33K8VUZ62; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -702,7 +702,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.1; + MARKETING_VERSION = 1.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.org.yumiparty; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -722,7 +722,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = F33K8VUZ62; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -731,7 +731,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.1; + MARKETING_VERSION = 1.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.org.yumiparty; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/lib/modules/room/detail/room_detail_page.dart b/lib/modules/room/detail/room_detail_page.dart index 6d2b505..b0e4c3a 100644 --- a/lib/modules/room/detail/room_detail_page.dart +++ b/lib/modules/room/detail/room_detail_page.dart @@ -21,6 +21,7 @@ import '../../../ui_kit/components/sc_debounce_widget.dart'; import '../../../ui_kit/components/sc_tts.dart'; import '../../../ui_kit/components/dialog/dialog_base.dart'; import '../../../ui_kit/components/text/sc_text.dart'; +import '../../../ui_kit/widgets/id/sc_special_id_badge.dart'; import '../../../main.dart'; import '../../index/main_route.dart'; @@ -153,10 +154,41 @@ class _RoomDetailPageState extends State { SizedBox(height: 5.w), Row( children: [ - text( - "ID:${ref.currenRoom?.roomProfile?.userProfile?.getID()}", - fontSize: 12.sp, - textColor: Colors.black, + SCSpecialIdBadge( + idText: + ref + .currenRoom + ?.roomProfile + ?.roomProfile + ?.roomAccount ?? + "", + showAnimated: + (ref + .currenRoom + ?.roomProfile + ?.roomProfile + ?.roomAccount + ?.isNotEmpty ?? + false), + assetPath: + SCSpecialIdAssets.roomId, + animationWidth: 124.w, + animationHeight: 30.w, + textPadding: EdgeInsets.fromLTRB( + 36.w, + 7.w, + 18.w, + 7.w, + ), + animationTextStyle: TextStyle( + color: Colors.white, + fontSize: 12.sp, + fontWeight: FontWeight.w700, + ), + normalTextStyle: TextStyle( + color: Colors.black, + fontSize: 12.sp, + ), ), SizedBox(width: 3.w), GestureDetector( @@ -278,10 +310,44 @@ class _RoomDetailPageState extends State { ), Row( children: [ - text( - "ID:${ref.currenRoom?.roomProfile?.userProfile?.account}", - textColor: Colors.black, - fontSize: 14.sp, + SCSpecialIdBadge( + idText: + ref + .currenRoom + ?.roomProfile + ?.userProfile + ?.getID() ?? + "", + showAnimated: + ref + .currenRoom + ?.roomProfile + ?.userProfile + ?.hasSpecialId() ?? + false, + assetPath: + SCSpecialIdAssets + .roomOwnerId, + animationWidth: 132.w, + animationHeight: 32.w, + textPadding: + EdgeInsets.fromLTRB( + 40.w, + 8.w, + 18.w, + 8.w, + ), + animationTextStyle: + TextStyle( + color: Colors.white, + fontSize: 13.sp, + fontWeight: + FontWeight.w700, + ), + normalTextStyle: TextStyle( + color: Colors.black, + fontSize: 14.sp, + ), ), SizedBox(width: 3.w), GestureDetector( @@ -304,7 +370,7 @@ class _RoomDetailPageState extends State { .currenRoom ?.roomProfile ?.userProfile - ?.account ?? + ?.getID() ?? "", ), ); diff --git a/lib/modules/room/online/room_online_page.dart b/lib/modules/room/online/room_online_page.dart index 44476e5..4372144 100644 --- a/lib/modules/room/online/room_online_page.dart +++ b/lib/modules/room/online/room_online_page.dart @@ -12,6 +12,7 @@ import '../../../ui_kit/components/sc_compontent.dart'; import '../../../ui_kit/components/sc_page_list.dart'; import '../../../ui_kit/components/sc_tts.dart'; import '../../../ui_kit/components/text/sc_text.dart'; +import '../../../ui_kit/widgets/id/sc_special_id_badge.dart'; import '../../../shared/tools/sc_lk_dialog_util.dart'; import '../../../ui_kit/widgets/room/room_user_info_card.dart'; @@ -148,22 +149,26 @@ class _RoomOnlinePageState GestureDetector( child: Container( padding: EdgeInsets.symmetric(vertical: 3.w), - child: Row( - textDirection: TextDirection.ltr, - children: [ - text( - "ID:${userInfo.getID()}", - fontSize: 12.sp, - textColor: Colors.black, - fontWeight: FontWeight.bold, - ), - SizedBox(width: 5.w), - Image.asset( - "sc_images/room/sc_icon_user_card_copy_id.png", - width: 12.w, - height: 12.w, - ), - ], + child: SCSpecialIdBadge( + idText: userInfo.getID(), + showAnimated: userInfo.hasSpecialId(), + assetPath: SCSpecialIdAssets.userId, + animationWidth: 110.w, + animationHeight: 28.w, + textPadding: EdgeInsets.fromLTRB(33.w, 6.w, 16.w, 6.w), + animationTextStyle: TextStyle( + color: Colors.white, + fontSize: 12.sp, + fontWeight: FontWeight.bold, + ), + normalTextStyle: TextStyle( + color: Colors.black, + fontSize: 12.sp, + fontWeight: FontWeight.bold, + ), + showCopyIcon: true, + copyIconSize: 12.w, + copyIconSpacing: 5.w, ), ), onTap: () { diff --git a/lib/modules/room/seat/sc_seat_item.dart b/lib/modules/room/seat/sc_seat_item.dart index 764c66c..9c1592e 100644 --- a/lib/modules/room/seat/sc_seat_item.dart +++ b/lib/modules/room/seat/sc_seat_item.dart @@ -28,6 +28,7 @@ class SCSeatItem extends StatefulWidget { class _SCSeatItemState extends State with TickerProviderStateMixin { static const String _seatHeartbeatValueIconAsset = "sc_images/room/sc_icon_room_seat_heartbeat_value.png"; + static const double _seatHeaddressScaleMultiplier = 1.3; RtcProvider? provider; _SeatRenderSnapshot? _cachedSnapshot; @@ -56,6 +57,8 @@ class _SCSeatItemState extends State with TickerProviderStateMixin { window.locale.languageCode == "ar" ? "" : seatSnapshot.headdressSourceUrl; + final double seatBaseSize = widget.isGameModel ? 40.w : 55.w; + final bool hasHeaddress = resolvedHeaddress.isNotEmpty; return GestureDetector( behavior: HitTestBehavior.opaque, @@ -66,9 +69,10 @@ class _SCSeatItemState extends State with TickerProviderStateMixin { children: [ SizedBox( key: _targetKey, - width: widget.isGameModel ? 40.w : 55.w, - height: widget.isGameModel ? 40.w : 55.w, + width: seatBaseSize, + height: seatBaseSize, child: Stack( + clipBehavior: Clip.none, alignment: Alignment.center, children: [ Sonic( @@ -77,10 +81,15 @@ class _SCSeatItemState extends State with TickerProviderStateMixin { isGameModel: widget.isGameModel, ), seatSnapshot.hasUser - ? head( - url: seatSnapshot.userAvatar, - width: widget.isGameModel ? 40.w : 55.w, - headdress: resolvedHeaddress, + ? Transform.scale( + scale: + hasHeaddress ? _seatHeaddressScaleMultiplier : 1, + child: head( + url: seatSnapshot.userAvatar, + width: seatBaseSize, + height: seatBaseSize, + headdress: resolvedHeaddress, + ), ) : (seatSnapshot.micLock ? Image.asset( diff --git a/lib/modules/user/me_page2.dart b/lib/modules/user/me_page2.dart index 4d66c40..63d682e 100644 --- a/lib/modules/user/me_page2.dart +++ b/lib/modules/user/me_page2.dart @@ -14,6 +14,7 @@ import 'package:yumi/shared/data_sources/sources/local/user_manager.dart'; import 'package:yumi/shared/data_sources/sources/repositories/sc_user_repository_impl.dart'; import 'package:yumi/ui_kit/components/sc_compontent.dart'; import 'package:yumi/ui_kit/components/sc_debounce_widget.dart'; +import 'package:yumi/ui_kit/widgets/id/sc_special_id_badge.dart'; class MePage2 extends StatefulWidget { const MePage2({super.key}); @@ -153,9 +154,19 @@ class _MePage2State extends State { ), ), SizedBox(height: 2.w), - Text( - 'ID:${profile?.account ?? ''}', - style: TextStyle( + SCSpecialIdBadge( + idText: profile?.getID() ?? '', + showAnimated: profile?.hasSpecialId() ?? false, + assetPath: SCSpecialIdAssets.userIdLarge, + animationWidth: 150.w, + animationHeight: 34.w, + textPadding: EdgeInsets.fromLTRB(48.w, 8.w, 18.w, 8.w), + animationTextStyle: TextStyle( + color: Colors.white, + fontSize: 16.sp, + fontWeight: FontWeight.w700, + ), + normalTextStyle: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.w600, diff --git a/lib/modules/user/profile/person_detail_page.dart b/lib/modules/user/profile/person_detail_page.dart index 3f5c631..882163a 100644 --- a/lib/modules/user/profile/person_detail_page.dart +++ b/lib/modules/user/profile/person_detail_page.dart @@ -34,6 +34,7 @@ import '../../../app/constants/sc_screen.dart'; import '../../../shared/business_logic/models/res/sc_user_counter_res.dart'; import '../../../shared/business_logic/models/res/sc_user_identity_res.dart'; import '../../../shared/business_logic/usecases/sc_fixed_width_tabIndicator.dart'; +import '../../../ui_kit/widgets/id/sc_special_id_badge.dart'; import '../../chat/chat_route.dart'; class PersonDetailPage extends StatefulWidget { @@ -398,11 +399,23 @@ class _PersonDetailPageState extends State Row( children: [ SizedBox(width: 25.w), - text( - "ID:${ref.userProfile?.account ?? ""}", - textColor: Colors.white, - fontWeight: FontWeight.w400, - fontSize: 16.sp, + SCSpecialIdBadge( + idText: ref.userProfile?.getID() ?? "", + showAnimated: ref.userProfile?.hasSpecialId() ?? false, + assetPath: SCSpecialIdAssets.userIdLarge, + animationWidth: 150.w, + animationHeight: 34.w, + textPadding: EdgeInsets.fromLTRB(48.w, 8.w, 18.w, 8.w), + animationTextStyle: TextStyle( + color: Colors.white, + fontSize: 16.sp, + fontWeight: FontWeight.w700, + ), + normalTextStyle: TextStyle( + color: Colors.white, + fontSize: 16.sp, + fontWeight: FontWeight.w400, + ), ), ], ), diff --git a/lib/shared/business_logic/models/res/login_res.dart b/lib/shared/business_logic/models/res/login_res.dart index fa628e4..5bd258e 100644 --- a/lib/shared/business_logic/models/res/login_res.dart +++ b/lib/shared/business_logic/models/res/login_res.dart @@ -568,7 +568,7 @@ class SocialChatUserProfile { ///获取Id,有靓号显示靓号 String getID() { String uid = account ?? ""; - if (_ownSpecialId != null) { + if (hasSpecialId()) { uid = _ownSpecialId?.account ?? ""; } return uid; diff --git a/lib/ui_kit/widgets/id/sc_special_id_badge.dart b/lib/ui_kit/widgets/id/sc_special_id_badge.dart new file mode 100644 index 0000000..21c0e01 --- /dev/null +++ b/lib/ui_kit/widgets/id/sc_special_id_badge.dart @@ -0,0 +1,145 @@ +import 'package:flutter/material.dart'; +import 'package:yumi/ui_kit/widgets/svga/sc_svga_asset_widget.dart'; + +class SCSpecialIdAssets { + static const String roomId = 'sc_images/general/room_id.svga'; + static const String roomOwnerId = 'sc_images/general/room_id_custom.svga'; + static const String userId = 'sc_images/general/user_id.svga'; + static const String userIdLarge = 'sc_images/general/user_id_4.svga'; +} + +class SCSpecialIdBadge extends StatelessWidget { + const SCSpecialIdBadge({ + super.key, + required this.idText, + this.showAnimated = false, + this.assetPath, + this.animationWidth = 120, + this.animationHeight = 28, + this.textPadding = EdgeInsets.zero, + this.animationTextStyle, + this.normalTextStyle, + this.normalPrefix = 'ID:', + this.showCopyIcon = false, + this.copyIconAssetPath = 'sc_images/room/sc_icon_user_card_copy_id.png', + this.copyIconSize = 12, + this.copyIconSpacing = 5, + this.copyIconColor, + this.loop = true, + this.active = true, + this.animationFit = BoxFit.fill, + }); + + final String idText; + final bool showAnimated; + final String? assetPath; + final double animationWidth; + final double animationHeight; + final EdgeInsetsGeometry textPadding; + final TextStyle? animationTextStyle; + final TextStyle? normalTextStyle; + final String normalPrefix; + final bool showCopyIcon; + final String copyIconAssetPath; + final double copyIconSize; + final double copyIconSpacing; + final Color? copyIconColor; + final bool loop; + final bool active; + final BoxFit animationFit; + + @override + Widget build(BuildContext context) { + final normalizedId = idText.trim(); + final shouldAnimate = + showAnimated && + (assetPath?.isNotEmpty ?? false) && + normalizedId.isNotEmpty; + + final children = [ + shouldAnimate + ? _buildAnimatedBadge(normalizedId) + : _buildPlainBadge(normalizedId), + ]; + + if (showCopyIcon) { + children.add(SizedBox(width: copyIconSpacing)); + children.add( + Image.asset( + copyIconAssetPath, + width: copyIconSize, + height: copyIconSize, + color: copyIconColor, + ), + ); + } + + return Row( + mainAxisSize: MainAxisSize.min, + textDirection: TextDirection.ltr, + children: children, + ); + } + + Widget _buildAnimatedBadge(String normalizedId) { + return SizedBox( + width: animationWidth, + height: animationHeight, + child: Stack( + clipBehavior: Clip.none, + children: [ + Positioned.fill( + child: SCSvgaAssetWidget( + assetPath: assetPath!, + width: animationWidth, + height: animationHeight, + active: active, + loop: loop, + fit: animationFit, + fallback: const SizedBox.shrink(), + ), + ), + Positioned.fill( + child: Padding( + padding: textPadding, + child: Align( + alignment: Alignment.centerLeft, + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: Text( + normalizedId, + maxLines: 1, + overflow: TextOverflow.visible, + style: + animationTextStyle ?? + const TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w700, + ), + ), + ), + ), + ), + ), + ], + ), + ); + } + + Widget _buildPlainBadge(String normalizedId) { + return Text( + '$normalPrefix$normalizedId', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: + normalTextStyle ?? + const TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ); + } +} diff --git a/lib/ui_kit/widgets/room/anim/room_gift_seat_flight_overlay.dart b/lib/ui_kit/widgets/room/anim/room_gift_seat_flight_overlay.dart index c53eaa6..42bfcd6 100644 --- a/lib/ui_kit/widgets/room/anim/room_gift_seat_flight_overlay.dart +++ b/lib/ui_kit/widgets/room/anim/room_gift_seat_flight_overlay.dart @@ -256,6 +256,7 @@ class _RoomGiftSeatFlightOverlayState extends State _ensureCenterVisual(request); _trimQueuedRequestsOverflow(); _queue.add(_QueuedRoomGiftSeatFlightRequest(request: request)); + _syncIdleCenterVisual(); _scheduleNextAnimation(); } @@ -328,17 +329,7 @@ class _RoomGiftSeatFlightOverlayState extends State for (final queuedRequest in requestsToRemove) { _queue.remove(queuedRequest); } - if (!_isPlaying && _queue.isEmpty) { - if (!mounted) { - _centerRequest = null; - _centerImageProvider = null; - return; - } - setState(() { - _centerRequest = null; - _centerImageProvider = null; - }); - } + _syncIdleCenterVisual(); } int _countTrackedRequests(String queueTag) { @@ -406,6 +397,7 @@ class _RoomGiftSeatFlightOverlayState extends State _scheduleNextAnimation(); }); } else { + _syncIdleCenterVisual(); _scheduleNextAnimation(); } return; @@ -443,28 +435,21 @@ class _RoomGiftSeatFlightOverlayState extends State } void _finishCurrentAnimation() { - final hasPendingRequests = _queue.isNotEmpty; if (!mounted) { - if (!hasPendingRequests) { - _centerRequest = null; - _centerImageProvider = null; - } _activeRequest = null; _activeImageProvider = null; _activeTargetOffset = null; _isPlaying = false; + _syncIdleCenterVisual(); return; } setState(() { - if (!hasPendingRequests) { - _centerRequest = null; - _centerImageProvider = null; - } _activeRequest = null; _activeImageProvider = null; _activeTargetOffset = null; _isPlaying = false; }); + _syncIdleCenterVisual(); _scheduleNextAnimation(); } @@ -472,7 +457,10 @@ class _RoomGiftSeatFlightOverlayState extends State if (_centerRequest != null && _centerImageProvider != null) { return; } - final imageProvider = _resolveImageProvider(request.imagePath); + final imageProvider = _resolveImageProvider( + request.imagePath, + request: request, + ); if (!mounted) { _centerRequest = request; _centerImageProvider = imageProvider; @@ -484,6 +472,39 @@ class _RoomGiftSeatFlightOverlayState extends State }); } + void _syncIdleCenterVisual() { + if (_isPlaying || _activeRequest != null) { + return; + } + + final nextRequest = _queue.isNotEmpty ? _queue.first.request : null; + final nextImageProvider = + nextRequest == null + ? null + : _resolveImageProvider( + nextRequest.imagePath, + request: nextRequest, + ); + + if (!mounted) { + _centerRequest = nextRequest; + _centerImageProvider = nextImageProvider; + return; + } + + final shouldUpdate = + _centerRequest != nextRequest || + _centerImageProvider != nextImageProvider; + if (!shouldUpdate) { + return; + } + + setState(() { + _centerRequest = nextRequest; + _centerImageProvider = nextImageProvider; + }); + } + Offset? _resolveTargetOffset(String targetUserId) { final overlayContext = _overlayKey.currentContext; final targetKey = widget.resolveTargetKey(targetUserId); @@ -507,8 +528,11 @@ class _RoomGiftSeatFlightOverlayState extends State return overlayBox.globalToLocal(globalTargetCenter); } - ImageProvider _resolveImageProvider(String imagePath) { - final currentRequest = _activeRequest ?? _centerRequest; + ImageProvider _resolveImageProvider( + String imagePath, { + RoomGiftSeatFlightRequest? request, + }) { + final currentRequest = request ?? _activeRequest ?? _centerRequest; final logicalSize = currentRequest == null ? null diff --git a/lib/ui_kit/widgets/room/effect/luck_gift_nomor_anim_widget.dart b/lib/ui_kit/widgets/room/effect/luck_gift_nomor_anim_widget.dart index d0120ac..68858da 100644 --- a/lib/ui_kit/widgets/room/effect/luck_gift_nomor_anim_widget.dart +++ b/lib/ui_kit/widgets/room/effect/luck_gift_nomor_anim_widget.dart @@ -3,6 +3,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:provider/provider.dart'; import 'package:yumi/shared/business_logic/models/res/sc_broad_cast_luck_gift_push.dart'; import 'package:yumi/services/audio/rtm_manager.dart'; +import 'package:yumi/ui_kit/components/sc_compontent.dart'; import 'package:yumi/ui_kit/widgets/svga/sc_svga_asset_widget.dart'; class LuckGiftNomorAnimWidget extends StatefulWidget { @@ -17,6 +18,20 @@ class LuckGiftNomorAnimWidget extends StatefulWidget { } class _LuckGiftNomorAnimWidgetState extends State { + static const double _groupShiftXRatio = 26 / 422; + static const double _groupShiftYRatio = 18 / 422; + static const double _groupShiftYExtraUnits = 40; + static const double _avatarScale = 0.8; + static const double _avatarExtraShiftXUnits = -2; + static const double _avatarExtraShiftYUnits = 18; + static const double _avatarDiameterRatio = 76 / 422; + static const double _avatarLeftRatio = 152 / 422; + static const double _avatarTopRatio = 64 / 422; + static const double _awardTopRatio = 153 / 422; + static const double _awardXOffsetRatio = -13 / 422; + static const double _multipleTopRatio = 193 / 422; + static const double _multipleXOffsetRatio = -22 / 422; + String? _currentBurstEventId; bool _isRewardAmountVisible = false; @@ -34,6 +49,48 @@ class _LuckGiftNomorAnimWidgetState extends State { return awardAmount.toString(); } + String _formatMultiple(num multiple) { + if (multiple % 1 == 0) { + return multiple.toInt().toString(); + } + return multiple.toString(); + } + + Widget _buildSenderAvatar({ + required String avatarUrl, + required double outerSize, + }) { + final avatarPadding = outerSize * 0.045; + final innerSize = outerSize - avatarPadding * 2; + return RepaintBoundary( + child: Container( + width: outerSize, + height: outerSize, + padding: EdgeInsets.all(avatarPadding), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: const Color(0xFFFFD680), + boxShadow: const [ + BoxShadow( + color: Color(0x55243A74), + blurRadius: 16, + offset: Offset(0, 6), + ), + ], + ), + child: ClipOval( + child: netImage( + url: avatarUrl, + width: innerSize, + height: innerSize, + fit: BoxFit.cover, + shape: BoxShape.circle, + ), + ), + ), + ); + } + @override Widget build(BuildContext context) { return IgnorePointer( @@ -45,6 +102,28 @@ class _LuckGiftNomorAnimWidgetState extends State { _isRewardAmountVisible = false; return const SizedBox.shrink(); } + final screenWidth = ScreenUtil().screenWidth; + final groupShiftX = screenWidth * _groupShiftXRatio; + final groupShiftY = + screenWidth * _groupShiftYRatio + _groupShiftYExtraUnits.w; + final avatarBaseDiameter = screenWidth * _avatarDiameterRatio; + final avatarDiameter = avatarBaseDiameter * _avatarScale; + final avatarInset = (avatarBaseDiameter - avatarDiameter) / 2; + final avatarLeft = + screenWidth * _avatarLeftRatio + + groupShiftX + + avatarInset + + _avatarExtraShiftXUnits.w; + final avatarTop = + screenWidth * _avatarTopRatio + + groupShiftY + + avatarInset + + _avatarExtraShiftYUnits.w; + final awardTop = screenWidth * _awardTopRatio + groupShiftY; + final awardXOffset = screenWidth * _awardXOffsetRatio + groupShiftX; + final multipleTop = screenWidth * _multipleTopRatio + groupShiftY; + final multipleXOffset = + screenWidth * _multipleXOffsetRatio + groupShiftX; final rewardAnimationKey = ValueKey( '${rewardData.sendUserId ?? ""}' '|${rewardData.acceptUserId ?? ""}' @@ -93,37 +172,83 @@ class _LuckGiftNomorAnimWidgetState extends State { }, ), ), + if (_isRewardAmountVisible && + (rewardData.userAvatar ?? '').trim().isNotEmpty) + Positioned( + left: avatarLeft, + top: avatarTop, + child: _buildSenderAvatar( + avatarUrl: (rewardData.userAvatar ?? '').trim(), + outerSize: avatarDiameter, + ), + ), if (_isRewardAmountVisible) - Positioned.fill( - child: Align( - alignment: const Alignment(0, 0.12), - child: Transform.translate( - offset: Offset(5.w, -4.w), + Positioned( + top: awardTop, + left: 0, + right: 0, + child: Transform.translate( + offset: Offset(awardXOffset, 0), + child: Center( child: ConstrainedBox( constraints: BoxConstraints( - maxWidth: ScreenUtil().screenWidth * 0.56, + maxWidth: screenWidth * 0.34, ), child: FittedBox( fit: BoxFit.scaleDown, - child: Padding( - padding: EdgeInsets.only(left: 0.w, right: 0.w), - child: Text( - _formatAwardAmount(rewardData.awardAmount ?? 0), - maxLines: 1, - style: TextStyle( - fontSize: 28.sp, - color: const Color(0xFFFFF3B6), - fontWeight: FontWeight.w900, - fontStyle: FontStyle.italic, - height: 1, - shadows: const [ - Shadow( - color: Color(0xCC7A3E00), - blurRadius: 12, - offset: Offset(0, 3), - ), - ], - ), + child: Text( + _formatAwardAmount(rewardData.awardAmount ?? 0), + maxLines: 1, + style: TextStyle( + fontSize: 28.sp, + color: const Color(0xFFFFF3B6), + fontWeight: FontWeight.w900, + fontStyle: FontStyle.italic, + height: 1, + shadows: const [ + Shadow( + color: Color(0xCC7A3E00), + blurRadius: 12, + offset: Offset(0, 3), + ), + ], + ), + ), + ), + ), + ), + ), + ), + if (_isRewardAmountVisible && (rewardData.multiple ?? 0) > 0) + Positioned( + top: multipleTop, + left: 0, + right: 0, + child: Transform.translate( + offset: Offset(multipleXOffset, 0), + child: Center( + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: screenWidth * 0.18, + ), + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + 'x${_formatMultiple(rewardData.multiple ?? 0)}', + maxLines: 1, + style: TextStyle( + fontSize: 17.sp, + color: const Color(0xFFF4F6FF), + fontWeight: FontWeight.w800, + fontStyle: FontStyle.italic, + height: 1, + shadows: const [ + Shadow( + color: Color(0x990B2D72), + blurRadius: 10, + offset: Offset(0, 2), + ), + ], ), ), ), diff --git a/lib/ui_kit/widgets/room/room_user_info_card.dart b/lib/ui_kit/widgets/room/room_user_info_card.dart index 811160b..c0c87e3 100644 --- a/lib/ui_kit/widgets/room/room_user_info_card.dart +++ b/lib/ui_kit/widgets/room/room_user_info_card.dart @@ -26,6 +26,7 @@ import 'package:yumi/services/general/sc_app_general_manager.dart'; import 'package:yumi/services/audio/rtc_manager.dart'; import 'package:yumi/services/auth/user_profile_manager.dart'; import 'package:yumi/modules/gift/gift_page.dart'; +import 'package:yumi/ui_kit/widgets/id/sc_special_id_badge.dart'; import '../../../shared/data_sources/models/enum/sc_room_roles_type.dart'; import '../../../shared/business_logic/models/res/sc_user_identity_res.dart'; @@ -265,11 +266,40 @@ class _RoomUserInfoCardState extends State { ], ), SizedBox(height: 2.w), - text( - "ID:${ref.userCardInfo?.userProfile?.getID() ?? 0}", - fontSize: 12.sp, - textColor: Colors.black, - fontWeight: FontWeight.bold, + SCSpecialIdBadge( + idText: + ref + .userCardInfo + ?.userProfile + ?.getID() ?? + "", + showAnimated: + ref + .userCardInfo + ?.userProfile + ?.hasSpecialId() ?? + false, + assetPath: + SCSpecialIdAssets.userId, + animationWidth: 110.w, + animationHeight: 28.w, + textPadding: + EdgeInsets.fromLTRB( + 33.w, + 6.w, + 16.w, + 6.w, + ), + animationTextStyle: TextStyle( + color: Colors.white, + fontSize: 12.sp, + fontWeight: FontWeight.bold, + ), + normalTextStyle: TextStyle( + color: Colors.black, + fontSize: 12.sp, + fontWeight: FontWeight.bold, + ), ), ], ), diff --git a/pubspec.lock b/pubspec.lock index 31f9492..7e25cb1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -6,7 +6,7 @@ packages: description: name: _flutterfire_internals sha256: ff0a84a2734d9e1089f8aedd5c0af0061b82fb94e95260d943404e0ef2134b11 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.59" agora_rtc_engine: @@ -14,7 +14,7 @@ packages: description: name: agora_rtc_engine sha256: "6559294d18ce4445420e19dbdba10fb58cac955cd8f22dbceae26716e194d70e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.5.3" app_links: @@ -22,7 +22,7 @@ packages: description: name: app_links sha256: "5f88447519add627fe1cbcab4fd1da3d4fed15b9baf29f28b22535c95ecee3e8" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.4.1" app_links_linux: @@ -30,7 +30,7 @@ packages: description: name: app_links_linux sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" app_links_platform_interface: @@ -38,7 +38,7 @@ packages: description: name: app_links_platform_interface sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.2" app_links_web: @@ -46,7 +46,7 @@ packages: description: name: app_links_web sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.4" archive: @@ -54,7 +54,7 @@ packages: description: name: archive sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.0.9" args: @@ -62,7 +62,7 @@ packages: description: name: args sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.7.0" async: @@ -70,7 +70,7 @@ packages: description: name: async sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.13.1" audioplayers: @@ -78,7 +78,7 @@ packages: description: name: audioplayers sha256: a72dd459d1a48f61a6fb9c0134dba26597c9236af40639ff0eb70eb4e0baab70 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.6.0" audioplayers_android: @@ -86,7 +86,7 @@ packages: description: name: audioplayers_android sha256: "60a6728277228413a85755bd3ffd6fab98f6555608923813ce383b190a360605" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.2.1" audioplayers_darwin: @@ -94,7 +94,7 @@ packages: description: name: audioplayers_darwin sha256: c994b3bb3a921e4904ac40e013fbc94488e824fd7c1de6326f549943b0b44a91 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.4.0" audioplayers_linux: @@ -102,7 +102,7 @@ packages: description: name: audioplayers_linux sha256: f75bce1ce864170ef5e6a2c6a61cd3339e1a17ce11e99a25bae4474ea491d001 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.2.1" audioplayers_platform_interface: @@ -110,7 +110,7 @@ packages: description: name: audioplayers_platform_interface sha256: "0e2f6a919ab56d0fec272e801abc07b26ae7f31980f912f24af4748763e5a656" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.1.1" audioplayers_web: @@ -118,7 +118,7 @@ packages: description: name: audioplayers_web sha256: faa8fa6587f996a6f604433b53af44c57a1407d4fe8dff5766cf63d6875e8de9 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.2.0" audioplayers_windows: @@ -126,7 +126,7 @@ packages: description: name: audioplayers_windows sha256: bafff2b38b6f6d331887558ba6e0a01c9c208d9dbb3ad0005234db065122a734 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.3.0" back_button_interceptor: @@ -134,23 +134,23 @@ packages: description: name: back_button_interceptor sha256: b85977faabf4aeb95164b3b8bf81784bed4c54ea1aef90a036ab6927ecf80c5a - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "8.0.4" badges: dependency: "direct main" description: name: badges - sha256: a7b6bbd60dce418df0db3058b53f9d083c22cdb5132a052145dc267494df0b84 - url: "https://pub.dev" + sha256: cf1c88fb3777df69ccd630b80de5267f54efa4a39381b0404a7c03d56cb7c041 + url: "https://pub.flutter-io.cn" source: hosted - version: "3.1.2" + version: "3.2.0" boolean_selector: dependency: transitive description: name: boolean_selector sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" cached_network_image: @@ -158,7 +158,7 @@ packages: description: name: cached_network_image sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.4.1" cached_network_image_platform_interface: @@ -166,7 +166,7 @@ packages: description: name: cached_network_image_platform_interface sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.1.1" cached_network_image_web: @@ -174,7 +174,7 @@ packages: description: name: cached_network_image_web sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.1" carousel_slider: @@ -182,7 +182,7 @@ packages: description: name: carousel_slider sha256: febf4b0163e0242adc13d7a863b04965351f59e7dfea56675c7c2caa7bcd7476 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.1.2" characters: @@ -190,7 +190,7 @@ packages: description: name: characters sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.1" checked_yaml: @@ -198,7 +198,7 @@ packages: description: name: checked_yaml sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.4" cli_util: @@ -206,7 +206,7 @@ packages: description: name: cli_util sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.4.2" clock: @@ -214,7 +214,7 @@ packages: description: name: clock sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.2" code_assets: @@ -222,7 +222,7 @@ packages: description: name: code_assets sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" collection: @@ -230,7 +230,7 @@ packages: description: name: collection sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.19.1" cookie_jar: @@ -238,7 +238,7 @@ packages: description: name: cookie_jar sha256: "963da02c1ef64cb5ac20de948c9e5940aa351f1e34a12b1d327c83d85b7e8fff" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.0.9" cross_file: @@ -246,7 +246,7 @@ packages: description: name: cross_file sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.5+2" crypto: @@ -254,7 +254,7 @@ packages: description: name: crypto sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.7" csslib: @@ -262,7 +262,7 @@ packages: description: name: csslib sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" cupertino_icons: @@ -270,7 +270,7 @@ packages: description: name: cupertino_icons sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.9" dbus: @@ -278,7 +278,7 @@ packages: description: name: dbus sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.12" device_info_plus: @@ -286,7 +286,7 @@ packages: description: name: device_info_plus sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "10.1.2" device_info_plus_platform_interface: @@ -294,7 +294,7 @@ packages: description: name: device_info_plus_platform_interface sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.0.3" dio: @@ -302,7 +302,7 @@ packages: description: name: dio sha256: aff32c08f92787a557dd5c0145ac91536481831a01b4648136373cddb0e64f8c - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.9.2" dio_web_adapter: @@ -310,7 +310,7 @@ packages: description: name: dio_web_adapter sha256: "2f9e64323a7c3c7ef69567d5c800424a11f8337b8b228bad02524c9fb3c1f340" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" event_bus: @@ -318,7 +318,7 @@ packages: description: name: event_bus sha256: "1a55e97923769c286d295240048fc180e7b0768902c3c2e869fe059aafa15304" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" extended_image: @@ -326,7 +326,7 @@ packages: description: name: extended_image sha256: f6cbb1d798f51262ed1a3d93b4f1f2aa0d76128df39af18ecb77fa740f88b2e0 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "10.0.1" extended_image_library: @@ -334,7 +334,7 @@ packages: description: name: extended_image_library sha256: "1f9a24d3a00c2633891c6a7b5cab2807999eb2d5b597e5133b63f49d113811fe" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.0.1" extended_nested_scroll_view: @@ -342,7 +342,7 @@ packages: description: name: extended_nested_scroll_view sha256: "835580d40c2c62b448bd14adecd316acba469ba61f1510ef559d17668a85e777" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.2.1" extended_text: @@ -350,7 +350,7 @@ packages: description: name: extended_text sha256: d8f4a6e2676505b54dc0d5f5e8de9020667b402e9c1b3a8b030a83e568c99654 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "15.0.2" extended_text_field: @@ -358,7 +358,7 @@ packages: description: name: extended_text_field sha256: "3996195c117c6beb734026a7bc0ba80d7e4e84e4edd4728caa544d8209ab4d7d" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "16.0.2" extended_text_library: @@ -366,7 +366,7 @@ packages: description: name: extended_text_library sha256: "13d99f8a10ead472d5e2cf4770d3d047203fe5054b152e9eb5dc692a71befbba" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "12.0.1" fading_edge_scrollview: @@ -374,7 +374,7 @@ packages: description: name: fading_edge_scrollview sha256: "1f84fe3ea8e251d00d5735e27502a6a250e4aa3d3b330d3fdcb475af741464ef" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.1.1" fake_async: @@ -382,7 +382,7 @@ packages: description: name: fake_async sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.3" ffi: @@ -390,7 +390,7 @@ packages: description: name: ffi sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" file: @@ -398,7 +398,7 @@ packages: description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.0.1" file_selector_linux: @@ -406,7 +406,7 @@ packages: description: name: file_selector_linux sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.9.4" file_selector_macos: @@ -414,7 +414,7 @@ packages: description: name: file_selector_macos sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.9.5" file_selector_platform_interface: @@ -422,7 +422,7 @@ packages: description: name: file_selector_platform_interface sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.7.0" file_selector_windows: @@ -430,7 +430,7 @@ packages: description: name: file_selector_windows sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.9.3+5" firebase_auth: @@ -438,7 +438,7 @@ packages: description: name: firebase_auth sha256: "0fed2133bee1369ee1118c1fef27b2ce0d84c54b7819a2b17dada5cfec3b03ff" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.7.0" firebase_auth_platform_interface: @@ -446,7 +446,7 @@ packages: description: name: firebase_auth_platform_interface sha256: "871c9df4ec9a754d1a793f7eb42fa3b94249d464cfb19152ba93e14a5966b386" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.7.3" firebase_auth_web: @@ -454,7 +454,7 @@ packages: description: name: firebase_auth_web sha256: d9ada769c43261fd1b18decf113186e915c921a811bd5014f5ea08f4cf4bc57e - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.15.3" firebase_core: @@ -462,7 +462,7 @@ packages: description: name: firebase_core sha256: "7be63a3f841fc9663342f7f3a011a42aef6a61066943c90b1c434d79d5c995c5" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.15.2" firebase_core_platform_interface: @@ -470,7 +470,7 @@ packages: description: name: firebase_core_platform_interface sha256: "0ecda14c1bfc9ed8cac303dd0f8d04a320811b479362a9a4efb14fd331a473ce" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.0.3" firebase_core_web: @@ -478,7 +478,7 @@ packages: description: name: firebase_core_web sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.24.1" firebase_crashlytics: @@ -486,7 +486,7 @@ packages: description: name: firebase_crashlytics sha256: "662ae6443da91bca1fb0be8aeeac026fa2975e8b7ddfca36e4d90ebafa35dde1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.3.10" firebase_crashlytics_platform_interface: @@ -494,7 +494,7 @@ packages: description: name: firebase_crashlytics_platform_interface sha256: "7222a8a40077c79f6b8b3f3439241c9f2b34e9ddfde8381ffc512f7b2e61f7eb" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.8.10" fixnum: @@ -502,7 +502,7 @@ packages: description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" fluro: @@ -510,7 +510,7 @@ packages: description: name: fluro sha256: "24d07d0b285b213ec2045b83e85d076185fa5c23651e44dae0ac6755784b97d0" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.5" flutter: @@ -523,7 +523,7 @@ packages: description: name: flutter_cache_manager sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.4.1" flutter_debouncer: @@ -531,7 +531,7 @@ packages: description: name: flutter_debouncer sha256: "89f98f874e6abbb212f3027a7a27d5ce42c5b6544c8f5967d91140c0ae06ae22" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" flutter_image_compress: @@ -539,7 +539,7 @@ packages: description: name: flutter_image_compress sha256: "51d23be39efc2185e72e290042a0da41aed70b14ef97db362a6b5368d0523b27" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.0" flutter_image_compress_common: @@ -547,7 +547,7 @@ packages: description: name: flutter_image_compress_common sha256: c5c5d50c15e97dd7dc72ff96bd7077b9f791932f2076c5c5b6c43f2c88607bfb - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.6" flutter_image_compress_macos: @@ -555,7 +555,7 @@ packages: description: name: flutter_image_compress_macos sha256: "20019719b71b743aba0ef874ed29c50747461e5e8438980dfa5c2031898f7337" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" flutter_image_compress_ohos: @@ -563,7 +563,7 @@ packages: description: name: flutter_image_compress_ohos sha256: e76b92bbc830ee08f5b05962fc78a532011fcd2041f620b5400a593e96da3f51 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.0.3" flutter_image_compress_platform_interface: @@ -571,7 +571,7 @@ packages: description: name: flutter_image_compress_platform_interface sha256: "579cb3947fd4309103afe6442a01ca01e1e6f93dc53bb4cbd090e8ce34a41889" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.5" flutter_image_compress_web: @@ -579,7 +579,7 @@ packages: description: name: flutter_image_compress_web sha256: b9b141ac7c686a2ce7bb9a98176321e1182c9074650e47bb140741a44b6f5a96 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.5" flutter_launcher_icons: @@ -587,7 +587,7 @@ packages: description: name: flutter_launcher_icons sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.14.4" flutter_lints: @@ -595,7 +595,7 @@ packages: description: name: flutter_lints sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.0.0" flutter_localizations: @@ -608,7 +608,7 @@ packages: description: name: flutter_plugin_android_lifecycle sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.34" flutter_screenutil: @@ -616,7 +616,7 @@ packages: description: name: flutter_screenutil sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.9.3" flutter_smart_dialog: @@ -624,7 +624,7 @@ packages: description: name: flutter_smart_dialog sha256: "72762b20c25f8e12d490332004c9cca327f39dfc1fcba66124c6b7c108b68850" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.9.8+10" flutter_staggered_grid_view: @@ -632,7 +632,7 @@ packages: description: name: flutter_staggered_grid_view sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.0" flutter_svga: @@ -640,7 +640,7 @@ packages: description: name: flutter_svga sha256: c914ba2aee5e2d53775b64c7ff6530b4cdc3c27fd9348debb0d86fd68b869c39 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.0.13" flutter_test: @@ -658,7 +658,7 @@ packages: description: name: fluttertoast sha256: "90778fe0497fe3a09166e8cf2e0867310ff434b794526589e77ec03cf08ba8e8" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "8.2.14" glob: @@ -666,7 +666,7 @@ packages: description: name: glob sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.3" google_identity_services_web: @@ -674,7 +674,7 @@ packages: description: name: google_identity_services_web sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.3+1" google_sign_in: @@ -682,7 +682,7 @@ packages: description: name: google_sign_in sha256: d0a2c3bcb06e607bb11e4daca48bd4b6120f0bbc4015ccebbe757d24ea60ed2a - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.3.0" google_sign_in_android: @@ -690,7 +690,7 @@ packages: description: name: google_sign_in_android sha256: d5e23c56a4b84b6427552f1cf3f98f716db3b1d1a647f16b96dbb5b93afa2805 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.2.1" google_sign_in_ios: @@ -698,7 +698,7 @@ packages: description: name: google_sign_in_ios sha256: "102005f498ce18442e7158f6791033bbc15ad2dcc0afa4cf4752e2722a516c96" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.9.0" google_sign_in_platform_interface: @@ -706,7 +706,7 @@ packages: description: name: google_sign_in_platform_interface sha256: "5f6f79cf139c197261adb6ac024577518ae48fdff8e53205c5373b5f6430a8aa" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.0" google_sign_in_web: @@ -714,7 +714,7 @@ packages: description: name: google_sign_in_web sha256: "460547beb4962b7623ac0fb8122d6b8268c951cf0b646dd150d60498430e4ded" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.4+4" gtk: @@ -722,23 +722,23 @@ packages: description: name: gtk sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" hooks: dependency: transitive description: name: hooks - sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 - url: "https://pub.dev" + sha256: "025f060e86d2d4c3c47b56e33caf7f93bf9283340f26d23424ebcfccf34f621e" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.2" + version: "1.0.3" html: dependency: transitive description: name: html sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.15.6" http: @@ -746,7 +746,7 @@ packages: description: name: http sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.6.0" http_client_helper: @@ -754,7 +754,7 @@ packages: description: name: http_client_helper sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" http_parser: @@ -762,7 +762,7 @@ packages: description: name: http_parser sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.1.2" image: @@ -770,7 +770,7 @@ packages: description: name: image sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.8.0" image_cropper: @@ -785,7 +785,7 @@ packages: description: name: image_cropper_for_web sha256: "865d798b5c9d826f1185b32e5d0018c4183ddb77b7b82a931e1a06aa3b74974e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" image_cropper_platform_interface: @@ -793,7 +793,7 @@ packages: description: name: image_cropper_platform_interface sha256: ee160d686422272aa306125f3b6fb1c1894d9b87a5e20ed33fa008e7285da11e - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.0.0" image_picker: @@ -801,7 +801,7 @@ packages: description: name: image_picker sha256: "784210112be18ea55f69d7076e2c656a4e24949fa9e76429fe53af0c0f4fa320" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.1" image_picker_android: @@ -809,7 +809,7 @@ packages: description: name: image_picker_android sha256: "66810af8e99b2657ee98e5c6f02064f69bb63f7a70e343937f70946c5f8c6622" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.8.13+16" image_picker_for_web: @@ -817,7 +817,7 @@ packages: description: name: image_picker_for_web sha256: "66257a3191ab360d23a55c8241c91a6e329d31e94efa7be9cf7a212e65850214" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.1" image_picker_ios: @@ -825,7 +825,7 @@ packages: description: name: image_picker_ios sha256: b9c4a438a9ff4f60808c9cf0039b93a42bb6c2211ef6ebb647394b2b3fa84588 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.8.13+6" image_picker_linux: @@ -833,7 +833,7 @@ packages: description: name: image_picker_linux sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.2" image_picker_macos: @@ -841,7 +841,7 @@ packages: description: name: image_picker_macos sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.2+1" image_picker_platform_interface: @@ -849,7 +849,7 @@ packages: description: name: image_picker_platform_interface sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.11.1" image_picker_windows: @@ -857,7 +857,7 @@ packages: description: name: image_picker_windows sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.2" in_app_purchase: @@ -865,7 +865,7 @@ packages: description: name: in_app_purchase sha256: "5cddd7f463f3bddb1d37a72b95066e840d5822d66291331d7f8f05ce32c24b6c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.3" in_app_purchase_android: @@ -873,7 +873,7 @@ packages: description: name: in_app_purchase_android sha256: "634bee4734b17fe55f370f0ac07a22431a9666e0f3a870c6d20350856e8bbf71" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.4.0+10" in_app_purchase_platform_interface: @@ -881,7 +881,7 @@ packages: description: name: in_app_purchase_platform_interface sha256: "1d353d38251da5b9fea6635c0ebfc6bb17a2d28d0e86ea5e083bf64244f1fb4c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" in_app_purchase_storekit: @@ -889,7 +889,7 @@ packages: description: name: in_app_purchase_storekit sha256: "1d512809edd9f12ff88fce4596a13a18134e2499013f4d6a8894b04699363c93" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.4.8+1" intl: @@ -897,23 +897,23 @@ packages: description: name: intl sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.20.2" iris_method_channel: dependency: transitive description: name: iris_method_channel - sha256: bfb5cfc6c6eae42da8cd1b35977a72d8b8881848a5dfc3d672e4760a907d11a0 - url: "https://pub.dev" + sha256: "114bbe541369add8dd0727858e7df5764f375e3fb88374ad487301733fddb57f" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.4" + version: "2.2.5" isolate_easy_pool: dependency: "direct main" description: name: isolate_easy_pool sha256: f0204cfdecbb84d61c46240a603bb21c3b2ac925475faf3f4afe18526fcb8f64 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.0.8" jni: @@ -921,7 +921,7 @@ packages: description: name: jni sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" jni_flutter: @@ -929,7 +929,7 @@ packages: description: name: jni_flutter sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" js: @@ -937,7 +937,7 @@ packages: description: name: js sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.6.7" json_annotation: @@ -945,7 +945,7 @@ packages: description: name: json_annotation sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.11.0" leak_tracker: @@ -953,7 +953,7 @@ packages: description: name: leak_tracker sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "11.0.2" leak_tracker_flutter_testing: @@ -961,7 +961,7 @@ packages: description: name: leak_tracker_flutter_testing sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.10" leak_tracker_testing: @@ -969,7 +969,7 @@ packages: description: name: leak_tracker_testing sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.2" lints: @@ -977,7 +977,7 @@ packages: description: name: lints sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.1.1" logging: @@ -985,7 +985,7 @@ packages: description: name: logging sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" marquee: @@ -993,7 +993,7 @@ packages: description: name: marquee sha256: a87e7e80c5d21434f90ad92add9f820cf68be374b226404fe881d2bba7be0862 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.0" matcher: @@ -1001,7 +1001,7 @@ packages: description: name: matcher sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.19" material_color_utilities: @@ -1009,7 +1009,7 @@ packages: description: name: material_color_utilities sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.13.0" meta: @@ -1017,7 +1017,7 @@ packages: description: name: meta sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.17.0" mime: @@ -1025,7 +1025,7 @@ packages: description: name: mime sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" mime_type: @@ -1033,7 +1033,7 @@ packages: description: name: mime_type sha256: d652b613e84dac1af28030a9fba82c0999be05b98163f9e18a0849c6e63838bb - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" native_toolchain_c: @@ -1041,7 +1041,7 @@ packages: description: name: native_toolchain_c sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.17.6" nested: @@ -1049,7 +1049,7 @@ packages: description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" objective_c: @@ -1057,7 +1057,7 @@ packages: description: name: objective_c sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "9.3.0" octo_image: @@ -1065,7 +1065,7 @@ packages: description: name: octo_image sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" package_config: @@ -1073,7 +1073,7 @@ packages: description: name: package_config sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" package_info_plus: @@ -1081,7 +1081,7 @@ packages: description: name: package_info_plus sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "8.3.1" package_info_plus_platform_interface: @@ -1089,7 +1089,7 @@ packages: description: name: package_info_plus_platform_interface sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.1" path: @@ -1097,7 +1097,7 @@ packages: description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.9.1" path_drawing: @@ -1105,7 +1105,7 @@ packages: description: name: path_drawing sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" path_parsing: @@ -1113,7 +1113,7 @@ packages: description: name: path_parsing sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" path_provider: @@ -1121,7 +1121,7 @@ packages: description: name: path_provider sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.5" path_provider_android: @@ -1129,7 +1129,7 @@ packages: description: name: path_provider_android sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.1" path_provider_foundation: @@ -1137,7 +1137,7 @@ packages: description: name: path_provider_foundation sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.6.0" path_provider_linux: @@ -1145,7 +1145,7 @@ packages: description: name: path_provider_linux sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.1" path_provider_platform_interface: @@ -1153,7 +1153,7 @@ packages: description: name: path_provider_platform_interface sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" path_provider_windows: @@ -1161,7 +1161,7 @@ packages: description: name: path_provider_windows sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.0" permission_handler: @@ -1169,7 +1169,7 @@ packages: description: name: permission_handler sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "12.0.1" permission_handler_android: @@ -1177,7 +1177,7 @@ packages: description: name: permission_handler_android sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "13.0.1" permission_handler_apple: @@ -1185,7 +1185,7 @@ packages: description: name: permission_handler_apple sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "9.4.7" permission_handler_html: @@ -1193,7 +1193,7 @@ packages: description: name: permission_handler_html sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.3+5" permission_handler_platform_interface: @@ -1201,7 +1201,7 @@ packages: description: name: permission_handler_platform_interface sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.3.0" permission_handler_windows: @@ -1209,7 +1209,7 @@ packages: description: name: permission_handler_windows sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.1" petitparser: @@ -1217,7 +1217,7 @@ packages: description: name: petitparser sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.0.2" photo_view: @@ -1225,7 +1225,7 @@ packages: description: name: photo_view sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.15.0" platform: @@ -1233,7 +1233,7 @@ packages: description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.6" plugin_platform_interface: @@ -1241,7 +1241,7 @@ packages: description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.8" posix: @@ -1249,7 +1249,7 @@ packages: description: name: posix sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.5.0" pretty_dio_logger: @@ -1257,7 +1257,7 @@ packages: description: name: pretty_dio_logger sha256: "36f2101299786d567869493e2f5731de61ce130faa14679473b26905a92b6407" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" protobuf: @@ -1265,7 +1265,7 @@ packages: description: name: protobuf sha256: "75ec242d22e950bdcc79ee38dd520ce4ee0bc491d7fadc4ea47694604d22bf06" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.0.0" provider: @@ -1273,7 +1273,7 @@ packages: description: name: provider sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.1.5+1" pub_semver: @@ -1281,7 +1281,7 @@ packages: description: name: pub_semver sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" pull_to_refresh: @@ -1289,7 +1289,7 @@ packages: description: name: pull_to_refresh sha256: bbadd5a931837b57739cf08736bea63167e284e71fb23b218c8c9a6e042aad12 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" readmore: @@ -1297,15 +1297,23 @@ packages: description: name: readmore sha256: e8fca2bd397b86342483b409e2ec26f06560a5963aceaa39b27f30722b506187 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" + record_use: + dependency: transitive + description: + name: record_use + sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.0" rxdart: dependency: transitive description: name: rxdart sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.28.0" shared_preferences: @@ -1313,7 +1321,7 @@ packages: description: name: shared_preferences sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.5" shared_preferences_android: @@ -1321,7 +1329,7 @@ packages: description: name: shared_preferences_android sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.23" shared_preferences_foundation: @@ -1329,7 +1337,7 @@ packages: description: name: shared_preferences_foundation sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.6" shared_preferences_linux: @@ -1337,7 +1345,7 @@ packages: description: name: shared_preferences_linux sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.1" shared_preferences_platform_interface: @@ -1345,7 +1353,7 @@ packages: description: name: shared_preferences_platform_interface sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.2" shared_preferences_web: @@ -1353,7 +1361,7 @@ packages: description: name: shared_preferences_web sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.3" shared_preferences_windows: @@ -1361,7 +1369,7 @@ packages: description: name: shared_preferences_windows sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.1" sign_in_with_apple: @@ -1369,7 +1377,7 @@ packages: description: name: sign_in_with_apple sha256: "8bd875c8e8748272749eb6d25b896f768e7e9d60988446d543fe85a37a2392b8" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.0.1" sign_in_with_apple_platform_interface: @@ -1377,7 +1385,7 @@ packages: description: name: sign_in_with_apple_platform_interface sha256: "981bca52cf3bb9c3ad7ef44aace2d543e5c468bb713fd8dda4275ff76dfa6659" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" sign_in_with_apple_web: @@ -1385,7 +1393,7 @@ packages: description: name: sign_in_with_apple_web sha256: f316400827f52cafcf50d00e1a2e8a0abc534ca1264e856a81c5f06bd5b10fed - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0" sky_engine: @@ -1398,7 +1406,7 @@ packages: description: name: source_span sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.2" sqflite: @@ -1406,7 +1414,7 @@ packages: description: name: sqflite sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.2" sqflite_android: @@ -1414,7 +1422,7 @@ packages: description: name: sqflite_android sha256: "881e28efdcc9950fd8e9bb42713dcf1103e62a2e7168f23c9338d82db13dec40" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.2+3" sqflite_common: @@ -1422,7 +1430,7 @@ packages: description: name: sqflite_common sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.6" sqflite_darwin: @@ -1430,7 +1438,7 @@ packages: description: name: sqflite_darwin sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.2" sqflite_platform_interface: @@ -1438,7 +1446,7 @@ packages: description: name: sqflite_platform_interface sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.0" stack_trace: @@ -1446,7 +1454,7 @@ packages: description: name: stack_trace sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.12.1" stream_channel: @@ -1454,7 +1462,7 @@ packages: description: name: stream_channel sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.4" string_scanner: @@ -1462,17 +1470,17 @@ packages: description: name: string_scanner sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.1" synchronized: dependency: transitive description: name: synchronized - sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 - url: "https://pub.dev" + sha256: "63896c27e81b28f8cb4e69ead0d3e8f03f1d1e5fc531a3e579cabed6a2c7c9e5" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.4.0" + version: "3.4.0+1" tancent_vap: dependency: "direct main" description: @@ -1485,7 +1493,7 @@ packages: description: name: tencent_cloud_chat_sdk sha256: fb930c86017fa4a546f3d0c15bc5a54197f07f003934737e80cf2f9a70cab1ba - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "8.3.6498+3" term_glyph: @@ -1493,7 +1501,7 @@ packages: description: name: term_glyph sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.2" test_api: @@ -1501,7 +1509,7 @@ packages: description: name: test_api sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.10" typed_data: @@ -1509,7 +1517,7 @@ packages: description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" universal_io: @@ -1517,7 +1525,7 @@ packages: description: name: universal_io sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.1" url_launcher: @@ -1525,7 +1533,7 @@ packages: description: name: url_launcher sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.3.2" url_launcher_android: @@ -1533,7 +1541,7 @@ packages: description: name: url_launcher_android sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.3.29" url_launcher_ios: @@ -1541,7 +1549,7 @@ packages: description: name: url_launcher_ios sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.4.1" url_launcher_linux: @@ -1549,7 +1557,7 @@ packages: description: name: url_launcher_linux sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.2" url_launcher_macos: @@ -1557,7 +1565,7 @@ packages: description: name: url_launcher_macos sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.5" url_launcher_platform_interface: @@ -1565,7 +1573,7 @@ packages: description: name: url_launcher_platform_interface sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.2" url_launcher_web: @@ -1573,7 +1581,7 @@ packages: description: name: url_launcher_web sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.2" url_launcher_windows: @@ -1581,7 +1589,7 @@ packages: description: name: url_launcher_windows sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.5" uuid: @@ -1589,7 +1597,7 @@ packages: description: name: uuid sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.5.3" vector_math: @@ -1597,7 +1605,7 @@ packages: description: name: vector_math sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" video_player: @@ -1605,7 +1613,7 @@ packages: description: name: video_player sha256: "48a7bdaa38a3d50ec10c78627abdbfad863fdf6f0d6e08c7c3c040cfd80ae36f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.11.1" video_player_android: @@ -1613,7 +1621,7 @@ packages: description: name: video_player_android sha256: "877a6c7ba772456077d7bfd71314629b3fe2b73733ce503fc77c3314d43a0ca0" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.9.5" video_player_avfoundation: @@ -1621,7 +1629,7 @@ packages: description: name: video_player_avfoundation sha256: af0e5b8a7a4876fb37e7cc8cb2a011e82bb3ecfa45844ef672e32cb14a1f259e - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.9.4" video_player_platform_interface: @@ -1629,7 +1637,7 @@ packages: description: name: video_player_platform_interface sha256: "57c5d73173f76d801129d0531c2774052c5a7c11ccb962f1830630decd9f24ec" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.6.0" video_player_web: @@ -1637,7 +1645,7 @@ packages: description: name: video_player_web sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.0" video_thumbnail: @@ -1645,7 +1653,7 @@ packages: description: name: video_thumbnail sha256: "181a0c205b353918954a881f53a3441476b9e301641688a581e0c13f00dc588b" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.5.6" visibility_detector: @@ -1653,39 +1661,39 @@ packages: description: name: visibility_detector sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.4.0+2" vm_service: dependency: transitive description: name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.dev" + sha256: "046d3928e16fa4dc46e8350415661755ab759d9fc97fc21b5ab295f71e4f0499" + url: "https://pub.flutter-io.cn" source: hosted - version: "15.0.2" + version: "15.1.0" wakelock_plus: dependency: "direct main" description: name: wakelock_plus sha256: "61713aa82b7f85c21c9f4cd0a148abd75f38a74ec645fcb1e446f882c82fd09b" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.3" wakelock_plus_platform_interface: dependency: transitive description: name: wakelock_plus_platform_interface - sha256: "24b84143787220a403491c2e5de0877fbbb87baf3f0b18a2a988973863db4b03" - url: "https://pub.dev" + sha256: "14b2e5b9e35c2631e656913c47adecdd71633ae92896a27a64c8f1fcfabc21cc" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.4.0" + version: "1.5.0" web: dependency: transitive description: name: web sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" webview_flutter: @@ -1693,7 +1701,7 @@ packages: description: name: webview_flutter sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.4.2" webview_flutter_android: @@ -1701,7 +1709,7 @@ packages: description: name: webview_flutter_android sha256: "47a8da40d02befda5b151a26dba71f47df471cddd91dfdb7802d0a87c5442558" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.16.9" webview_flutter_platform_interface: @@ -1709,23 +1717,23 @@ packages: description: name: webview_flutter_platform_interface sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.15.1" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: d7219cfabc6f5fc2032e0fa980ec36d71f308a35a823395af1abc34d9a2ede83 - url: "https://pub.dev" + sha256: e15d8828e014291324a4d0cf6e272090167f4fa5673ffcf8fe446f4a4cd35861 + url: "https://pub.flutter-io.cn" source: hosted - version: "3.24.2" + version: "3.24.3" win32: dependency: transitive description: name: win32 sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.15.0" win32_registry: @@ -1733,7 +1741,7 @@ packages: description: name: win32_registry sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.5" xdg_directories: @@ -1741,7 +1749,7 @@ packages: description: name: xdg_directories sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" xml: @@ -1749,7 +1757,7 @@ packages: description: name: xml sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.6.1" yaml: @@ -1757,9 +1765,9 @@ packages: description: name: yaml sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.3" sdks: - dart: ">=3.10.7 <4.0.0" - flutter: ">=3.38.4" + dart: ">=3.11.0 <4.0.0" + flutter: ">=3.41.0" diff --git a/pubspec.yaml b/pubspec.yaml index 7869bc2..a5ecc80 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.1.1+3 +version: 1.2.0+4 environment: diff --git a/sc_images/general/room_id.svga b/sc_images/general/room_id.svga new file mode 100644 index 0000000..4e6234d Binary files /dev/null and b/sc_images/general/room_id.svga differ diff --git a/sc_images/general/room_id_custom.svga b/sc_images/general/room_id_custom.svga new file mode 100644 index 0000000..0e783cb Binary files /dev/null and b/sc_images/general/room_id_custom.svga differ diff --git a/sc_images/general/user_id.svga b/sc_images/general/user_id.svga new file mode 100644 index 0000000..739c689 Binary files /dev/null and b/sc_images/general/user_id.svga differ diff --git a/sc_images/general/user_id_4.svga b/sc_images/general/user_id_4.svga new file mode 100644 index 0000000..76c66a7 Binary files /dev/null and b/sc_images/general/user_id_4.svga differ diff --git a/需求进度.md b/需求进度.md index 8eb6e26..e61fb45 100644 --- a/需求进度.md +++ b/需求进度.md @@ -3,6 +3,10 @@ ## 当前总目标 - 控制当前 Flutter Android 发包体积,持续定位冗余组件、超大资源和不合理构建配置,并把每一步处理结果落盘记录。 +## 本轮靓号动效替换(已完成) +- 已按 2026-04-21 最新靓号动效需求,把桌面“靓号动效”里的 `room_id / room_id_custom / user_id / user_id_4` 四套 `SVGA` 素材导入 Flutter 工程,并新增统一的靓号 ID 展示组件;当前会按 `ownSpecialId != null && expiredTime > now` 判定是否仍为有效靓号,过期靓号会自动回退到原始账号展示。 +- 已完成 4 个指定场景的替换:`room_id` 现用于房间详情里的房间号,`room_id_custom` 现用于房间详情里的房主 ID,`user_id` 现用于房间在线列表和房间个人卡片,`user_id_4` 现用于个人主页和 `Me` 页;对应文案在命中靓号时会展示靓号号码,未命中时保持原始 `ID:` 文本样式。 + ## 本轮房间动效优化(进行中) - 已按 2026-04-21 当前房间卡顿优化方案先落第一步“统一调度层”:新增房间特效调度器,在全屏 `VAP/SVGA` 高成本特效播放或排队期间,暂缓低优先级的房间进场动画、全局飘屏和座位飞屏入队,待高成本特效清空后按小间隔续播,先减少多条动画链路同一时刻抢主线程的情况。 - 本步只处理“调度时机”,没有改动现有动画内部逻辑:礼物/飞屏/飘屏的现有倍率触发规则、现有上限截断、`customAnimationCount` 现有循环方式和当前视觉表现均保持原样,避免第一步就引入联动回归。 @@ -68,6 +72,8 @@ - 已继续绕开幸运礼物紫色横幅里可疑的小图 `ExtendedImage` 渲染链:当前礼物图标已改为在 `initState` 里先构建 `buildCachedImageProvider`,再通过基础 `Image(image: provider)` 直接绘制,并额外输出一次 `gift icon frame ready` 日志,用于确认这张图是否真的完成首帧解码显示;这样可以把问题进一步收敛为“图片 provider/解码”还是“组件布局/视觉观感”。 - 已按 2026-04-21 最新联调请求,把紫色幸运礼物横幅 `from` 后的图标临时替换为金币图标:这一步只用于快速验证该图标位本身的布局和可见性是否正常,不再受当前礼物图资源链路影响;如果金币图标能稳定显示,就说明问题仍集中在礼物图渲染链,而不是这个位置被遮挡或根本没画出来。 - 已按 2026-04-21 最新回归把 [floating_luck_gift_screen_widget] 的样式撤回到最初实现,不再继续在幸运礼物飘屏横幅上做偏题调试;同时已定位到真正缺图的是消息栏里的 `gameLuckyGift_5` 高亮消息,这条消息此前只写入了 `awardAmount/user/msg`,没有把 `gift` 一并塞进去,导致 `room_msg_item.dart` 读取 `widget.msg.gift?.giftPhoto` 时天然为空。当前已在 `RTM` 构造高亮 lucky 消息时补回 `giftPhoto`,让消息栏里的紫色 lucky message 能和其它消息一样拿到礼物图。 +- 已按 2026-04-21 最新特效需求继续调整幸运礼物 `burst`:在 `luck_gift_reward_burst.svga` 下方那块淡色圆角矩形区域,补上了与 `SVGA` 同步进场/消失的中奖倍数文案;当前会和中央金额文本共用同一显隐时机,并在 `multiple > 0` 时展示为 `xN`,避免出现 `x0` 这类无效信息。 +- 已继续按 2026-04-21 最新特效稿给幸运礼物 `burst` 补上中奖发送者头像:当前头像会出现在你标的黑块位置附近,并和 `SVGA` 使用同一套开始/结束显隐时机同步出现与消失;头像显示只读取当前中奖事件的 `userAvatar`,不改现有 `burst` 触发条件和播放时长。 - 已优化语言房麦位/头像的二次确认交互:普通用户点击可上麦的空麦位时,当前会直接执行上麦,不再先弹出只有 `Take the mic / Cancel` 的确认层;普通用户点击房间头像或已占麦位上的用户头像时,也会直接打开个人卡片,不再额外弹出仅含 `Open user profile card / Cancel` 的底部确认。房主/管理员仍保留原有带禁麦、锁麦、邀请上麦等管理动作的底部菜单,避免误删管理能力。 - 已继续收窄语言房个人卡片前的“确认意义”弹层:当前用户在麦位上点击自己的头像时,也会直接打开自己的个人卡片,不再先弹出仅包含 `Leave the mic / Open user profile card / Cancel` 的底部菜单;同时个人卡片内的“离开麦位”入口已替换为新的 `leave` 视觉素材,和最新房间交互稿保持一致。 - 已继续微调语言房个人卡片与送礼 UI:个人卡片底部动作文案现已支持两行居中展示,避免 `Leave the mic` 这类英文按钮被硬截断;房间底部礼物入口也已切换为新的本地 `SVGA` 资源 `room_bottom_gift_button.svga`,保持房间底栏视觉和最新动效稿一致。 @@ -239,6 +245,12 @@ - `lib/ui_kit/widgets/room/room_game_bottom_sheet.dart` - `lib/ui_kit/widgets/svga/sc_svga_asset_widget.dart` - `lib/modules/room/detail/room_detail_page.dart` +- `lib/modules/room/online/room_online_page.dart` +- `lib/modules/user/me_page2.dart` +- `lib/modules/user/profile/person_detail_page.dart` +- `lib/shared/business_logic/models/res/login_res.dart` +- `lib/ui_kit/widgets/id/sc_special_id_badge.dart` +- `lib/ui_kit/widgets/room/room_user_info_card.dart` - `lib/modules/home/popular/party/sc_home_party_page.dart` - `lib/modules/home/popular/mine/sc_home_mine_skeleton.dart` - `lib/modules/home/popular/follow/sc_room_follow_page.dart` @@ -259,6 +271,10 @@ - `lib/modules/user/my_items/theme/bags_theme_page.dart` - `lib/ui_kit/widgets/store/store_bag_page_helpers.dart` - `sc_images/general/sc_no_data.png` +- `sc_images/general/room_id.svga` +- `sc_images/general/room_id_custom.svga` +- `sc_images/general/user_id.svga` +- `sc_images/general/user_id_4.svga` - `sc_images/splash/sc_weekly_star_bg.png` - `sc_images/splash/sc_icon_weekly_star_rank_1.png` - `sc_images/splash/sc_icon_weekly_star_rank_2.png` @@ -419,6 +435,13 @@ - Launch image 仍是默认占位资源,提交前建议替换 - `android/key.properties` 保存了本地 upload keystore 口令,必须自行妥善备份,且不要提交到仓库 - 由于已显式移除 Agora 本地屏幕共享相关组件,如果业务后续要启用“屏幕共享/录屏推流”,需要再单独恢复相关 manifest 声明 +- `burst` 特效叠加层已停止用 `Align + translate` 猜偏移,改为按 `luck_gift_reward_burst.svga` 拆出的参考图层比例重排头像、中奖金额、倍数,重点对齐头像黑色占位圈和底部倍数圆角块 +- 根据最新真机截图,`burst` 叠加层已整体继续向右下微调,先修正“整体偏左上”的问题,不改头像和文案尺寸 +- 按最新口头要求,`burst` 叠加层又整体额外向下平移 `40` 个设计单位,继续保持头像、金额、倍数三者相对位置不变 +- `burst` 头像已按最新要求缩到原来的 `80%`,并同步补偿左上坐标,保持头像中心点仍然对准原坑位 +- `burst` 头像继续按最新口头要求单独微调:向下 `10` 个设计单位、向左 `2` 个设计单位,其余金额和倍数位置不动 +- `burst` 头像又继续单独向下补移 `8` 个设计单位,当前累计为向下 `18`、向左 `2` +- 飞向麦位动画补了统一的“中心图空闲同步”逻辑:目标坐标重试失败放弃、队列被清空、上一段飞行结束后,都会把中心静态礼物图切到队列头或直接清空,避免残留卡死在屏幕中央 ## 下一步要做什么 - 将新的 `AAB` 上传到 Play Console,并在首发流程中继续使用 Google 管理的 app signing key。