diff --git a/ios/Podfile b/ios/Podfile index a09ea13..eaf1562 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '13.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -64,7 +64,7 @@ post_install do |installer| ## 6. 禁用 Siri/助手 (NSSiriUsageDescription) 'PERMISSION_ASSISTANT=0', - ## 7. 禁用 媒体库 (NSAppleMusicUsageDescription) + ## 7. 启用 媒体库 (NSAppleMusicUsageDescription) 'PERMISSION_MEDIA_LIBRARY=1', ## 8. 禁用 蓝牙 (如果你没用到蓝牙,建议也关掉) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6ebc174..6197448 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -11,11 +11,47 @@ PODS: - GoogleUtilities/Environment (~> 8.0) - GoogleUtilities/UserDefaults (~> 8.0) - PromisesObjC (~> 2.4) + - audio_session (0.0.1): + - Flutter - audioplayers_darwin (0.0.1): - Flutter - FlutterMacOS - device_info_plus (0.0.1): - Flutter + - DKImagePickerController/Core (4.3.9): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.9) + - DKImagePickerController/PhotoGallery (4.3.9): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.9) + - DKPhotoGallery (0.0.19): + - DKPhotoGallery/Core (= 0.0.19) + - DKPhotoGallery/Model (= 0.0.19) + - DKPhotoGallery/Preview (= 0.0.19) + - DKPhotoGallery/Resource (= 0.0.19) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.19): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.19): + - SDWebImage + - SwiftyGif + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter - Firebase/Auth (11.15.0): - Firebase/CoreOnly - FirebaseAuth (~> 11.15.0) @@ -141,6 +177,9 @@ PODS: - in_app_purchase_storekit (0.0.1): - Flutter - FlutterMacOS + - just_audio (0.0.1): + - Flutter + - FlutterMacOS - libpag (4.5.52) - libwebp (1.5.0): - libwebp/demux (= 1.5.0) @@ -170,6 +209,9 @@ PODS: - pag (0.0.1): - Flutter - libpag + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS - permission_handler_apple (9.3.0): - Flutter - PromisesObjC (2.4.0) @@ -191,6 +233,7 @@ PODS: - Flutter - FlutterMacOS - SwiftyBeaver (1.9.5) + - SwiftyGif (5.4.5) - tancent_vap (0.0.1): - Flutter - tencent_cloud_chat_sdk (8.0.0): @@ -223,8 +266,10 @@ PODS: DEPENDENCIES: - app_links (from `.symlinks/plugins/app_links/ios`) + - audio_session (from `.symlinks/plugins/audio_session/ios`) - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/darwin`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) + - file_picker (from `.symlinks/plugins/file_picker/ios`) - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`) @@ -235,9 +280,11 @@ DEPENDENCIES: - image_cropper (from `.symlinks/plugins/image_cropper/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`) + - just_audio (from `.symlinks/plugins/just_audio/darwin`) - on_audio_query_ios (from `.symlinks/plugins/on_audio_query_ios/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - pag (from `.symlinks/plugins/pag/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`) @@ -255,6 +302,8 @@ SPEC REPOS: trunk: - AppAuth - AppCheckCore + - DKImagePickerController + - DKPhotoGallery - Firebase - FirebaseAppCheckInterop - FirebaseAuth @@ -282,6 +331,7 @@ SPEC REPOS: - SDWebImage - SDWebImageWebPCoder - SwiftyBeaver + - SwiftyGif - TOCropViewController - TXCustomBeautyProcesserPlugin - TXIMSDK_Plus_iOS_XCFramework @@ -290,10 +340,14 @@ SPEC REPOS: EXTERNAL SOURCES: app_links: :path: ".symlinks/plugins/app_links/ios" + audio_session: + :path: ".symlinks/plugins/audio_session/ios" audioplayers_darwin: :path: ".symlinks/plugins/audioplayers_darwin/darwin" device_info_plus: :path: ".symlinks/plugins/device_info_plus/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/ios" firebase_auth: :path: ".symlinks/plugins/firebase_auth/ios" firebase_core: @@ -314,12 +368,16 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/image_picker_ios/ios" in_app_purchase_storekit: :path: ".symlinks/plugins/in_app_purchase_storekit/darwin" + just_audio: + :path: ".symlinks/plugins/just_audio/darwin" on_audio_query_ios: :path: ".symlinks/plugins/on_audio_query_ios/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" pag: :path: ".symlinks/plugins/pag/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" shared_preferences_foundation: @@ -349,8 +407,12 @@ SPEC CHECKSUMS: app_links: 3dbc685f76b1693c66a6d9dd1e9ab6f73d97dc0a AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73 AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f + audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0 audioplayers_darwin: 835ced6edd4c9fc8ebb0a7cc9e294a91d99917d5 device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896 + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 + file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e firebase_auth: 50af8366c87bb88c80ebeae62eb60189c7246b9b firebase_core: 995454a784ff288be5689b796deb9e9fa3601818 @@ -378,6 +440,7 @@ SPEC CHECKSUMS: image_cropper: 655b3ba703c9e15e3111e79151624d6154288774 image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326 in_app_purchase_storekit: 22cca7d08eebca9babdf4d07d0baccb73325d3c8 + just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed libpag: 98742fad4b3ac2a2ee31e383d2483495fb9a5fb4 libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d @@ -385,6 +448,7 @@ SPEC CHECKSUMS: on_audio_query_ios: 28a780e2d0d85d92d500ba6e12c6c8167022b2fa package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 pag: f01aa9017ab0e04a83ba4a20d6070a50f0ac9da8 + path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 @@ -395,6 +459,7 @@ SPEC CHECKSUMS: sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418 sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 SwiftyBeaver: 84069991dd5dca07d7069100985badaca7f0ce82 + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 tancent_vap: fa8ad93814a9f950514a7074c662d2c937084c68 tencent_cloud_chat_sdk: 55e5fffe20f6b7937a26a674ccccb639563a9790 tencent_rtc_sdk: f77558b6b436a149d378557c2a837f73c09061bc @@ -408,6 +473,6 @@ SPEC CHECKSUMS: wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d -PODFILE CHECKSUM: a6f49a93e5f85201a2efdadcd7cf184b0e310894 +PODFILE CHECKSUM: b724feb0f01aec7228c34cc4763485e911aa9322 COCOAPODS: 1.16.2 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index 879503c..399e070 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index e03f697..e4d7e0a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index a4a7cbc..07818e1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index c26b0c5..1bcc67e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 5d3adbe..0df806a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index 3d50c36..04aca42 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 8e5585d..0ba09e6 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index a4a7cbc..07818e1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 690398a..015fdc9 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index 40a9548..f966f58 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png index 7cff2c2..f0cf623 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png index 58af325..09a2fbf 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png index e8b01af..6bd8fa2 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png index 2f36d02..36ca7b4 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index 40a9548..f966f58 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 33e7037..2e5a170 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png index bab4549..2a1dbf0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png index 1a5b3c6..13ab27e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index b386803..a723642 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index efbff97..bb72963 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 32f26cb..423a252 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/lib/modules/auth/edit/sc_edit_profile_page.dart b/lib/modules/auth/edit/sc_edit_profile_page.dart index 5a013f3..d6fd5ad 100644 --- a/lib/modules/auth/edit/sc_edit_profile_page.dart +++ b/lib/modules/auth/edit/sc_edit_profile_page.dart @@ -106,7 +106,7 @@ class _SCEditProfilePageState extends State { if (success) { userProvider?.updateUserAvatar(url); } - }); + }, allowGif: true); }, ), SizedBox(height: 15.w), @@ -559,24 +559,6 @@ class _SCEditProfilePageState extends State { return primary ?? fallback; } - bool _isBrokenLocalMediaUrl(String? url) { - return (url ?? "").contains("/external/oss/local/"); - } - - String? _preferUsableAvatar(String? primary, String? fallback) { - if (primary != null && - primary.isNotEmpty && - !_isBrokenLocalMediaUrl(primary)) { - return primary; - } - if (fallback != null && - fallback.isNotEmpty && - !_isBrokenLocalMediaUrl(fallback)) { - return fallback; - } - return _preferNonEmpty(primary, fallback); - } - num? _preferNonZero(num? primary, num? fallback) { if (primary != null && primary != 0) { return primary; @@ -661,10 +643,6 @@ class _SCEditProfilePageState extends State { if (submittedProfile != null) { final mergedProfile = (user.userProfile ?? SocialChatUserProfile()) .copyWith( - userAvatar: _preferUsableAvatar( - user.userProfile?.userAvatar, - submittedProfile.userAvatar, - ), userNickname: _preferNonEmpty( user.userProfile?.userNickname, submittedProfile.userNickname, diff --git a/lib/modules/room/music/room_music_page.dart b/lib/modules/room/music/room_music_page.dart index 812821b..7ac57eb 100644 --- a/lib/modules/room/music/room_music_page.dart +++ b/lib/modules/room/music/room_music_page.dart @@ -558,31 +558,37 @@ class _SwipeDeleteTileState extends State<_SwipeDeleteTile> { duration: const Duration(milliseconds: 160), curve: Curves.easeOutCubic, transform: Matrix4.translationValues(_dragOffset, 0, 0), - child: Row( - children: [ - SizedBox(width: constraints.maxWidth, child: widget.child), - SizedBox( - width: actionWidth, - height: 56.w, - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: widget.onDelete, - child: Container( - margin: EdgeInsetsDirectional.only(start: 4.w), - decoration: BoxDecoration( - color: const Color(0xFFE64A4A), - borderRadius: BorderRadius.circular(8.w), - ), - alignment: Alignment.center, - child: Image.asset( - "sc_images/room/sc_music_material_delete.png", - width: 22.w, - height: 22.w, + child: SizedBox( + width: constraints.maxWidth + actionWidth, + child: Row( + children: [ + SizedBox( + width: constraints.maxWidth, + child: widget.child, + ), + SizedBox( + width: actionWidth, + height: 56.w, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: widget.onDelete, + child: Container( + margin: EdgeInsetsDirectional.only(start: 4.w), + decoration: BoxDecoration( + color: const Color(0xFFE64A4A), + borderRadius: BorderRadius.circular(8.w), + ), + alignment: Alignment.center, + child: Image.asset( + "sc_images/room/sc_music_material_delete.png", + width: 22.w, + height: 22.w, + ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/modules/room/voice_room_page.dart b/lib/modules/room/voice_room_page.dart index 8458c9a..20dfa9d 100644 --- a/lib/modules/room/voice_room_page.dart +++ b/lib/modules/room/voice_room_page.dart @@ -330,9 +330,11 @@ class _VoiceRoomPageState extends State OverlayManager().removeRoom(roomId: currentRoomId); SCRoomEffectScheduler().clearDeferredTasks(reason: 'voice_room_suspend'); SCGiftVapSvgaManager().stopPlayback(); - unawaited( - Provider.of(context, listen: false).stopForRoomExit(), - ); + if (!SCFloatIchart().isShow()) { + unawaited( + Provider.of(context, listen: false).stopForRoomExit(), + ); + } } Widget _buildRoomStartupLayer() { diff --git a/lib/modules/user/edit/edit_user_info_page2.dart b/lib/modules/user/edit/edit_user_info_page2.dart index de8adae..5f21950 100644 --- a/lib/modules/user/edit/edit_user_info_page2.dart +++ b/lib/modules/user/edit/edit_user_info_page2.dart @@ -75,21 +75,6 @@ class _EditUserInfoPage2State extends State return primary ?? fallback; } - bool _isBrokenLocalMediaUrl(String? url) { - return (url ?? "").contains("/external/oss/local/"); - } - - String? _preferUsableAvatar(String? primary, String? fallback) { - if ((primary ?? "").trim().isNotEmpty && !_isBrokenLocalMediaUrl(primary)) { - return primary; - } - if ((fallback ?? "").trim().isNotEmpty && - !_isBrokenLocalMediaUrl(fallback)) { - return fallback; - } - return _preferNonEmpty(primary, fallback); - } - DateTime? _birthdayFromProfile([SocialChatUserProfile? profile]) { final targetProfile = profile ?? AccountStorage().getCurrentUser()?.userProfile; @@ -158,7 +143,7 @@ class _EditUserInfoPage2State extends State } void _syncLocalProfileState(SocialChatUserProfile profile) { - userCover = _preferUsableAvatar(profile.userAvatar, userCover); + userCover = profile.userAvatar; nickName = profile.userNickname ?? nickName; autograph = profile.autograph ?? autograph; hobby = profile.hobby ?? hobby; @@ -239,11 +224,9 @@ class _EditUserInfoPage2State extends State String url, ) { if (success) { - userCover = url; - setState(() {}); - submitAvatarOnly(); + submit(userAvatarValue: url); } - }); + }, allowGif: true); }, ), SizedBox(height: 3.w), @@ -404,13 +387,6 @@ class _EditUserInfoPage2State extends State return eighteenYearsAgo; } - void submitAvatarOnly() { - if ((userCover ?? "").trim().isEmpty) { - return; - } - submit(userAvatarValue: userCover); - } - void submit({ Object? userAvatarValue = _noChange, Object? userNicknameValue = _noChange, @@ -473,12 +449,6 @@ class _EditUserInfoPage2State extends State : autographValue as String?, ); final mergedProfile = updatedProfile.copyWith( - userAvatar: _preferUsableAvatar( - updatedProfile.userAvatar, - identical(userAvatarValue, _noChange) - ? userCover - : userAvatarValue as String?, - ), userNickname: _preferNonEmpty( updatedProfile.userNickname, identical(userNicknameValue, _noChange) diff --git a/lib/modules/user/profile/person_detail_page.dart b/lib/modules/user/profile/person_detail_page.dart index 1dbc1a8..02f556b 100644 --- a/lib/modules/user/profile/person_detail_page.dart +++ b/lib/modules/user/profile/person_detail_page.dart @@ -887,6 +887,8 @@ class _PersonDetailPageState extends State with RouteAware { width: ScreenUtil().screenWidth, height: 300.w, fit: BoxFit.cover, + gifFit: BoxFit.cover, + gifAlignment: Alignment.topCenter, ), ); }).toList(), @@ -2024,6 +2026,7 @@ class _PersonDetailPageState extends State with RouteAware { }, aspectRatio: ScreenUtil().screenWidth / 300.w, backOriginalFile: false, + allowGif: true, ); } @@ -2040,19 +2043,8 @@ class _PersonDetailPageState extends State with RouteAware { final updatedProfile = await SCAccountRepository().updateUserInfo( backgroundPhotos: [imageUrl], ); - final returnedPhotos = updatedProfile.backgroundPhotos ?? []; - final hasUploadedPhoto = returnedPhotos.any( - (photo) => (photo.url ?? "").trim() == imageUrl, - ); - final backgroundPhotos = - hasUploadedPhoto - ? returnedPhotos - : [PersonPhoto(url: imageUrl, status: 1)]; - final mergedProfile = updatedProfile.copyWith( - backgroundPhotos: backgroundPhotos, - ); - ref.userProfile = mergedProfile; - ref.syncCurrentUserProfile(mergedProfile); + ref.userProfile = updatedProfile; + ref.syncCurrentUserProfile(updatedProfile); if (!mounted) { return; } diff --git a/lib/services/audio/rtc_manager.dart b/lib/services/audio/rtc_manager.dart index 296fc90..a8450a6 100644 --- a/lib/services/audio/rtc_manager.dart +++ b/lib/services/audio/rtc_manager.dart @@ -66,6 +66,7 @@ import '../../ui_kit/widgets/room/rocket/room_rocket_pag_effect_overlay.dart'; import '../../ui_kit/widgets/room/rocket/room_rocket_api_mapper.dart'; typedef OnSoundVoiceChange = Function(num index, int volum); +typedef RoomMusicSessionExitListener = Future Function(); typedef RtcProvider = RealTimeCommunicationManager; enum RoomStartupStatus { idle, loading, ready, failed } @@ -468,6 +469,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { RoomRtcEngineAdapter? _roomRtcEngineAdapter; RoomMusicMixingStateListener? _roomMusicMixingStateListener; RoomMusicMicRouteChangedListener? _roomMusicMicRouteChangedListener; + RoomMusicSessionExitListener? _roomMusicSessionExitListener; BuildContext? context; RtmProvider? rtmProvider; @@ -2849,7 +2851,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { } } if (currenRoom != null) { - _switchAwayFromCurrentRoomForNewEntry(); + await _switchAwayFromCurrentRoomForNewEntry(); } if (!context.mounted) { return; @@ -4854,8 +4856,9 @@ class RealTimeCommunicationManager extends ChangeNotifier { exitRtmProvider?.cleanRoomData(); } catch (e) {} + await _notifyRoomMusicSessionExit(); _clearData(clearPersistedRoomMarker: false); - if (!isLogout && navigationContext != null) { + if (!isLogout && navigationContext != null && navigationContext.mounted) { VoiceRoomRoute.popVoiceRoomToPrevious(navigationContext); } @@ -4875,7 +4878,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { } } - void _switchAwayFromCurrentRoomForNewEntry() { + Future _switchAwayFromCurrentRoomForNewEntry() async { _stopRoomStatePolling(); final groupId = currenRoom?.roomProfile?.roomProfile?.roomAccount ?? ""; final roomId = currenRoom?.roomProfile?.roomProfile?.id ?? ""; @@ -4889,6 +4892,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { exitRtmProvider?.cleanRoomData(); } catch (e) {} + await _notifyRoomMusicSessionExit(); _clearData(clearPersistedRoomMarker: false); final roomRtcLeaveTask = _leaveRoomRtcForExit(); _pendingRoomSwitchRtcLeaveTask = roomRtcLeaveTask; @@ -6028,6 +6032,20 @@ class RealTimeCommunicationManager extends ChangeNotifier { _roomMusicMicRouteChangedListener = listener; } + void setRoomMusicSessionExitListener(RoomMusicSessionExitListener? listener) { + _roomMusicSessionExitListener = listener; + } + + Future _notifyRoomMusicSessionExit() async { + final listener = _roomMusicSessionExitListener; + if (listener == null) { + return; + } + try { + await listener(); + } catch (_) {} + } + void updateRoomMusicPublishingState({ required String? userId, required bool publishing, diff --git a/lib/services/music/local_music_scanner.dart b/lib/services/music/local_music_scanner.dart index 6dfd398..886590b 100644 --- a/lib/services/music/local_music_scanner.dart +++ b/lib/services/music/local_music_scanner.dart @@ -1,7 +1,11 @@ +import 'dart:convert'; import 'dart:io'; +import 'package:file_picker/file_picker.dart'; +import 'package:just_audio/just_audio.dart'; import 'package:on_audio_query/on_audio_query.dart'; import 'package:path/path.dart' as p; +import 'package:path_provider/path_provider.dart'; import 'package:yumi/shared/data_sources/models/sc_music_folder_mode.dart'; import 'package:yumi/shared/data_sources/models/sc_music_mode.dart'; import 'package:yumi/shared/tools/sc_permission_utils.dart'; @@ -15,6 +19,10 @@ class LocalMusicScanner { Future> scanMp3Folders({ List addedSongs = const [], }) async { + if (Platform.isIOS) { + return _pickIosMp3Files(addedSongs: addedSongs); + } + final hasPermission = await SCPermissionUtils.checkAudioPermission(); if (!hasPermission) { return const []; @@ -96,6 +104,98 @@ class LocalMusicScanner { return List.unmodifiable(folders); } + Future> _pickIosMp3Files({ + required List addedSongs, + }) async { + final FilePickerResult? result; + try { + result = await FilePicker.pickFiles( + type: FileType.custom, + allowedExtensions: const ['mp3'], + allowMultiple: true, + withData: false, + withReadStream: false, + ); + } catch (_) { + return const []; + } + if (result == null || result.files.isEmpty) { + return const []; + } + + final addedIds = addedSongs.map((item) => item.id).toSet(); + final addedPaths = addedSongs.map((item) => item.localPath).toSet(); + final storageDir = await _iosRoomMusicDirectory(); + final player = AudioPlayer(); + final songs = []; + final seen = {}; + + try { + for (final file in result.files) { + final sourcePath = (file.path ?? '').trim(); + if (sourcePath.isEmpty || + !_isMp3FileName(file.name) || + !_fileExists(sourcePath)) { + continue; + } + final sourceId = _firstNonEmpty([ + file.identifier, + '${file.name}:${file.size}', + sourcePath, + ]); + if (sourceId.isEmpty || !seen.add(sourceId)) { + continue; + } + final storedPath = await _copyIosPickedFile( + sourcePath: sourcePath, + fileName: file.name, + sourceId: sourceId, + storageDir: storageDir, + ); + final durationMs = await _readLocalMp3DurationMs(player, storedPath); + final storedFile = File(storedPath); + final safeFileName = p.basename(storedPath); + songs.add( + SCMusicMode( + id: sourceId, + title: p.basenameWithoutExtension(file.name).trim(), + artist: '', + durationMs: durationMs, + localPath: storedPath, + contentUri: '', + folderPath: storageDir.path, + fileName: safeFileName, + size: storedFile.existsSync() ? storedFile.lengthSync() : file.size, + addedAt: DateTime.now().millisecondsSinceEpoch, + ), + ); + } + } finally { + await player.dispose(); + } + + if (songs.isEmpty) { + return const []; + } + songs.sort( + (a, b) => a.title.toLowerCase().compareTo(b.title.toLowerCase()), + ); + final addedCount = + songs.where((song) { + return addedIds.contains(song.id) || + addedPaths.contains(song.localPath); + }).length; + return [ + SCMusicFolderMode( + id: 'ios_file_picker', + name: 'Selected Music', + path: 'Files', + songs: List.unmodifiable(songs), + addedCount: addedCount, + ), + ]; + } + bool _isMp3(SongModel song) { final extension = _songString( song, @@ -108,6 +208,72 @@ class LocalMusicScanner { _songString(song, "_data").toLowerCase().endsWith(".mp3"); } + bool _isMp3FileName(String fileName) { + return fileName.toLowerCase().endsWith('.mp3'); + } + + Future _iosRoomMusicDirectory() async { + final supportDir = await getApplicationSupportDirectory(); + final directory = Directory(p.join(supportDir.path, 'room_music')); + if (!directory.existsSync()) { + await directory.create(recursive: true); + } + return directory; + } + + Future _copyIosPickedFile({ + required String sourcePath, + required String fileName, + required String sourceId, + required Directory storageDir, + }) async { + if (p.isWithin(storageDir.path, sourcePath)) { + return sourcePath; + } + final sourceFile = File(sourcePath); + final targetFile = File( + p.join(storageDir.path, _iosStoredFileName(fileName, sourceId)), + ); + if (targetFile.existsSync() && + targetFile.lengthSync() == sourceFile.lengthSync()) { + return targetFile.path; + } + await sourceFile.copy(targetFile.path); + return targetFile.path; + } + + String _iosStoredFileName(String fileName, String sourceId) { + final baseName = p.basenameWithoutExtension(fileName).trim(); + final safeBaseName = + baseName + .replaceAll(RegExp(r'[^A-Za-z0-9._ -]+'), '_') + .replaceAll(RegExp(r'\s+'), ' ') + .trim(); + final token = base64Url.encode(utf8.encode(sourceId)).replaceAll('=', ''); + final suffix = token.length > 12 ? token.substring(0, 12) : token; + return '${safeBaseName.isEmpty ? 'music' : safeBaseName}_$suffix.mp3'; + } + + Future _readLocalMp3DurationMs(AudioPlayer player, String path) async { + try { + final duration = await player.setFilePath(path); + await player.stop(); + return duration?.inMilliseconds ?? 0; + } catch (_) { + return 0; + } + } + + String _firstNonEmpty(List values) { + for (final value in values) { + final text = value?.trim() ?? ''; + if (text.isNotEmpty) { + return text; + } + } + return ''; + } + bool _fileExists(String path) { try { return File(path).existsSync(); diff --git a/lib/services/music/room_music_manager.dart b/lib/services/music/room_music_manager.dart index 4289c12..fbc2f6d 100644 --- a/lib/services/music/room_music_manager.dart +++ b/lib/services/music/room_music_manager.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'dart:math'; +import 'package:audio_session/audio_session.dart'; import 'package:flutter/foundation.dart'; import 'package:yumi/services/audio/rtc_manager.dart'; import 'package:yumi/services/audio/room_rtc_types.dart'; @@ -86,9 +87,11 @@ class RoomMusicManager extends ChangeNotifier { } _rtcProvider?.setRoomMusicMixingStateListener(null); _rtcProvider?.setRoomMusicMicRouteChangedListener(null); + _rtcProvider?.setRoomMusicSessionExitListener(null); _rtcProvider = provider; provider.setRoomMusicMixingStateListener(_handleMixingStateChanged); provider.setRoomMusicMicRouteChangedListener(_handleMicRouteChanged); + provider.setRoomMusicSessionExitListener(stopForRoomExit); _syncPublishingState(force: true); } @@ -364,6 +367,7 @@ class RoomMusicManager extends ChangeNotifier { } _isStarting = true; try { + await _configureIosAudioSessionIfNeeded(); await _waitForStartInterval(); _lastLoopback = !rtcProvider.isOnMai(); await rtcProvider.startRoomMusicAudioMixing( @@ -404,6 +408,31 @@ class RoomMusicManager extends ChangeNotifier { } } + Future _configureIosAudioSessionIfNeeded() async { + if (!Platform.isIOS) { + return; + } + try { + final session = await AudioSession.instance; + await session.configure( + AudioSessionConfiguration( + avAudioSessionCategory: AVAudioSessionCategory.playAndRecord, + avAudioSessionCategoryOptions: + AVAudioSessionCategoryOptions.mixWithOthers | + AVAudioSessionCategoryOptions.defaultToSpeaker | + AVAudioSessionCategoryOptions.allowBluetooth | + AVAudioSessionCategoryOptions.allowBluetoothA2dp, + avAudioSessionMode: AVAudioSessionMode.voiceChat, + avAudioSessionRouteSharingPolicy: + AVAudioSessionRouteSharingPolicy.defaultPolicy, + avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none, + ), + ); + } catch (_) { + // TRTC can still manage the iOS audio session if this best-effort setup fails. + } + } + void _startPositionTimer() { _positionTimer?.cancel(); _positionTimer = Timer.periodic(const Duration(milliseconds: 800), (_) { @@ -554,6 +583,7 @@ class RoomMusicManager extends ChangeNotifier { _publishingStateHeartbeatTimer?.cancel(); _rtcProvider?.setRoomMusicMixingStateListener(null); _rtcProvider?.setRoomMusicMicRouteChangedListener(null); + _rtcProvider?.setRoomMusicSessionExitListener(null); super.dispose(); } } diff --git a/lib/shared/tools/sc_pick_utils.dart b/lib/shared/tools/sc_pick_utils.dart index f997c85..5f31212 100644 --- a/lib/shared/tools/sc_pick_utils.dart +++ b/lib/shared/tools/sc_pick_utils.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:yumi/ui_kit/components/sc_tts.dart'; @@ -11,6 +10,8 @@ import 'package:yumi/shared/tools/sc_loading_manager.dart'; class SCPickUtils { static final ImagePicker _pkr = ImagePicker(); + static const int _defaultMaxImageBytes = 4000000; + static const int _gifOriginalMaxImageBytes = 10 * 1024 * 1024; static void pickImage( BuildContext context, @@ -18,27 +19,51 @@ class SCPickUtils { double? aspectRatio, bool? backOriginalFile = true, bool? neeCrop = true, + bool allowGif = false, + bool skipCropForGif = true, }) async { try { - final XFile? pickedFile = await _pkr.pickImage( - source: ImageSource.gallery, - imageQuality: 90, - maxWidth: 1920, - maxHeight: 1080, - ); + final XFile? pickedFile = + allowGif + ? await _pkr.pickImage(source: ImageSource.gallery) + : await _pkr.pickImage( + source: ImageSource.gallery, + imageQuality: 90, + maxWidth: 1920, + maxHeight: 1080, + ); if (pickedFile == null) return; - if (!SCPathUtils.fileTypeIsPic(pickedFile.path)) { - SCTts.show("Please select sc_images in .jpg, .jpeg, .png format."); + final isGif = await _igif(pickedFile); + if (!context.mounted) { + onUpLoadCallBack(false, ""); return; } - // 检查是否为 GIF 图像 - if (await _igif(pickedFile)) { - SCTts.show("GIF sc_images are not supported"); + if (isGif) { + if (!allowGif) { + SCTts.show("GIF sc_images are not supported"); + return; + } + } else if (!SCPathUtils.fileTypeIsPic(pickedFile.path)) { + SCTts.show( + allowGif + ? "Please select sc_images in .jpg, .jpeg, .png, .gif format." + : "Please select sc_images in .jpg, .jpeg, .png format.", + ); return; } final File imageFile = File(pickedFile.path); + if (isGif && skipCropForGif) { + await _uploadOriginalImage( + context, + imageFile, + onUpLoadCallBack, + maxBytes: _gifOriginalMaxImageBytes, + oversizeMessage: "The GIF image size cannot exceed 10M", + ); + return; + } if (neeCrop ?? false) { cropImage( imageFile, @@ -48,28 +73,45 @@ class SCPickUtils { onUpLoadCallBack, ); } else { - if (imageFile.lengthSync() > 4000000) { - SCTts.show(SCAppLocalizations.of(context)!.theImageSizeCannotExceed); - onUpLoadCallBack?.call(false, ""); - return; - } - SCLoadingManager.show(context: context); - try { - String fileUrl = await SCGeneralRepositoryImp().upload(imageFile); - SCLoadingManager.hide(); - onUpLoadCallBack?.call(true, fileUrl); - } catch (e) { - SCTts.show("upload fail $e"); - onUpLoadCallBack?.call(false, ""); - SCLoadingManager.hide(); - } + await _uploadOriginalImage( + context, + imageFile, + onUpLoadCallBack, + maxBytes: _defaultMaxImageBytes, + oversizeMessage: + SCAppLocalizations.of(context)!.theImageSizeCannotExceed, + ); } } catch (e) { - onUpLoadCallBack?.call(false, ""); + onUpLoadCallBack(false, ""); SCTts.show("Failed to select image"); } } + static Future _uploadOriginalImage( + BuildContext context, + File imageFile, + OnUpLoadCallBack onUpLoadCallBack, { + required int maxBytes, + required String oversizeMessage, + }) async { + if (imageFile.lengthSync() > maxBytes) { + SCTts.show(oversizeMessage); + onUpLoadCallBack(false, ""); + return; + } + SCLoadingManager.show(context: context); + try { + String fileUrl = await SCGeneralRepositoryImp().upload(imageFile); + SCLoadingManager.hide(); + onUpLoadCallBack(true, fileUrl); + } catch (e) { + SCTts.show("upload fail $e"); + onUpLoadCallBack(false, ""); + SCLoadingManager.hide(); + } + } + /// 检查图像是否为 GIF 格式 static Future _igif(XFile file) async { try { @@ -165,7 +207,12 @@ class SCPickUtils { if (pickedFile == null) return; // 相机拍摄的照片不会是 GIF,但为了安全也可以检查 - if (await _igif(pickedFile)) { + final isGif = await _igif(pickedFile); + if (!context.mounted) { + onUpLoadCallBack(false, ""); + return; + } + if (isGif) { SCTts.show("Unsupported image format"); return; } @@ -209,9 +256,6 @@ class SCPickUtils { OnUpLoadCallBack onUpLoadCallBack, { bool needUpload = true, }) async { - if (originalImage == null) { - return; - } await Navigator.push( context, MaterialPageRoute( diff --git a/lib/ui_kit/components/sc_compontent.dart b/lib/ui_kit/components/sc_compontent.dart index 27bf2bd..83c7f45 100644 --- a/lib/ui_kit/components/sc_compontent.dart +++ b/lib/ui_kit/components/sc_compontent.dart @@ -49,6 +49,7 @@ Widget head({ String? headdressCover, BoxShape shape = BoxShape.circle, BoxFit fit = BoxFit.cover, + BoxFit gifFit = BoxFit.contain, BorderRadius? borderRadius, bool showDefault = true, bool isRoom = false, @@ -85,6 +86,7 @@ Widget head({ width: avatarWidth, height: avatarHeight, fit: fit, + gifFit: gifFit, noDefaultImg: !showDefault, defaultImg: "sc_images/general/sc_icon_avar_defalt.png", ), @@ -221,19 +223,28 @@ Widget netImage({ double? height, BorderRadius? borderRadius, BoxFit? fit, + BoxFit? gifFit, + AlignmentGeometry? gifAlignment, BoxShape? shape, Border? border, Widget? loadingWidget, Widget? errorWidget, }) { + final isGif = SCPathUtils.getFileExtension(url) == ".gif"; + final resolvedHeight = height ?? width; + final resolvedFit = + isGif ? (gifFit ?? fit ?? BoxFit.cover) : (fit ?? BoxFit.cover); + final resolvedAlignment = + isGif ? (gifAlignment ?? Alignment.center) : Alignment.center; return ExtendedImage.network( url, width: width, - height: height ?? width, - cacheWidth: _resolveImageCacheDimension(width), - cacheHeight: _resolveImageCacheDimension(height ?? width), + height: resolvedHeight, + cacheWidth: isGif ? null : _resolveImageCacheDimension(width), + cacheHeight: isGif ? null : _resolveImageCacheDimension(resolvedHeight), headers: buildNetworkImageHeaders(url), - fit: fit ?? BoxFit.cover, + fit: resolvedFit, + alignment: resolvedAlignment, cache: true, shape: shape ?? BoxShape.rectangle, borderRadius: borderRadius, @@ -246,7 +257,10 @@ Widget netImage({ if (state.extendedImageLoadState == LoadState.completed) { return ExtendedRawImage( image: state.extendedImageInfo?.image, - fit: fit ?? BoxFit.cover, + width: width, + height: resolvedHeight, + fit: resolvedFit, + alignment: resolvedAlignment, ); } else if (state.extendedImageLoadState == LoadState.failed) { if (errorWidget != null) { diff --git a/lib/ui_kit/widgets/room/exit_min_room_page.dart b/lib/ui_kit/widgets/room/exit_min_room_page.dart index 2cdab5b..60244af 100644 --- a/lib/ui_kit/widgets/room/exit_min_room_page.dart +++ b/lib/ui_kit/widgets/room/exit_min_room_page.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:yumi/app_localizations.dart'; @@ -10,7 +8,6 @@ import 'package:yumi/app/routes/sc_fluro_navigator.dart'; import 'package:yumi/modules/room/voice_room_route.dart'; import 'package:yumi/services/audio/rtm_manager.dart'; import 'package:yumi/services/gift/gift_animation_manager.dart'; -import 'package:yumi/services/music/room_music_manager.dart'; import 'package:yumi/services/audio/rtc_manager.dart'; import 'package:yumi/shared/data_sources/sources/local/floating_screen_manager.dart'; import 'package:yumi/shared/tools/sc_gift_vap_svga_manager.dart'; @@ -88,7 +85,6 @@ class _ExitMinRoomPageState extends State { reason: 'room_minimize', ); SCGiftVapSvgaManager().stopPlayback(); - unawaited(context.read().stopForRoomExit()); giftAnimationManager.cleanupAnimationResources(); SCFloatIchart().show(); VoiceRoomRoute.popVoiceRoomToPrevious(context); diff --git a/pubspec.lock b/pubspec.lock index 1659351..b390fe9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -65,6 +65,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.13.1" + audio_session: + dependency: "direct main" + description: + name: audio_session + sha256: "7217b229db57cc4dc577a8abb56b7429a5a212b978517a5be578704bfe5e568b" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.3" audioplayers: dependency: "direct main" description: @@ -209,14 +217,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.2" - code_assets: - dependency: transitive - description: - name: code_assets - sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.0.0" collection: dependency: transitive description: @@ -393,6 +393,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "7.0.1" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: f13a03000d942e476bc1ff0a736d2e9de711d2f89a95cd4c1d88f861c3348387 + url: "https://pub.flutter-io.cn" + source: hosted + version: "11.0.2" file_selector_linux: dependency: transitive description: @@ -660,14 +668,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "8.2.14" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.1.3" google_identity_services_web: dependency: transitive description: @@ -724,14 +724,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" - hooks: - dependency: transitive - description: - name: hooks - sha256: "025f060e86d2d4c3c47b56e33caf7f93bf9283340f26d23424ebcfccf34f621e" - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.0.3" html: dependency: transitive description: @@ -947,6 +939,30 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "4.12.0" + just_audio: + dependency: "direct main" + description: + name: just_audio + sha256: "9694e4734f515f2a052493d1d7e0d6de219ee0427c7c29492e246ff32a219908" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.10.5" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + sha256: "2532c8d6702528824445921c5ff10548b518b13f808c2e34c2fd54793b999a6a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.6.0" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.16" leak_tracker: dependency: transitive description: @@ -979,14 +995,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "5.1.1" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.3.0" marquee: dependency: "direct main" description: @@ -1035,14 +1043,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" - native_toolchain_c: - dependency: transitive - description: - name: native_toolchain_c - sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.17.6" nested: dependency: transitive description: @@ -1051,14 +1051,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" - objective_c: - dependency: transitive - description: - name: objective_c - sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" - url: "https://pub.flutter-io.cn" - source: hosted - version: "9.3.0" octo_image: dependency: transitive description: @@ -1177,13 +1169,13 @@ packages: source: hosted version: "2.3.1" path_provider_foundation: - dependency: transitive + dependency: "direct overridden" description: name: path_provider_foundation - sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" url: "https://pub.flutter-io.cn" source: hosted - version: "2.6.0" + version: "2.4.2" path_provider_linux: dependency: transitive description: @@ -1320,14 +1312,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.1.5+1" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.2.0" pull_to_refresh: dependency: "direct main" description: @@ -1344,14 +1328,6 @@ packages: 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: @@ -1846,4 +1822,4 @@ packages: version: "3.1.3" sdks: dart: ">=3.11.0 <4.0.0" - flutter: ">=3.38.4" + flutter: ">=3.38.0" diff --git a/pubspec.yaml b/pubspec.yaml index 4cc806a..a45f372 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -136,15 +136,23 @@ dependencies: flutter_svg: ^2.3.0 pag: path: ./local_packages/pag-1.0.7-patched + just_audio: ^0.10.5 + audio_session: ^0.2.3 + file_picker: ^11.0.2 dev_dependencies: - flutter_launcher_icons: ^0.14.4 - flutter_test: - sdk: flutter - flutter_lints: ^5.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec + flutter_launcher_icons: ^0.14.4 + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + +dependency_overrides: + # path_provider_foundation 2.6.0 pulls in objective_c native assets that are + # currently packaged as simulator frameworks and rejected by App Store upload. + path_provider_foundation: 2.4.2 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter packages. flutter: