Browse Source

feat: 基础库合并 (#43)

* feat: 基础库合并

1.捞日志功能增强
2.rtc实现与声网解耦
3.文件资源缓存管理
4.WeAnimView下沉和ExoPlayer下沉

* fix: 修复一些商品预览和动效播放问题

* feat: 改成依赖trtcpro

* fix: 个人资料页音乐播放问题&融云日志上传

* fix: 火箭发射台动效问题

* fix: 座驾预览循环问题

* fix: WeEffectView播放mp4铺满全屏问题

* feat: 正式版本bom

* fix: review问题

---------

Co-authored-by: wutiaorong <wutiaorong@gmail.com>
Talon 5 months ago
parent
commit
9774b5232c
100 changed files with 969 additions and 2640 deletions
  1. 2 1
      .gitignore
  2. 4 0
      app/build.gradle
  3. 49 47
      app/dependencies/releaseRuntimeClasspath.txt
  4. 15 15
      app/src/main/java/com/adealink/weparty/App.kt
  5. 0 20
      app/src/main/java/com/adealink/weparty/aab/AABConfig.kt
  6. 12 27
      app/src/main/java/com/adealink/weparty/apm/APMInit.kt
  7. 19 3
      app/src/main/java/com/adealink/weparty/base/AppBaseImpl.kt
  8. 2 2
      app/src/main/java/com/adealink/weparty/cocosgame/BaseCocosWebGameFragment.kt
  9. 2 2
      app/src/main/java/com/adealink/weparty/cocosgame/data/CocosGameData.kt
  10. 3 3
      app/src/main/java/com/adealink/weparty/cocosgame/data/CocosWindowViewData.kt
  11. 2 2
      app/src/main/java/com/adealink/weparty/cocosgame/data/GameData.kt
  12. 2 2
      app/src/main/java/com/adealink/weparty/cocosgame/method/OnGetAppEnv.kt
  13. 17 10
      app/src/main/java/com/adealink/weparty/cocosgame/method/OnNetworkRequest.kt
  14. 2 2
      app/src/main/java/com/adealink/weparty/cocosgame/viewmodel/BaseCocosWebGameViewModel.kt
  15. 2 2
      app/src/main/java/com/adealink/weparty/cocosgame/web/CocosGameWebView.kt
  16. 2 2
      app/src/main/java/com/adealink/weparty/config/Data.kt
  17. 7 8
      app/src/main/java/com/adealink/weparty/crash/CrashInit.kt
  18. 13 9
      app/src/main/java/com/adealink/weparty/debug/DebugActivity.kt
  19. 3 3
      app/src/main/java/com/adealink/weparty/debug/DebugUtil.kt
  20. 2 2
      app/src/main/java/com/adealink/weparty/deviceidservice/DeviceIdServiceConfig.kt
  21. 32 0
      app/src/main/java/com/adealink/weparty/download/DownloadConfig.kt
  22. 21 43
      app/src/main/java/com/adealink/weparty/effect/AvatarFrameView.kt
  23. 3 19
      app/src/main/java/com/adealink/weparty/effect/EffectConfig.kt
  24. 2 58
      app/src/main/java/com/adealink/weparty/effect/EffectData.kt
  25. 72 78
      app/src/main/java/com/adealink/weparty/effect/EffectPreviewView.kt
  26. 18 43
      app/src/main/java/com/adealink/weparty/effect/EffectViewModel.kt
  27. 10 3
      app/src/main/java/com/adealink/weparty/effect/IPreviewView.kt
  28. 4 4
      app/src/main/java/com/adealink/weparty/effect/SvgaConfig.kt
  29. 2 17
      app/src/main/java/com/adealink/weparty/effect/TCEffectConfig.kt
  30. 0 796
      app/src/main/java/com/adealink/weparty/effect/WeAnimView.kt
  31. 0 289
      app/src/main/java/com/adealink/weparty/exoplayer/ExoPlayerHelper.kt
  32. 0 2
      app/src/main/java/com/adealink/weparty/googleservice/GoogleServiceConfig.kt
  33. 2 2
      app/src/main/java/com/adealink/weparty/im/IMConfig.kt
  34. 17 0
      app/src/main/java/com/adealink/weparty/image/ImageConfig.kt
  35. 6 9
      app/src/main/java/com/adealink/weparty/imageselect/selectpreview/SelectPreviewActivity.kt
  36. 0 27
      app/src/main/java/com/adealink/weparty/json/JsonConfig.kt
  37. 8 5
      app/src/main/java/com/adealink/weparty/log/LogConfig.kt
  38. 0 22
      app/src/main/java/com/adealink/weparty/log/data/LogData.kt
  39. 0 4
      app/src/main/java/com/adealink/weparty/log/data/Tags.kt
  40. 0 17
      app/src/main/java/com/adealink/weparty/log/datasource/remote/LogHttpService.kt
  41. 0 19
      app/src/main/java/com/adealink/weparty/log/manager/ILogManager.kt
  42. 0 311
      app/src/main/java/com/adealink/weparty/log/manager/LogManager.kt
  43. 0 32
      app/src/main/java/com/adealink/weparty/log/viewmodel/LogViewModel.kt
  44. 24 0
      app/src/main/java/com/adealink/weparty/log/viewmodel/LogViewModelFactory.kt
  45. 33 11
      app/src/main/java/com/adealink/weparty/media/MediaConfig.kt
  46. 3 3
      app/src/main/java/com/adealink/weparty/module/call/CallConfig.kt
  47. 3 3
      app/src/main/java/com/adealink/weparty/module/call/match/data/CallMatchData.kt
  48. 8 36
      app/src/main/java/com/adealink/weparty/module/entereffect/effect/CarEffectView.kt
  49. 1 1
      app/src/main/java/com/adealink/weparty/module/entereffect/effect/data/CarEffectEntity.kt
  50. 22 16
      app/src/main/java/com/adealink/weparty/module/entereffect/view/CarCustomizedUserView.kt
  51. 2 1
      app/src/main/java/com/adealink/weparty/module/entereffect/viewmodel/IEnterEffectViewModel.kt
  52. 1 1
      app/src/main/java/com/adealink/weparty/module/family/data/FamilyData.kt
  53. 2 2
      app/src/main/java/com/adealink/weparty/module/game/data/GameData.kt
  54. 25 5
      app/src/main/java/com/adealink/weparty/module/game/data/GameHubData.kt
  55. 33 8
      app/src/main/java/com/adealink/weparty/module/game/gamehub/GameHubManager.kt
  56. 2 1
      app/src/main/java/com/adealink/weparty/module/game/rocket/Data.kt
  57. 2 1
      app/src/main/java/com/adealink/weparty/module/game/rocket/view/RocketHeadlineView.kt
  58. 4 3
      app/src/main/java/com/adealink/weparty/module/game/rocket/viewmodel/IRocketViewModel.kt
  59. 5 191
      app/src/main/java/com/adealink/weparty/module/gift/data/GiftData.kt
  60. 79 0
      app/src/main/java/com/adealink/weparty/module/gift/data/GiftDynamicExt.kt
  61. 3 4
      app/src/main/java/com/adealink/weparty/module/gift/effect/SendGiftNoticeView.kt
  62. 15 19
      app/src/main/java/com/adealink/weparty/module/gift/view/EdgeFlashEffectView.kt
  63. 1 5
      app/src/main/java/com/adealink/weparty/module/message/reminder/MessageReminderDialog.kt
  64. 1 1
      app/src/main/java/com/adealink/weparty/module/operation/reward/preview/BaseRewardPreviewDialog.kt
  65. 1 1
      app/src/main/java/com/adealink/weparty/module/operation/reward/preview/CarPreviewDialog.kt
  66. 16 10
      app/src/main/java/com/adealink/weparty/module/operation/reward/preview/FramePreviewDialog.kt
  67. 1 1
      app/src/main/java/com/adealink/weparty/module/operation/reward/preview/IRewardPreviewDialog.kt
  68. 1 2
      app/src/main/java/com/adealink/weparty/module/operation/reward/preview/MedalPreviewDialog.kt
  69. 1 1
      app/src/main/java/com/adealink/weparty/module/operation/reward/preview/OtherPreviewDialog.kt
  70. 1 1
      app/src/main/java/com/adealink/weparty/module/operation/reward/preview/RewardPreviewDialogBuilder.kt
  71. 6 22
      app/src/main/java/com/adealink/weparty/module/operation/reward/preview/ThemePreviewDialog.kt
  72. 63 79
      app/src/main/java/com/adealink/weparty/module/profile/decorate/data/ExtraConfigData.kt
  73. 1 1
      app/src/main/java/com/adealink/weparty/module/profile/decorate/data/UserDecorateData.kt
  74. 7 11
      app/src/main/java/com/adealink/weparty/module/profile/view/UserVoiceView.kt
  75. 1 10
      app/src/main/java/com/adealink/weparty/module/profile/widget/VipLevelView.kt
  76. 6 16
      app/src/main/java/com/adealink/weparty/module/rank/view/MarkProfileView.kt
  77. 2 2
      app/src/main/java/com/adealink/weparty/module/room/data/RoomAttrData.kt
  78. 3 3
      app/src/main/java/com/adealink/weparty/module/room/data/RoomFlowData.kt
  79. 1 1
      app/src/main/java/com/adealink/weparty/module/store/data/StoreData.kt
  80. 2 2
      app/src/main/java/com/adealink/weparty/module/task/ExceptionHandlerEx.kt
  81. 2 1
      app/src/main/java/com/adealink/weparty/module/theme/data/ThemeData.kt
  82. 2 2
      app/src/main/java/com/adealink/weparty/module/theme/viewmodel/IThemeViewModel.kt
  83. 27 6
      app/src/main/java/com/adealink/weparty/network/NetworkConfig.kt
  84. 0 10
      app/src/main/java/com/adealink/weparty/network/NetworkConfig.kt.rej
  85. 2 2
      app/src/main/java/com/adealink/weparty/network/NetworkEnv.kt
  86. 19 0
      app/src/main/java/com/adealink/weparty/push/PushMessageManager.kt
  87. 1 0
      app/src/main/java/com/adealink/weparty/push/data/PushData.kt
  88. 2 2
      app/src/main/java/com/adealink/weparty/router/RouterConfig.kt
  89. 0 22
      app/src/main/java/com/adealink/weparty/security/SecurityConfig.kt
  90. 1 1
      app/src/main/java/com/adealink/weparty/share/CommonShareFragment.kt
  91. 0 4
      app/src/main/java/com/adealink/weparty/share/ShareConfig.kt
  92. 4 0
      app/src/main/java/com/adealink/weparty/sound/SoundPlayerConfig.kt
  93. 39 31
      app/src/main/java/com/adealink/weparty/sound/UserProfileSoundViewModel.kt
  94. 9 0
      app/src/main/java/com/adealink/weparty/sound/manager/ISoundManager.kt
  95. 18 0
      app/src/main/java/com/adealink/weparty/sound/manager/SoundManager.kt
  96. 2 2
      app/src/main/java/com/adealink/weparty/stat/data/StatData.kt
  97. 4 4
      app/src/main/java/com/adealink/weparty/stat/standard/StandardStatEvent.kt
  98. 16 0
      app/src/main/java/com/adealink/weparty/storage/CacheSubDir.kt
  99. 47 12
      app/src/main/java/com/adealink/weparty/storage/config/StorageConfig.kt
  100. 35 104
      app/src/main/java/com/adealink/weparty/storage/file/FilePath.kt

+ 2 - 1
.gitignore

@@ -20,4 +20,5 @@ schemas
 schemas/
 schemas/*
 app/release/
-app/yoki/release
+app/yoki/release
+/tool/log/config.ini

+ 4 - 0
app/build.gradle

@@ -166,6 +166,7 @@ android {
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_17
         targetCompatibility JavaVersion.VERSION_17
+        coreLibraryDesugaringEnabled true
     }
 
     compileOptions {
@@ -352,6 +353,7 @@ dependencies {
     api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
     //kotlin
     implementation libs.kotlin.stdlib
+    coreLibraryDesugaring libs.desugar.jdk.libs
 
     //androidx
     api libs.androidx.core.ktx
@@ -472,6 +474,8 @@ dependencies {
     api libs.frame.locale
     api libs.frame.push
     api libs.frame.media
+    implementation libs.frame.agorartc
+    implementation libs.frame.trtc.pro
     api libs.frame.share
     api libs.frame.dot
     api libs.frame.crash

+ 49 - 47
app/dependencies/releaseRuntimeClasspath.txt

@@ -217,57 +217,59 @@ com.squareup.okio:okio:3.6.0
 com.squareup.wire:wire-runtime:2.3.0-RC1
 com.tencent.imsdk:imsdk-plus:8.4.6667
 com.tencent.liteav.tuikit:tuicore:8.4.6667
-com.tencent.liteav:LiteAVSDK_Professional:12.3.0.17115
-com.tencent.liteav:LiteAVSDK_ScreenCapture:12.3.0.17115
-com.tencent.mediacloud:TCEffectPlayer:3.1.0.247
-com.tencent.mediacloud:TCMediaX:3.1.0.247
-com.tencent.mediacloud:TCXMagicAuth:3.1.0.247
+com.tencent.liteav:LiteAVSDK_Professional:12.6.0.18891
+com.tencent.liteav:LiteAVSDK_ScreenCapture:12.6.0.18891
+com.tencent.mediacloud:TCEffectPlayer:3.2.0.248
+com.tencent.mediacloud:TCMediaX:3.2.0.248
+com.tencent.mediacloud:TCXMagicAuth:3.2.0.248
 com.tencent.vasdolly:common:3.0.6
 com.tencent.vasdolly:helper:3.0.6
 com.tencent.vasdolly:reader:3.0.6
 com.tencent:mmkv:1.3.14
-com.wenext.android:SVGAPlayer:5.1.7-yoki-beta
-com.wenext.android:animplayer:5.1.4
-com.wenext.android:autosize:5.1.4
-com.wenext.android:drawee:5.1.5
-com.wenext.android:frame-aab:5.1.8-yoki-beta
-com.wenext.android:frame-apm:5.1.5-yoki-beta
-com.wenext.android:frame-audio:5.1.4
-com.wenext.android:frame-base:5.1.4
-com.wenext.android:frame-bom:5.1.29-yoki
-com.wenext.android:frame-coroutine:5.1.4
-com.wenext.android:frame-crash:5.1.5-yoki-beta
-com.wenext.android:frame-data:5.1.5-yoki
-com.wenext.android:frame-debug:5.1.4
-com.wenext.android:frame-deviceid:5.1.4
-com.wenext.android:frame-dot:5.1.10-yoki-beta
-com.wenext.android:frame-download:5.1.7-yoki-beta
-com.wenext.android:frame-effect:5.1.6
-com.wenext.android:frame-game:5.1.5-yoki
-com.wenext.android:frame-googleservice:5.1.4
-com.wenext.android:frame-guide:5.1.19-yoki
-com.wenext.android:frame-image:5.1.8-yoki-beta
-com.wenext.android:frame-locale:5.1.8-yoki
-com.wenext.android:frame-log:5.1.6-yoki
-com.wenext.android:frame-media:5.1.10-yoki-beta
-com.wenext.android:frame-mvvm:5.1.5-beta
-com.wenext.android:frame-network:5.1.9-yoki
-com.wenext.android:frame-oss:5.1.7-yoki-1
-com.wenext.android:frame-push:5.1.4
-com.wenext.android:frame-router-annotation:5.1.4
-com.wenext.android:frame-router-api:5.1.5
-com.wenext.android:frame-security:5.1.5
-com.wenext.android:frame-share:5.1.18-yoki
-com.wenext.android:frame-sound:5.1.4
-com.wenext.android:frame-spi:5.1.4
-com.wenext.android:frame-startup:5.1.1-yoki
-com.wenext.android:frame-statistics:5.1.7
-com.wenext.android:frame-storage:5.1.7-yoki
-com.wenext.android:frame-tceffect:5.1.8-yoki-beta
-com.wenext.android:frame-tcturing:5.1.5-yoki-beta
-com.wenext.android:frame-util:5.1.6-yoki-beta
-com.wenext.android:frame-zero:5.1.4
-com.wenext.android:retrofit:5.1.4
+com.wenext.android:SVGAPlayer:6.0.0
+com.wenext.android:animplayer:6.0.0
+com.wenext.android:autosize:6.0.0
+com.wenext.android:drawee:6.0.0
+com.wenext.android:frame-aab:6.0.3
+com.wenext.android:frame-agorartc:6.0.2
+com.wenext.android:frame-apm:6.0.1
+com.wenext.android:frame-audio:6.0.0
+com.wenext.android:frame-base:6.0.2
+com.wenext.android:frame-bom:6.0.20
+com.wenext.android:frame-coroutine:6.0.0
+com.wenext.android:frame-crash:6.0.1
+com.wenext.android:frame-data:6.0.0
+com.wenext.android:frame-debug:6.0.0
+com.wenext.android:frame-deviceid:6.0.0
+com.wenext.android:frame-dot:6.0.0
+com.wenext.android:frame-download:6.0.2
+com.wenext.android:frame-effect:6.0.12
+com.wenext.android:frame-game:6.0.0
+com.wenext.android:frame-googleservice:6.0.0
+com.wenext.android:frame-guide:6.0.1
+com.wenext.android:frame-image:6.0.6
+com.wenext.android:frame-locale:6.0.0
+com.wenext.android:frame-log:6.0.3
+com.wenext.android:frame-media:6.0.5
+com.wenext.android:frame-mvvm:6.0.0
+com.wenext.android:frame-network:6.0.12
+com.wenext.android:frame-oss:6.0.3
+com.wenext.android:frame-push:6.0.0
+com.wenext.android:frame-router-annotation:6.0.0
+com.wenext.android:frame-router-api:6.0.0
+com.wenext.android:frame-security:6.0.1
+com.wenext.android:frame-share:6.0.1
+com.wenext.android:frame-sound:6.0.4
+com.wenext.android:frame-spi:6.0.0
+com.wenext.android:frame-startup:6.0.1
+com.wenext.android:frame-statistics:6.0.1
+com.wenext.android:frame-storage:6.0.7
+com.wenext.android:frame-tceffect:6.0.4
+com.wenext.android:frame-tcturing:6.0.1
+com.wenext.android:frame-trtc-pro:6.0.0
+com.wenext.android:frame-util:6.0.3
+com.wenext.android:frame-zero:6.0.0
+com.wenext.android:retrofit:6.0.0
 id.zelory:compressor:3.0.1
 io.agora.rtc:agora-special-voice:3.7.3.5.XYHZ
 io.github.flyjingfish:androidaop-annotation:2.7.0

+ 15 - 15
app/src/main/java/com/adealink/weparty/App.kt

@@ -8,9 +8,8 @@ import androidx.room.Room
 import com.adealink.frame.aab.AAB
 import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.apm.initAPMService
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.crash.installCrashProtector
-import com.adealink.frame.data.json.initJsonConfig
 import com.adealink.frame.debug.datasource.performanceDataController
 import com.adealink.frame.debug.floatkit.floatKitManager
 import com.adealink.frame.deviceid.createDeviceIdService
@@ -27,6 +26,8 @@ import com.adealink.frame.initStorageService
 import com.adealink.frame.locale.language.createLanguageManager
 import com.adealink.frame.log.Log
 import com.adealink.frame.log.XLogHelper
+import com.adealink.frame.log.manager.ILogService
+import com.adealink.frame.log.manager.LogService
 import com.adealink.frame.media.createMediaService
 import com.adealink.frame.network.INetworkService
 import com.adealink.frame.network.NetworkService
@@ -45,6 +46,7 @@ import com.adealink.frame.startup.task.StartUpTask
 import com.adealink.frame.startup.task.SubNoWaitStartUpTask
 import com.adealink.frame.startup.task.SubWaitStartUpTask
 import com.adealink.frame.statistics.report.initStat
+import com.adealink.frame.storage.file.logPath
 import com.adealink.frame.storageService
 import com.adealink.frame.tceffect.TCEffectManager
 import com.adealink.frame.util.ActivityLifecycleCallbacksExt
@@ -55,7 +57,7 @@ import com.adealink.tcturing.TCTuringManager
 import com.adealink.weparty.aab.AABConfig
 import com.adealink.weparty.apm.APMConfig
 import com.adealink.weparty.apm.initAPM
-import com.adealink.weparty.base.AppBaseConfig
+import com.adealink.weparty.base.AppBaseImpl
 import com.adealink.weparty.commonui.WEUI
 import com.adealink.weparty.commonui.widget.floatview.WindowManagerProxy
 import com.adealink.weparty.constant.TAG_TIME_APP_START
@@ -77,7 +79,6 @@ import com.adealink.weparty.hardware.HardwareManager
 import com.adealink.weparty.hardware.IHardwareManager
 import com.adealink.weparty.im.IMConfig
 import com.adealink.weparty.image.ImageConfig
-import com.adealink.weparty.json.JsonConfig
 import com.adealink.weparty.locale.LanguageConfig
 import com.adealink.weparty.log.LogConfig
 import com.adealink.weparty.media.IMediaManager
@@ -100,7 +101,6 @@ import com.adealink.weparty.sound.SoundPlayerConfig
 import com.adealink.weparty.stat.StatConfig
 import com.adealink.weparty.storage.config.StorageConfig
 import com.adealink.weparty.storage.db.AppDatabase
-import com.adealink.weparty.storage.file.FilePath
 import com.adealink.weparty.url.urlConfigService
 import com.adealink.weparty.webview.JSBridgeConfig
 import com.adealink.weparty.webview.WebResourceConfig
@@ -146,6 +146,7 @@ class App : SplitCompatApplication(), ActivityLifecycleCallbacksExt {
     val database by lazy {
         Room.databaseBuilder(applicationContext, AppDatabase::class.java, "weparty_app_db").build()
     }
+    val logService: ILogService by lazy { LogService(LogConfig()) }
     val imService by lazy { IMService.create(IMConfig()) }
     val hardwareManager: IHardwareManager by lazy { HardwareManager() }
 
@@ -153,7 +154,7 @@ class App : SplitCompatApplication(), ActivityLifecycleCallbacksExt {
     override fun attachBaseContext(base: Context?) {
         logTime(TAG_TIME_APP_START, "app attachBaseContext start")
         instance = this
-        AppBaseInfo.init(AppBaseConfig())
+        AppBase.init(AppBaseImpl())
         AppUtil.init(this)
         super.attachBaseContext(base)
         appStartTime = SystemClock.elapsedRealtime()
@@ -198,7 +199,7 @@ class App : SplitCompatApplication(), ActivityLifecycleCallbacksExt {
             //其他子任务(不卡主流程)
             addAppStartTask(InitOther())
 
-            if (!AppBaseInfo.isRelease) {
+            if (!AppBase.isRelease) {
                 addAppStartTask(InitDebugKit())
             }
 
@@ -221,15 +222,14 @@ class App : SplitCompatApplication(), ActivityLifecycleCallbacksExt {
         installCrashProtector(CrashConfig())
         initCrash(this@App) //依赖xlog,stat,crash protector
         AAB.init(AABConfig())
-        initJsonConfig(JsonConfig())
         Log.i(TAG_TIME_APP_START, "baseStartTask end, cost: ${SystemClock.elapsedRealtime() - startTs}")
     }
 
     private fun initXLog() {
         XLogHelper.initXLog(
             if (BuildConfig.OFFICIAL || BuildConfig.DEBUG) Xlog.LEVEL_ALL else Xlog.LEVEL_INFO,
-            FilePath.logPath,
-            FilePath.logPath,
+            logPath,
+            logPath,
             BuildConfig.DEBUG
         )
         Log.setLogConfig(LogConfig())
@@ -249,7 +249,7 @@ class App : SplitCompatApplication(), ActivityLifecycleCallbacksExt {
         override fun run() {
             //UI初始化
             WEUI.init(this@App)
-            ScreenAutoSizeUtil.init(this@App, !AppBaseInfo.isRelease)
+            ScreenAutoSizeUtil.init(this@App, !AppBase.isRelease)
             WindowManagerProxy.init()
         }
     }
@@ -364,8 +364,8 @@ class App : SplitCompatApplication(), ActivityLifecycleCallbacksExt {
 
     inner class InitFB : SubWaitStartUpTask() {
         override fun run() {
-            if (!AppBaseInfo.isRelease) {
-                FacebookSdk.setIsDebugEnabled(AppBaseInfo.isRelease)
+            if (!AppBase.isRelease) {
+                FacebookSdk.setIsDebugEnabled(AppBase.isRelease)
                 FacebookSdk.addLoggingBehavior(LoggingBehavior.APP_EVENTS)
             }
         }
@@ -390,7 +390,7 @@ class App : SplitCompatApplication(), ActivityLifecycleCallbacksExt {
                 this@App,
                 InitOption.Builder()
                     .setAreaCode(
-                        when (AppBaseInfo.isProdEnv) {
+                        when (AppBase.isProdEnv) {
                             true -> InitOption.AreaCode.SG
                             else -> InitOption.AreaCode.BJ
                         }
@@ -436,7 +436,7 @@ class App : SplitCompatApplication(), ActivityLifecycleCallbacksExt {
         override val isRunOnMainThread: Boolean = true
 
         override fun run() {
-            if (AppBaseInfo.isRelease) {
+            if (AppBase.isRelease) {
                 return
             }
             if (DebugPrefs.showPerformanceFloatView) {

+ 0 - 20
app/src/main/java/com/adealink/weparty/aab/AABConfig.kt

@@ -2,8 +2,6 @@ package com.adealink.weparty.aab
 
 import android.app.Application
 import com.adealink.frame.aab.IAABConfig
-import com.adealink.frame.aab.log.ILog
-import com.adealink.frame.log.Log
 import com.adealink.weparty.App
 
 /**
@@ -13,22 +11,4 @@ class AABConfig : IAABConfig {
 
     override val application: Application
         get() = App.instance
-    override val log: ILog
-        get() = object : ILog {
-
-            override fun logD(tag: String, msg: String) {
-                Log.d(tag, msg)
-            }
-
-            override fun logI(tag: String, msg: String) {
-                Log.i(tag, msg)
-            }
-
-            override fun logE(tag: String, msg: String, e: Exception?) {
-                Log.e(tag, msg, e)
-            }
-
-        }
-
-
 }

+ 12 - 27
app/src/main/java/com/adealink/weparty/apm/APMInit.kt

@@ -14,19 +14,18 @@ import com.adealink.frame.apm.plugins.memory.memoryleak.MemoryLeakPlugin
 import com.adealink.frame.apm.plugins.uiblock.ANRStat
 import com.adealink.frame.apm.plugins.uiblock.BlockStat
 import com.adealink.frame.apm.plugins.uiblock.UIBlockMonitor
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.coroutine.dispatcher.Dispatcher
 import com.adealink.frame.data.json.toJsonErrorNull
-import com.adealink.frame.log.ILog
 import com.adealink.frame.log.Log
 import com.adealink.frame.log.Log.splitLog
+import com.adealink.frame.log.data.APMLogType
+import com.adealink.frame.log.data.ReportLogReason
 import com.adealink.frame.util.AppUtil
 import com.adealink.frame.util.ProcessUtil
 import com.adealink.weparty.App
 import com.adealink.weparty.BuildConfig
 import com.adealink.weparty.apm.stat.APMStatEvent
-import com.adealink.weparty.log.data.UploadLogType
-import com.adealink.weparty.log.manager.logManager
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 
@@ -52,12 +51,12 @@ fun initAPM(application: Application) {
 
         use(UIBlockMonitor {
             releaseUploadThreshold = 3000
-            uiBlockEnable = BuildConfig.DEBUG || !AppBaseInfo.isRelease //开发阶段默认开启,线上发布需要灰度收集
+            uiBlockEnable = BuildConfig.DEBUG || !AppBase.isRelease //开发阶段默认开启,线上发布需要灰度收集
         })
         use(LargeBitmapPlugin(
             LargeBitmapConfig.Builder()
                 .apply {
-                    largeBitmapEnable = BuildConfig.DEBUG || !AppBaseInfo.isRelease //只在开发阶段使用
+                    largeBitmapEnable = BuildConfig.DEBUG || !AppBase.isRelease //只在开发阶段使用
                 }
                 .build())
         )
@@ -65,23 +64,9 @@ fun initAPM(application: Application) {
             MemoryLeakPlugin(
                 MemoryConfig()
                     .apply {
-                        memoryLeakEnable = BuildConfig.DEBUG || !AppBaseInfo.isRelease //只在开发阶段使用
+                        memoryLeakEnable = BuildConfig.DEBUG || !AppBase.isRelease //只在开发阶段使用
                     })
         )
-
-        setLog(object : ILog {
-            override fun logD(tag: String, msg: String) {
-                Log.d(tag, msg)
-            }
-
-            override fun logI(tag: String, msg: String) {
-                Log.i(tag, msg)
-            }
-
-            override fun logE(tag: String, msg: String, e: Exception?) {
-                Log.e(tag, msg, e)
-            }
-        })
     }
 }
 
@@ -131,8 +116,8 @@ private fun reportANR(anrStat: ANRStat) {
         val time = System.currentTimeMillis()
         splitLog("$anrEventMap")
             .forEach { Log.i(TAG_APM, "anr($time) = $it") }
-        logManager.uploadLongString("anr($time)", "${toJsonErrorNull(anrEventMap)}")
-        logManager.uploadLog(UploadLogType.FIVE_DAY)
+        App.instance.logService.uploadLongString("anr($time)", "${toJsonErrorNull(anrEventMap)}")
+        App.instance.logService.uploadLog(ReportLogReason.APM(APMLogType.ANR))
     }
 }
 
@@ -147,8 +132,8 @@ private fun reportUiBlock(blockStat: BlockStat) {
         val time = System.currentTimeMillis()
         splitLog("$blockEventMap")
             .forEach { Log.i(TAG_APM, "ui block($time) = $it") }
-        logManager.uploadLongString("ui block($time)", "${toJsonErrorNull(blockEventMap)}")
-        logManager.uploadLog(UploadLogType.FIVE_DAY)
+        App.instance.logService.uploadLongString("ui block($time)", "${toJsonErrorNull(blockEventMap)}")
+        App.instance.logService.uploadLog(ReportLogReason.APM(APMLogType.UI_BLOCK))
     }
 }
 
@@ -167,7 +152,7 @@ private fun reportMemoryLeak(stat: LeakStat) {
         val time = System.currentTimeMillis()
         splitLog("$memoryEventMap")
             .forEach { Log.i(TAG_APM, "memory leak($time) = $it") }
-        logManager.uploadLongString("memory leak($time)", "${toJsonErrorNull(memoryEventMap)}")
-        logManager.uploadLog(UploadLogType.FIVE_DAY)
+        App.instance.logService.uploadLongString("memory leak($time)", "${toJsonErrorNull(memoryEventMap)}")
+        App.instance.logService.uploadLog(ReportLogReason.APM(APMLogType.MEMORY_LEAK))
     }
 }

+ 19 - 3
app/src/main/java/com/adealink/weparty/base/AppBaseConfig.kt → app/src/main/java/com/adealink/weparty/base/AppBaseImpl.kt

@@ -1,12 +1,14 @@
 package com.adealink.weparty.base
 
 import android.net.Uri
-import com.adealink.frame.base.IAppBaseConfig
+import com.adealink.frame.base.IAppBase
+import com.adealink.frame.log.ILog
+import com.adealink.frame.log.Log
+import com.adealink.weparty.BuildConfig
 import com.adealink.weparty.debug.DebugPrefs
 import com.adealink.weparty.network.RELEASE_HOSTS
-import com.adealink.weparty.BuildConfig
 
-class AppBaseConfig : IAppBaseConfig {
+class AppBaseImpl: IAppBase {
     override val debugLog: Boolean
         get() = BuildConfig.DEBUG
     override val isRelease: Boolean
@@ -21,4 +23,18 @@ class AppBaseConfig : IAppBaseConfig {
         get() = isRelease || RELEASE_HOSTS.contains(Uri.parse(DebugPrefs.httpUrl).host)
     override val appName: String
         get() = "yoki"
+    override val log: ILog = object : ILog {
+
+        override fun d(tag: String, msg: String) {
+            Log.d(tag, msg)
+        }
+
+        override fun i(tag: String, msg: String) {
+            Log.i(tag, msg)
+        }
+
+        override fun e(tag: String, msg: String, e: Exception?) {
+            Log.e(tag, msg, e)
+        }
+    }
 }

+ 2 - 2
app/src/main/java/com/adealink/weparty/cocosgame/BaseCocosWebGameFragment.kt

@@ -8,7 +8,7 @@ import androidx.core.view.updateLayoutParams
 import androidx.fragment.app.DialogFragment
 import androidx.lifecycle.Observer
 import androidx.viewbinding.ViewBinding
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.router.Router
 import com.adealink.weparty.cocosgame.chat.listener.IChatOperateListener
 import com.adealink.weparty.cocosgame.data.ClickAvatarOpData
@@ -86,7 +86,7 @@ abstract class BaseCocosWebGameFragment<VM : BaseCocosWebGameViewModel<*, *, *,
         )
         loadUrlAfterViewCreated()
         onCocosGameViewCreated(contentViewBinding)
-        if (!AppBaseInfo.isRelease) {
+        if (!AppBase.isRelease) {
             // DEBUG包打印游戏路径
             showToast("DEBUG: gameCode:${cocosGame()}, gameUrl:${gameUrl()}")
         }

+ 2 - 2
app/src/main/java/com/adealink/weparty/cocosgame/data/CocosGameData.kt

@@ -2,7 +2,7 @@ package com.adealink.weparty.cocosgame.data
 
 import android.os.Parcelable
 import com.adealink.frame.aab.util.getCompatString
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.locale.language.data.Language
 import com.adealink.frame.locale.language.languageManager
 import com.adealink.frame.util.PackageUtil
@@ -100,7 +100,7 @@ enum class LeaveRoomReason(val reason: String) {
 data class JoinRoomReq(
     @SerializedName("roomId") val roomId: Long,
     @SerializedName("versionCode") val versionCode: Int = PackageUtil.getVersionCode(),
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("packageName") val packageName: String = PackageUtil.getPackageName(),
 )
 

+ 3 - 3
app/src/main/java/com/adealink/weparty/cocosgame/data/CocosWindowViewData.kt

@@ -2,7 +2,7 @@ package com.adealink.weparty.cocosgame.data
 
 import android.os.Parcelable
 import android.util.Size
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.data.json.froJsonErrorNull
 import com.adealink.frame.data.json.toJsonErrorNull
 import com.adealink.frame.locale.country.getNewCountryCode
@@ -183,7 +183,7 @@ data class CocosWindowViewData(
     @SerializedName("room_id") val roomId: Long = 0,
     @SerializedName("scheme_host") val schemeHost: String = Router.getDeepLink(""),
     @SerializedName("ws_url") val wsUrl: String = "",
-    @SerializedName("app_name") val appName: String = AppBaseInfo.appName,
+    @SerializedName("app_name") val appName: String = AppBase.appName,
     @SerializedName("package_name") val packageName: String = PackageUtil.getPackageName(),
     //埋点数据相关,跟StatConfig保持一致
     @SerializedName("report_url") val reportUrl: String = "https://api-log-upload.wenext.technology/api/log",
@@ -199,7 +199,7 @@ data class CocosWindowViewData(
     @SerializedName("organic_install") val organicInstall: Boolean = !AttributionModule.isInorganicInstall(),
     @SerializedName("os_version") val osVersion: String = getOsVersion(),
     @SerializedName("api_level") val apiLevel: Int = getApiLevel(),
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("region") val region: String? = ProfileModule.getMyUserInfo()?.region,
     @SerializedName("uid") val uid: Long = ProfileModule.getMyUid(),
     @SerializedName("version_code") val versionCode: Int = PackageUtil.getVersionCode(),

+ 2 - 2
app/src/main/java/com/adealink/weparty/cocosgame/data/GameData.kt

@@ -3,7 +3,7 @@ package com.adealink.weparty.cocosgame.data
 import android.os.Parcelable
 import androidx.annotation.StringRes
 import com.adealink.frame.aab.util.getCompatString
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.util.PackageUtil
 import com.adealink.weparty.R
 import com.google.gson.annotations.GsonNullable
@@ -91,7 +91,7 @@ data class GameShowConfigReq(
     @SerializedName("configTypes") val configTypes: List<Int>,
     @SerializedName("versionCode") val versionCode: Int,
     @SerializedName("channel") val channel: String,
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("packageName") val packageName: String = PackageUtil.getPackageName(),
 )
 

+ 2 - 2
app/src/main/java/com/adealink/weparty/cocosgame/method/OnGetAppEnv.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.cocosgame.method
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.log.Log
 import com.adealink.weparty.cocosgame.data.TAG_COCOS_GAME_FLOW
 import com.adealink.weparty.webview.jsbridge.callback.JSBridgeCallback
@@ -25,7 +25,7 @@ class OnGetAppEnvJsMethod: JSNativeMethod<Any, EnvInfo> {
 
     override fun handleMethodCall(data: Any, callback: JSBridgeCallback<EnvInfo>?) {
         Log.d(TAG_COCOS_GAME_FLOW, "$METHOD_NAME, data:${data}")
-        callback?.resolve(EnvInfo(AppBaseInfo.isRelease.not()))
+        callback?.resolve(EnvInfo(AppBase.isRelease.not()))
     }
 
 }

+ 17 - 10
app/src/main/java/com/adealink/weparty/cocosgame/method/OnNetworkRequest.kt

@@ -51,6 +51,7 @@ class OnNetworkRequestJsMethod(val getGameMeta: () -> String?) :
         val type = dataJSONObject.optInt("type")
         when (NetworkType.map(type)) {
             NetworkType.HTTP -> {
+                val method = dataJSONObject.optString("method").ifEmpty { "POST" }
                 val path = dataJSONObject.optString("path")
                 if (path.isNullOrEmpty()) {
                     callback?.reject(GameErrorCode.HTTP_PATH_NULL_ERROR.code)
@@ -63,18 +64,24 @@ class OnNetworkRequestJsMethod(val getGameMeta: () -> String?) :
                     headers["game_meta_data"] = it
                     headers[Constants.KEY_CORE_REQ] = Constants.CORE_REQ_VALUE
                 }
-                App.instance.networkService.httpPost(url, headers, dataJson, object : Callback<String> {
-
-                    override fun onCall(t: String?) {
-                        if (t.isNullOrEmpty()) {
-                            callback?.reject(GameErrorCode.DATA_NULL_ERROR.code)
-                            return
+                App.instance.networkService.http(
+                    method,
+                    url,
+                    headers,
+                    dataJson,
+                    null,
+                    object : Callback<String> {
+
+                        override fun onCall(t: String?) {
+                            if (t.isNullOrEmpty()) {
+                                callback?.reject(GameErrorCode.DATA_NULL_ERROR.code)
+                                return
+                            }
+
+                            callback?.resolve(NetworkData(t))
                         }
 
-                        callback?.resolve(NetworkData(t))
-                    }
-
-                })
+                    })
             }
 
             NetworkType.SOCKET -> {

+ 2 - 2
app/src/main/java/com/adealink/weparty/cocosgame/viewmodel/BaseCocosWebGameViewModel.kt

@@ -6,7 +6,7 @@ import android.os.Vibrator
 import android.view.View
 import androidx.annotation.CallSuper
 import androidx.lifecycle.LiveData
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.base.IError
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.ext.doOnGlobalLayout
@@ -199,7 +199,7 @@ abstract class BaseCocosWebGameViewModel<GameType, GameMode, MagicMode, PlayerCo
                 RoomModule.getJoinedRoomId() ?: 0,
                 wsUrl = App.instance.networkService.replaceUrlHost(
                     when {
-                        AppBaseInfo.isProdEnv -> "wss://${getLocalHost()}/api/gamewebsocket"
+                        AppBase.isProdEnv -> "wss://${getLocalHost()}/api/gamewebsocket"
                         else -> "ws://${getLocalHost()}/api/gamewebsocket"
                     }
                 )

+ 2 - 2
app/src/main/java/com/adealink/weparty/cocosgame/web/CocosGameWebView.kt

@@ -7,7 +7,7 @@ import android.util.AttributeSet
 import android.view.ViewGroup
 import android.webkit.WebSettings
 import android.webkit.WebView
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.base.fastLazy
 import com.adealink.frame.log.Log
 import com.adealink.weparty.App
@@ -61,7 +61,7 @@ class CocosGameWebView : SPWebView, IWebView {
             //5.0以上开启混合模式加载
             settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
         }
-        if (!AppBaseInfo.isRelease && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+        if (!AppBase.isRelease && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
             setWebContentsDebuggingEnabled(true)
         }
         settings.builtInZoomControls = false

+ 2 - 2
app/src/main/java/com/adealink/weparty/config/Data.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.config
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.util.ONE_MINUTE
 import com.adealink.frame.util.PackageUtil
 import com.adealink.weparty.channel.getChannel
@@ -12,7 +12,7 @@ data class GetGlobalConfigReq(
     @SerializedName("configs") val configs: List<Int>,
     @SerializedName("seqid") val seqId: Long = System.currentTimeMillis(),
     @SerializedName("versionCode") val versionCode: Int = PackageUtil.getVersionCode(),
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("packageName") val packageName: String = PackageUtil.getPackageName(),
     @SerializedName("channel") val channel: String = getChannel(),
 )

+ 7 - 8
app/src/main/java/com/adealink/weparty/crash/CrashInit.kt

@@ -1,17 +1,17 @@
 package com.adealink.weparty.crash
 
 import android.app.Application
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.coroutine.dispatcher.Dispatcher
 import com.adealink.frame.crash.report.CrashConfig
 import com.adealink.frame.crash.report.CrashReporter
 import com.adealink.frame.data.json.toJsonErrorNull
 import com.adealink.frame.log.Log
 import com.adealink.frame.log.Log.splitLog
+import com.adealink.frame.log.data.APMLogType
+import com.adealink.frame.log.data.ReportLogReason
 import com.adealink.weparty.App
 import com.adealink.weparty.apm.stat.APMStatEvent
-import com.adealink.weparty.log.data.UploadLogType
-import com.adealink.weparty.log.manager.logManager
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 
@@ -34,9 +34,9 @@ fun initCrash(application: Application) {
             }
 
             override fun reportCrash(map: MutableMap<String, String>) {
-                if(!AppBaseInfo.isRelease) {
+                if(!AppBase.isRelease) {
                     CoroutineScope(Dispatcher.WENEXT_THREAD_POOL).launch {
-                        logManager.uploadLongString("crash${System.currentTimeMillis()})", "${toJsonErrorNull(map)}")
+                        App.instance.logService.uploadLongString("crash${System.currentTimeMillis()})", "${toJsonErrorNull(map)}")
                     }
                 }
                 APMStatEvent(APMStatEvent.Action.CRASH)
@@ -51,9 +51,8 @@ fun initCrash(application: Application) {
                     val time = System.currentTimeMillis()
                     splitLog(crashJson)
                         .forEach { Log.i(TAG_CRASH, "crash($time) = $it") }
-                    logManager.uploadLongString("crash($time)", crashJson)
-                    logManager.uploadLog(UploadLogType.FIVE_DAY)
-                }
+                    App.instance.logService.uploadLongString("crash($time)", crashJson)
+                    App.instance.logService.uploadLog(ReportLogReason.APM(APMLogType.CRASH))                }
             }
 
         })

+ 13 - 9
app/src/main/java/com/adealink/weparty/debug/DebugActivity.kt

@@ -5,10 +5,13 @@ import android.net.Uri
 import android.os.Bundle
 import androidx.activity.viewModels
 import androidx.lifecycle.lifecycleScope
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.debug.datasource.performanceDataController
 import com.adealink.frame.debug.floatkit.floatKitManager
+import com.adealink.frame.log.data.ReportLogReq
+import com.adealink.frame.log.data.ReportLogType
+import com.adealink.frame.log.viewmodel.LogViewModel
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.network.data.Res
 import com.adealink.frame.router.Router
@@ -24,7 +27,7 @@ import com.adealink.weparty.commonui.widget.BottomDialogFragment
 import com.adealink.weparty.commonui.widget.floatview.WindowManagerProxy
 import com.adealink.weparty.commonui.widget.floatview.data.MODE_APPLICATION
 import com.adealink.weparty.databinding.ActivityDebugBinding
-import com.adealink.weparty.log.viewmodel.LogViewModel
+import com.adealink.weparty.log.viewmodel.LogViewModelFactory
 import com.adealink.weparty.module.account.AccountLocalService
 import com.adealink.weparty.module.call.Call
 import com.adealink.weparty.module.call.CallModule
@@ -45,7 +48,7 @@ import retrofit2.http.POST
 class DebugActivity : BaseActivity(), OnReturnValue {
 
     private val binding by viewBinding(ActivityDebugBinding::inflate)
-    private val logViewModel by viewModels<LogViewModel>()
+    private val logViewModel by viewModels<LogViewModel> { LogViewModelFactory() }
     private val api = App.instance.networkService.getHttpService(DebugApi::class.java)
 
     @SuppressLint("SetTextI18n")
@@ -118,7 +121,7 @@ class DebugActivity : BaseActivity(), OnReturnValue {
             binding.switchSvgaChecker.show()
             binding.tvSvgaChecker.text = getSvgaCheckerText()
             binding.clSvgaChecker.setOnClickListener {
-                if (AppBaseInfo.isRelease) {
+                if (AppBase.isRelease) {
                     showToast("RELEASE包不能设置")
                     return@setOnClickListener
                 }
@@ -127,7 +130,7 @@ class DebugActivity : BaseActivity(), OnReturnValue {
             binding.clSvgaCheckerResult.show()
             binding.tvSvgaCheckerResult.text = getSvgaCheckResultText()
             binding.clSvgaCheckerResult.setOnClickListener {
-                if (AppBaseInfo.isRelease) {
+                if (AppBase.isRelease) {
                     showToast("RELEASE包不能设置")
                     return@setOnClickListener
                 }
@@ -164,7 +167,7 @@ class DebugActivity : BaseActivity(), OnReturnValue {
 
         binding.swPerformanceMonitor.isChecked = isShowMemoryFloatView
         binding.swPerformanceMonitor.setOnCheckedChangeListener { _, isChecked ->
-            if (AppBaseInfo.isRelease) {
+            if (AppBase.isRelease) {
                 return@setOnCheckedChangeListener
             }
             isShowMemoryFloatView = isChecked
@@ -199,7 +202,8 @@ class DebugActivity : BaseActivity(), OnReturnValue {
     private fun reportLog() {
         val uid = binding.logUidEt.text.toString()
         val uidLong = uid.toLongOrNull() ?: return
-        logViewModel.reportLog(uidLong).observe(this) {
+        val req = ReportLogReq(uidLong, logTypes = listOf(ReportLogType.USER.type))
+        logViewModel.reportLog(req).observe(this) {
             showToast(it)
         }
     }
@@ -291,7 +295,7 @@ class DebugActivity : BaseActivity(), OnReturnValue {
     }
 
     private fun getSvgaCheckerText(): String {
-        if (AppBaseInfo.isRelease) {
+        if (AppBase.isRelease) {
             return "RELEASE包不能设置"
         }
         return if (DebugPrefs.enableSvgaChecker) {
@@ -302,7 +306,7 @@ class DebugActivity : BaseActivity(), OnReturnValue {
     }
 
     private fun getSvgaCheckResultText(): String {
-        if (AppBaseInfo.isRelease) {
+        if (AppBase.isRelease) {
             return "RELEASE包不能设置"
         }
         if (!DebugPrefs.enableSvgaChecker) {

+ 3 - 3
app/src/main/java/com/adealink/weparty/debug/DebugUtil.kt

@@ -1,14 +1,14 @@
 package com.adealink.weparty.debug
 
 import android.net.Uri
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.weparty.network.DEBUG_HOST_CN
 import com.adealink.weparty.network.RELEASE_HOSTS
 import com.adealink.weparty.network.getLocalHost
 
 fun isCNTestEnv(): Boolean {
     return when {
-        AppBaseInfo.isRelease -> false
+        AppBase.isRelease -> false
         DebugPrefs.httpUrl.isEmpty() -> {
             getLocalHost() == DEBUG_HOST_CN
         }
@@ -23,7 +23,7 @@ fun isTestEnv(): Boolean {
 }
 
 fun envName(): String {
-    if (AppBaseInfo.isRelease) {
+    if (AppBase.isRelease) {
         return "生产"
     }
 

+ 2 - 2
app/src/main/java/com/adealink/weparty/deviceidservice/DeviceIdServiceConfig.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.deviceidservice
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.base.CommonDataNullError
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.deviceid.IDeviceIdServiceConfig
@@ -33,7 +33,7 @@ class DeviceIdServiceConfig : IDeviceIdServiceConfig {
             UpdateDeviceIdRequest(
                 deviceId,
                 oldDeviceId,
-                AppBaseInfo.platform,
+                AppBase.platform,
                 gAid,
                 androidId,
                 mac,

+ 32 - 0
app/src/main/java/com/adealink/weparty/download/DownloadConfig.kt

@@ -1,7 +1,12 @@
 package com.adealink.weparty.download
 
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.base.WriterCallback
 import com.adealink.frame.download.config.IDownloadConfig
+import com.adealink.frame.download.constant.DownloadResultData
+import com.adealink.frame.network.stat.NetMonitorStatEvent
 import com.adealink.frame.oss.IOssService
+import com.adealink.frame.storageService
 import com.adealink.weparty.App
 import okhttp3.OkHttpClient
 
@@ -17,4 +22,31 @@ class DownloadConfig : IDownloadConfig {
     override val downloadHttpClient: OkHttpClient
         get() = App.instance.networkService.fileHttpClient
 
+    override fun getCacheRootDir(): String {
+        return storageService.file.getCacheRootDir()
+    }
+
+    override fun getTempUsingDir(): String {
+        return storageService.file.getTempUsingDir()
+    }
+
+    override fun report(data: DownloadResultData) {
+        val (url, host, size, duration, protocol, tlsVersion, awsXAmzCfId) = data
+        NetMonitorStatEvent(NetMonitorStatEvent.Action.TRAFFIC)
+            .apply {
+                uri to url
+                this.host to host
+                amount to size
+                this.duration to duration
+                this.protocol to protocol
+                this.tlsVersion to tlsVersion
+                xAmzCfId to awsXAmzCfId
+            }
+            .send()
+    }
+
+    override suspend fun saveFile(savePath: String, callback: WriterCallback): Rlt<Any> {
+        return storageService.file.saveFile(savePath, callback)
+    }
+
 }

+ 21 - 43
app/src/main/java/com/adealink/weparty/effect/AvatarFrameView.kt

@@ -7,7 +7,10 @@ import androidx.core.view.doOnAttach
 import androidx.lifecycle.findViewTreeLifecycleOwner
 import androidx.lifecycle.findViewTreeViewModelStoreOwner
 import com.adealink.frame.base.Rlt
+import com.adealink.frame.effect.data.AnimExtraConfig
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.frame.effect.data.INFINITE_LOOP
+import com.adealink.frame.effect.view.WeAnimView
 import com.adealink.weparty.commonui.ext.gone
 import com.adealink.weparty.commonui.ext.show
 import com.adealink.weparty.module.profile.ProfileModule
@@ -38,7 +41,11 @@ class AvatarFrameView(context: Context, attrs: AttributeSet? = null) : WeAnimVie
                             if (avatarFrameDecor is AvatarFrameDecor) {
                                 show()
                                 showAvatarFrame(avatarFrameDecor)
+                            } else {
+                                stopPlay()
+                                gone()
                             }
+
                         }
 
                         is Rlt.Failed -> {
@@ -52,7 +59,6 @@ class AvatarFrameView(context: Context, attrs: AttributeSet? = null) : WeAnimVie
 
     fun showAvatarFrame(
         avatarFrameConfig: AvatarFrameDecor?,
-        playListener: IWeAnimPlayListener? = null
     ) {
         Log.d(TAG, "hashCode:${hashCode()}, showAvatarFrame, avatarFrameConfig: $avatarFrameConfig")
         if (avatarFrameConfig == null) {
@@ -61,51 +67,23 @@ class AvatarFrameView(context: Context, attrs: AttributeSet? = null) : WeAnimVie
             return
         }
         val effectResource = avatarFrameConfig.effectResource
-        when (EffectAnimType.map(effectResource.animType)) {
-            EffectAnimType.SVGA -> {
-                showSvgaAvatarFrame(avatarFrameConfig, effectResource, playListener)
-            }
-            EffectAnimType.MP4, EffectAnimType.TC -> {
-                showTCAvatarFrame(avatarFrameConfig, effectResource, playListener)
-            }
-            else -> {
-                stopPlay()
-                gone()
-            }
+        val effectAnimType = EffectAnimType.map(effectResource.animType)
+        if (effectAnimType != EffectAnimType.SVGA && effectAnimType != EffectAnimType.MP4 && effectAnimType != EffectAnimType.TC) {
+            stopPlay()
+            gone()
+            return
         }
-    }
-
-    private fun showSvgaAvatarFrame(
-        config: AvatarFrameDecor,
-        effectResource: EffectResource,
-        playListener: IWeAnimPlayListener? = null
-    ) {
-        val svgaExtraConfig = SVGAExtraConfig(
-            dynamicEntitySupplier = config.extraConfig?.createSVGADynamicSupplier(),
-            clearsAfterDetached = false
-        )
-        val animExtraConfig = AnimExtraConfig(
-            loop = INFINITE_LOOP,
-            ratio = config.ratio,
-            svgaExtraConfig = svgaExtraConfig
-        )
-        setUrl(effectResource.resourceUrl, EffectAnimType.SVGA, animExtraConfig, playListener)
-    }
-
-    private fun showTCAvatarFrame(
-        config: AvatarFrameDecor,
-        effectResource: EffectResource,
-        playListener: IWeAnimPlayListener? = null
-    ) {
-        val tcFetchResource = TCExtraConfig(
-            tcFetchResource = config.extraConfig?.createTCFetchResource(),
+        show()
+        setConfig(
+            AnimExtraConfig(
+                loop = INFINITE_LOOP,
+                ratio = avatarFrameConfig.ratio,
+            )
         )
-        val animExtraConfig = AnimExtraConfig(
-            loop = INFINITE_LOOP,
-            ratio = config.ratio,
-            tcExtraConfig = tcFetchResource
+        setUrl(
+            effectResource.resourceUrl,
+            avatarFrameConfig.extraConfig?.createAnimDynamicProvider()
         )
-        setUrl(effectResource.resourceUrl, EffectAnimType.TC, animExtraConfig, playListener)
     }
 
     override fun onDetachedFromWindow() {

+ 3 - 19
app/src/main/java/com/adealink/weparty/effect/EffectConfig.kt

@@ -2,9 +2,8 @@ package com.adealink.weparty.effect
 
 import android.content.Context
 import com.adealink.frame.effect.config.IEffectConfig
-import com.adealink.frame.log.ILog
-import com.adealink.frame.log.Log
 import com.adealink.weparty.App
+import com.adealink.weparty.storage.file.FilePath
 
 /**
  * Created by sunxiaodong on 2021/4/24.
@@ -14,21 +13,6 @@ class EffectConfig : IEffectConfig {
     override val ctx: Context
         get() = App.instance
 
-    override val log: ILog
-        get() = object : ILog {
-
-            override fun logD(tag: String, msg: String) {
-                Log.d(tag, msg)
-            }
-
-            override fun logI(tag: String, msg: String) {
-                Log.i(tag, msg)
-            }
-
-            override fun logE(tag: String, msg: String, e: Exception?) {
-                Log.e(tag, msg)
-            }
-
-        }
-
+    override val videoCachePath: String
+        get() = FilePath.videoCachePath
 }

+ 2 - 58
app/src/main/java/com/adealink/weparty/effect/EffectData.kt

@@ -1,72 +1,16 @@
 package com.adealink.weparty.effect
 
-import android.widget.ImageView
-import com.opensource.svgaplayer.FillMode
-import com.opensource.svgaplayer.SVGADynamicEntity
-import com.opensource.svgaplayer.utils.Supplier
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResource
+import com.adealink.frame.storage.file.WeFile
 
 /**
  * 动效类型
  */
-enum class EffectAnimType(val type: Int) {
-    IMAGE(0), //图片
-    SVGA(1),  //SVGA
-    MP4(2),   //vap或者纯mp4
-    TC(3);    //腾讯云动效
-
-    companion object {
-        fun map(type: Int?): EffectAnimType? {
-            return entries.firstOrNull { it.type == type }
-        }
-
-        fun getOldEffectAnimTypeByUrl(url: String): Int {
-            return when {
-                url.endsWith(".svga") -> {
-                    SVGA.type
-                }
-                url.endsWith(".mp4") -> {
-                    MP4.type
-                }
-                else -> {
-                    IMAGE.type
-                }
-            }
-        }
-    }
-}
-
 data class EffectResource(
     val resourceUrl: String,
     val animType: Int
 )
 
 data class EffectSaveResource(
-    val savePath: String,
+    val effectFile: WeFile?,
     val animType: Int
-)
-
-data class AnimExtraConfig(
-    val loop: Int = 0,//循环次数,<0时,表示无限循环播放
-    val ratio: Float = 1f,
-    val mute: Boolean = false,
-    val scaleType: ImageView.ScaleType? = null,
-    val svgaExtraConfig: SVGAExtraConfig? = null,
-    val tcExtraConfig: TCExtraConfig? = null,
-    val vapExtraConfig: VapExtraConfig? = null,
-    val autoPlay: Boolean? = null,
-)
-
-data class SVGAExtraConfig(
-    val dynamicEntitySupplier: Supplier<SVGADynamicEntity>? = null,
-    val clearsAfterDetached: Boolean = true,
-    val fillMode: FillMode = FillMode.Forward,
-)
-
-data class TCExtraConfig(
-    val tcFetchResource: IFetchResource? = null
-)
-
-data class VapExtraConfig(
-    val vapFetchResource: com.tencent.qgame.animplayer.inter.IFetchResource? = null
 )

+ 72 - 78
app/src/main/java/com/adealink/weparty/effect/EffectPreviewView.kt

@@ -9,7 +9,14 @@ import android.view.View
 import android.widget.FrameLayout
 import androidx.core.view.updateLayoutParams
 import androidx.fragment.app.FragmentManager
+import com.adealink.frame.effect.data.AnimExtraConfig
+import com.adealink.frame.effect.data.DynamicAnimImage
+import com.adealink.frame.effect.data.DynamicAnimText
+import com.adealink.frame.effect.data.EffectAnimType
+import com.adealink.frame.effect.data.IAnimDynamicProvider
 import com.adealink.frame.effect.data.INFINITE_LOOP
+import com.adealink.frame.effect.view.IWeAnimPlayListener
+import com.adealink.frame.effect.view.WeAnimView
 import com.adealink.weparty.R
 import com.adealink.weparty.commonui.ext.isMP4
 import com.adealink.weparty.commonui.ext.isSVGAImage
@@ -18,11 +25,6 @@ import com.adealink.weparty.commonui.ext.show
 import com.adealink.weparty.module.medal.view.MedalImageView
 import com.adealink.weparty.module.medal.view.getMedalLevelImgResource
 import com.adealink.weparty.module.store.StoreModule
-import com.opensource.svgaplayer.SVGADynamicEntity
-import com.opensource.svgaplayer.utils.Supplier
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResource
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResourceImgResult
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResourceTxtResult
 
 class EffectPreviewView @JvmOverloads constructor(
     context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
@@ -37,6 +39,18 @@ class EffectPreviewView @JvmOverloads constructor(
     private var intent: Intent? = null
     private var medalViewConfig: IPreviewView.IMedalViewConfig? = null
     private var animExtraConfig: AnimExtraConfig? = null
+    private var innerPlayListener = object : IWeAnimPlayListener {
+        override fun onPlayStart() {
+            super.onPlayStart()
+            playListener?.onPlayStart()
+        }
+
+        override fun onPlayEnd() {
+            super.onPlayEnd()
+            medalViewConfig?.onPlayEnd()
+        }
+    }
+    private var playListener: IWeAnimPlayListener? = null
 
     override fun setMedalViewConfig(medalViewConfig: IPreviewView.IMedalViewConfig) {
         this.medalViewConfig = medalViewConfig
@@ -48,7 +62,9 @@ class EffectPreviewView @JvmOverloads constructor(
         animType: EffectAnimType?,
         intent: Intent?,
         fragmentManager: FragmentManager?,
-        animExtraConfig: AnimExtraConfig?
+        animExtraConfig: AnimExtraConfig,
+        dynamicProvider: IAnimDynamicProvider?,
+        playListener: IWeAnimPlayListener?
     ) {
         this.previewUrl = previewUrl
         this.animType = animType
@@ -56,28 +72,22 @@ class EffectPreviewView @JvmOverloads constructor(
         this.fragmentManager = fragmentManager//是否单击查看预览图
         this.intent = intent//是否单击查看预览图
         this.animExtraConfig = animExtraConfig
+        this.playListener = playListener
         if (previewUrl.isEmpty()) {
             return
         }
-        var finalAnimType = animType
+        var isAnim = false
         if (animType == null) {
             //未指定animType,根据后缀判断
-            finalAnimType = when {
-                isSVGAImage(previewUrl) -> EffectAnimType.SVGA
-                isMP4(previewUrl) || isTCMP4(previewUrl) -> EffectAnimType.TC
-                else -> EffectAnimType.IMAGE
-            }
-        }
-        if (finalAnimType == null) {
-            return
+            isAnim = isSVGAImage(previewUrl) || isMP4(previewUrl) || isTCMP4(previewUrl)
         }
         removeAllViews()
-        when(finalAnimType) {
-            EffectAnimType.IMAGE -> {
-                setImageView(previewUrl)
+        when (isAnim) {
+            true -> {
+                setWeAnimView(previewUrl, animExtraConfig, dynamicProvider)
             }
             else -> {
-                setWeAnimView(previewUrl, animType, animExtraConfig)
+                setImageView(previewUrl)
             }
         }
     }
@@ -88,72 +98,52 @@ class EffectPreviewView @JvmOverloads constructor(
         animType: EffectAnimType?,
         intent: Intent?,
         fragmentManager: FragmentManager?,
-        autoPlay: Boolean?,
+        autoPlay: Boolean,
         level: Int,
-        subLevel: Int
+        subLevel: Int,
+        playListener: IWeAnimPlayListener?
     ) {
         this.level = level
         this.subLevel = subLevel
-        setURL(previewUrl, animType, intent, fragmentManager, AnimExtraConfig(
-            loop = INFINITE_LOOP,
-            autoPlay = autoPlay,
-            svgaExtraConfig = SVGAExtraConfig(dynamicEntitySupplier = getMedalSvgaDynamicEntity()),
-            tcExtraConfig = TCExtraConfig(tcFetchResource = getMedalTCFetchResource())
-        ))
-    }
-
-    private fun getMedalSvgaDynamicEntity(): Supplier<SVGADynamicEntity>? {
-        val dynamicEntity = SVGADynamicEntity()
+        setURL(
+            previewUrl,
+            animType,
+            intent,
+            fragmentManager,
+            AnimExtraConfig(
+                loop = INFINITE_LOOP,
+                autoPlay = autoPlay,
+            ),
+            dynamicProvider = getMedalAnimDynamicProvider(),
+            playListener = playListener
+        )
+    }
+
+    private fun getMedalAnimDynamicProvider(): IAnimDynamicProvider? {
         val drawableId = getMedalLevelImgResource(level, subLevel)
         if (drawableId == 0) {
             return null
         }
-        return Supplier {
-            val options = BitmapFactory.Options()
-            options.inScaled = false
-            dynamicEntity.setDynamicImage(
-                BitmapFactory.decodeResource(
-                    resources,
-                    drawableId,
-                    options
-                ), "number"
-            )
-            dynamicEntity
-        }
-    }
-
-    private fun getMedalTCFetchResource(): IFetchResource {
-        return object : IFetchResource {
-            override fun fetchImage(
-                resource: com.tencent.tcmediax.tceffectplayer.api.mix.Resource,
-                result: IFetchResourceImgResult
-            ) {
-                if (resource.tag == "number") {
-                    val drawableId = getMedalLevelImgResource(level, subLevel)
-                    if (drawableId == 0) {
-                        result.fetch(null)
-                        return
-                    }
-                    val options = BitmapFactory.Options()
-                    options.inScaled = false
-                    result.fetch(BitmapFactory.decodeResource(resources, drawableId, options))
-                } else {
-                    result.fetch(null)
-                }
+        return object : IAnimDynamicProvider {
+            override fun provideImage(callback: (Map<String, DynamicAnimImage>?) -> Unit) {
+                callback(
+                    hashMapOf(
+                        "number" to DynamicAnimImage {
+                            BitmapFactory.decodeResource(
+                                resources,
+                                drawableId,
+                                BitmapFactory.Options().apply {
+                                    inScaled = false
+                                })
+                        }
+                    )
+                )
             }
 
-            override fun fetchText(
-                resource: com.tencent.tcmediax.tceffectplayer.api.mix.Resource,
-                result: IFetchResourceTxtResult
-            ) {
-                result.loadTextForPlayer(null)
+            override fun provideText(callback: (Map<String, DynamicAnimText>?) -> Unit) {
+                callback(null)
             }
 
-            override fun releaseResource(resources: MutableList<com.tencent.tcmediax.tceffectplayer.api.mix.Resource>) {
-                resources.forEach {
-                    it.bitmap?.recycle()
-                }
-            }
         }
     }
 
@@ -169,11 +159,15 @@ class EffectPreviewView @JvmOverloads constructor(
         imageView.setMedal(img, level, subLevel, false)
     }
 
-    private fun setWeAnimView(url: String, animType: EffectAnimType?, animExtraConfig: AnimExtraConfig? = null) {
+    private fun setWeAnimView(
+        url: String,
+        animExtraConfig: AnimExtraConfig,
+        dynamicProvider: IAnimDynamicProvider? = null
+    ) {
         val weAnimView = inflateWeAnimView()
-        weAnimView.setUrl(url, animType = animType, extraConfig = animExtraConfig, onPlayEnd = {
-            medalViewConfig?.onPlayEnd()
-        })
+        weAnimView.setConfig(animExtraConfig)
+        weAnimView.setListener(innerPlayListener)
+        weAnimView.setUrl(url, dynamicProvider)
     }
 
     private fun inflateImageView(): MedalImageView {
@@ -219,7 +213,7 @@ class EffectPreviewView @JvmOverloads constructor(
     }
 
     override fun startPlay() {
-        setURL(previewUrl, animType = animType, intent, fragmentManager, animExtraConfig)
+        setURL(previewUrl, animType = animType, intent, fragmentManager, animExtraConfig?: AnimExtraConfig(), getMedalAnimDynamicProvider(), playListener)
     }
 
     override fun stopPlay() {

+ 18 - 43
app/src/main/java/com/adealink/weparty/effect/EffectViewModel.kt

@@ -2,31 +2,29 @@ package com.adealink.weparty.effect
 
 import androidx.lifecycle.LiveData
 import com.adealink.frame.base.IError
-import com.adealink.frame.coroutine.dispatcher.Dispatcher
 import com.adealink.frame.download.listener.TaskListener
 import com.adealink.frame.download.task.Task
 import com.adealink.frame.download.task.TaskPriority
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.frame.log.Log
 import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
 import com.adealink.frame.mvvm.viewmodel.BaseViewModel
-import com.adealink.frame.util.createOrExistsDir
-import com.adealink.frame.util.isFileExists
+import com.adealink.frame.storage.file.WeFile
+import com.adealink.frame.storage.file.getCacheFilePathByUrl
+import com.adealink.frame.storageService
 import com.adealink.frame.util.md5
 import com.adealink.weparty.App
-import com.adealink.weparty.storage.file.FilePath
 import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.suspendCancellableCoroutine
-import kotlinx.coroutines.withContext
-import java.io.File
 import kotlin.coroutines.resume
 
 class EffectViewModel : BaseViewModel() {
 
-    fun downloadResources(urls: List<String>, priority: TaskPriority): LiveData<List<String?>> {
-        val liveData = OnceMutableLiveData<List<String?>>()
+    fun downloadResources(urls: List<String>, priority: TaskPriority): LiveData<List<WeFile?>> {
+        val liveData = OnceMutableLiveData<List<WeFile?>>()
         viewModelScope.launch {
             val resultList = coroutineScope {
                 urls.map { url ->
@@ -40,8 +38,8 @@ class EffectViewModel : BaseViewModel() {
         return liveData
     }
 
-    fun downloadResource(url: String, priority: TaskPriority): LiveData<String?> {
-        val liveData = OnceMutableLiveData<String?>()
+    fun downloadResource(url: String, priority: TaskPriority): LiveData<WeFile?> {
+        val liveData = OnceMutableLiveData<WeFile?>()
         viewModelScope.launch {
             liveData.send(
                 downloadEffect(url, priority)
@@ -68,6 +66,7 @@ class EffectViewModel : BaseViewModel() {
                 effectUrl = oldUrl
                 effectAnimType = EffectAnimType.getOldEffectAnimTypeByUrl(oldUrl)
             }
+
             else -> {
                 effectUrl = newUrl
                 effectAnimType = newAnimType
@@ -77,26 +76,18 @@ class EffectViewModel : BaseViewModel() {
             val animType = EffectAnimType.map(effectAnimType)
             if (animType == null) {
                 //不支持的动效类型
-                liveData.send(EffectSaveResource("", effectAnimType))
+                liveData.send(EffectSaveResource(null, effectAnimType))
                 return@launch
             }
             liveData.send(
-                EffectSaveResource(downloadEffect(effectUrl, priority) ?: "", effectAnimType)
+                EffectSaveResource(downloadEffect(effectUrl, priority), effectAnimType)
             )
         }
         return liveData
     }
 
-    fun isDownloaded(url: String): LiveData<Boolean> {
-        val liveData = OnceMutableLiveData<Boolean>()
-        viewModelScope.launch {
-            liveData.send(checkIfNeedDownload(url))
-        }
-        return liveData
-    }
-
-    private suspend fun downloadEffect(url: String, priority: TaskPriority): String? {
-        val savePath = getSavePath(url)
+    private suspend fun downloadEffect(url: String, priority: TaskPriority): WeFile? {
+        val savePath = getCacheFilePathByUrl(url)
         return suspendCancellableCoroutine { continuation ->
             addDownloadTask(url, savePath, priority,
                 { localPath ->
@@ -114,23 +105,19 @@ class EffectViewModel : BaseViewModel() {
         }
     }
 
-    private suspend fun checkIfNeedDownload(url: String): Boolean {
-        val savePath = getSavePath(url)
-        return !isFileExists(savePath)
-    }
-
     private fun addDownloadTask(
         url: String,
         savePath: String,
         priority: TaskPriority,
-        success: ((path: String) -> Unit)? = null,
+        success: ((path: WeFile) -> Unit)? = null,
         failed: ((error: IError) -> Unit)? = null,
     ) {
         Log.d(TAG, "addDownloadTask, url: $url")
         Log.d(TAG, "                 savePath: $savePath")
-        if (isFileExists(savePath)) {
+        val file = storageService.file.createWeFile(savePath)
+        if (file.exists()) {
             Log.d(TAG, "addDownloadTask, fileExist, return")
-            success?.invoke(savePath)
+            success?.invoke(file)
             return
         }
 
@@ -144,7 +131,7 @@ class EffectViewModel : BaseViewModel() {
 
             override fun onFinished(task: Task) {
                 super.onFinished(task)
-                success?.invoke(savePath)
+                success?.invoke(file)
                 Log.d(
                     TAG,
                     "addDownloadTask, download success, task:$task"
@@ -169,18 +156,6 @@ class EffectViewModel : BaseViewModel() {
 
     companion object {
         private const val TAG = "EffectViewModel"
-
-        private suspend fun getSaveDir(): String {
-            val dir = "${FilePath.effectPath}${File.separator}"
-            withContext(Dispatcher.WENEXT_THREAD_POOL) {
-                createOrExistsDir(dir)
-            }
-            return dir
-        }
-
-        suspend fun getSavePath(url: String): String {
-            return "${getSaveDir()}${"${url.md5()}.${url.split(".").last()}"}"
-        }
     }
 
 }

+ 10 - 3
app/src/main/java/com/adealink/weparty/effect/IPreviewView.kt

@@ -3,6 +3,10 @@ package com.adealink.weparty.effect
 import android.content.Intent
 import android.view.View
 import androidx.fragment.app.FragmentManager
+import com.adealink.frame.effect.data.AnimExtraConfig
+import com.adealink.frame.effect.data.EffectAnimType
+import com.adealink.frame.effect.data.IAnimDynamicProvider
+import com.adealink.frame.effect.view.IWeAnimPlayListener
 
 interface IPreviewView {
     fun setURL(
@@ -10,16 +14,19 @@ interface IPreviewView {
         animType: EffectAnimType? = null,
         intent: Intent? = null,
         fragmentManager: FragmentManager? = null,
-        animExtraConfig: AnimExtraConfig? = null
+        animExtraConfig: AnimExtraConfig = AnimExtraConfig(),
+        dynamicProvider: IAnimDynamicProvider? = null,
+        playListener: IWeAnimPlayListener? = null
     )
     fun setMedal(
         previewUrl: String,
         animType: EffectAnimType? = null,
         intent: Intent? = null,
         fragmentManager: FragmentManager? = null,
-        autoPlay: Boolean? = true,
+        autoPlay: Boolean = true,
         level: Int = 0,
-        subLevel: Int = 0
+        subLevel: Int = 0,
+        playListener: IWeAnimPlayListener? = null
     )
 
     fun setMedalViewConfig(medalViewConfig: IPreviewView.IMedalViewConfig)

+ 4 - 4
app/src/main/java/com/adealink/weparty/effect/SvgaConfig.kt

@@ -1,7 +1,7 @@
 package com.adealink.weparty.effect
 
 import android.graphics.Bitmap
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.coroutine.dispatcher.Dispatcher
 import com.adealink.frame.image.imageService
 import com.adealink.frame.image.listener.IImageLoadResultListener
@@ -44,7 +44,7 @@ val SVGA_CONFIG = SvgaConfig(
         }
 
     },
-    debuggable = !AppBaseInfo.isRelease,
+    debuggable = !AppBase.isRelease,
     imageFetcher = object : ImageFetcher {
 
         override fun fetchDynamicImage(
@@ -72,6 +72,6 @@ val SVGA_CONFIG = SvgaConfig(
 
     },
     designWidthPx = 750f,
-    enableSvgaChecker = !AppBaseInfo.isRelease && DebugPrefs.enableSvgaChecker,
-    enableShowSvgaCheckResult = !AppBaseInfo.isRelease && DebugPrefs.enableSvgaChecker && DebugPrefs.enableShowSvgaCheckResult
+    enableSvgaChecker = !AppBase.isRelease && DebugPrefs.enableSvgaChecker,
+    enableShowSvgaCheckResult = !AppBase.isRelease && DebugPrefs.enableSvgaChecker && DebugPrefs.enableShowSvgaCheckResult
 )

+ 2 - 17
app/src/main/java/com/adealink/weparty/effect/TCEffectConfig.kt

@@ -1,9 +1,7 @@
 package com.adealink.weparty.effect
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.data.json.froJsonErrorNull
-import com.adealink.frame.log.ILog
-import com.adealink.frame.log.Log
 import com.adealink.frame.tceffect.config.ITCEffectConfig
 import com.adealink.frame.util.ONE_MINUTE
 import com.adealink.weparty.config.GlobalConfigType
@@ -16,20 +14,7 @@ class TCEffectConfig : ITCEffectConfig {
     )
     override val oldLicence: String = "edbd15d01777ad43b422347e94e90757"
     override val licence: String = "db3ac8d5972ef28cb62c9b7eabe76b39"
-    override val logEnable: Boolean = !AppBaseInfo.isRelease
-    override val log: ILog = object : ILog {
-        override fun logD(tag: String, msg: String) {
-            Log.d(tag, msg)
-        }
-
-        override fun logI(tag: String, msg: String) {
-            Log.i(tag, msg)
-        }
-
-        override fun logE(tag: String, msg: String, e: Exception?) {
-            Log.e(tag, msg)
-        }
-    }
+    override val logEnable: Boolean = !AppBase.isRelease
 
     private var backupHostList: List<String>? = null
     private var lastGetBackupHostConfigTime: Long = 0

+ 0 - 796
app/src/main/java/com/adealink/weparty/effect/WeAnimView.kt

@@ -1,796 +0,0 @@
-package com.adealink.weparty.effect
-
-import android.content.Context
-import android.content.res.TypedArray
-import android.graphics.Matrix
-import android.os.Bundle
-import android.util.AttributeSet
-import android.view.ViewTreeObserver
-import android.widget.FrameLayout
-import android.widget.ImageView
-import androidx.core.view.isVisible
-import com.adealink.frame.base.Rlt
-import com.adealink.frame.coroutine.dispatcher.Dispatcher
-import com.adealink.frame.download.manager.downloadManager
-import com.adealink.frame.download.task.TaskPriority
-import com.adealink.frame.effect.data.INFINITE_LOOP
-import com.adealink.frame.effect.svga.data.PathType
-import com.adealink.frame.log.Log
-import com.adealink.frame.tceffect.TCEffectManager
-import com.adealink.frame.util.AppUtil
-import com.adealink.frame.util.createOrExistsDir
-import com.adealink.frame.util.runOnUiThread
-import com.adealink.weparty.R
-import com.adealink.weparty.commonui.ext.gone
-import com.adealink.weparty.commonui.ext.isMP4
-import com.adealink.weparty.commonui.ext.isSVGAImage
-import com.adealink.weparty.commonui.ext.isTCMP4
-import com.adealink.weparty.commonui.ext.show
-import com.adealink.weparty.storage.file.FilePath
-import com.opensource.svgaplayer.WenextSvgaView
-import com.opensource.svgaplayer.control.ControllerListener
-import com.opensource.svgaplayer.entities.SvgaInfo
-import com.tencent.qgame.animplayer.AnimConfig
-import com.tencent.qgame.animplayer.AnimView
-import com.tencent.qgame.animplayer.inter.IAnimListener
-import com.tencent.qgame.animplayer.util.ScaleType
-import com.tencent.tcmediax.tceffectplayer.api.TCEffectAnimView
-import com.tencent.tcmediax.tceffectplayer.api.TCEffectConfig
-import com.tencent.tcmediax.tceffectplayer.api.TCEffectPlayerConstant
-import com.tencent.tcmediax.tceffectplayer.api.TCEffectPlayerConstant.REPORT_INFO_ON_PLAY_EVT_RCV_FIRST_I_FRAME
-import com.tencent.tcmediax.tceffectplayer.api.data.TCEffectAnimInfo
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.android.asCoroutineDispatcher
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.io.File
-import java.io.FileOutputStream
-
-/**
- * 通用动效播放view,支持svga,带透明度mp4(vap或者腾讯云特效格式),tcmp4,特效类型播放
- * 带透明度mp4在腾讯特效播放器可用情况下使用腾讯云特效播放器播放,否则使用vap播放器播放
- */
-open class WeAnimView @JvmOverloads constructor(
-    context: Context, attrs: AttributeSet? = null
-) : FrameLayout(context, attrs), CoroutineScope {
-    private val serialHandler = Dispatcher.getSerialHandler()
-    override val coroutineContext = SupervisorJob() + serialHandler.asCoroutineDispatcher()
-
-    private var originWidth: Int = 0
-    private var originHeight: Int = 0
-
-    private var svgaAnimView: WenextSvgaView? = null
-    private var tcAnimView: TCEffectAnimView? = null
-    private var vapAnimView: AnimView? = null
-
-    private var downloadJob: Job? = null
-
-    private var autoPlay: Boolean = true
-    private var path: String? = null
-    private var pathType: PathType? = null
-    private var animType: EffectAnimType? = null
-    private var extraConfig: AnimExtraConfig? = null
-    private var listener: IWeAnimPlayListener? = null
-
-    init {
-        attrs?.let { loadAttrs(it) }
-    }
-
-    private fun loadAttrs(attrs: AttributeSet) {
-        if (isInEditMode) {
-            return
-        }
-        val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.WeAnimView, 0, 0)
-        onAttrsLoad(typedArray, context)
-        typedArray.recycle()
-    }
-
-    protected open fun onAttrsLoad(typedArray: TypedArray, context: Context) {
-        autoPlay = typedArray.getBoolean(R.styleable.WeAnimView_autoPlay, true)
-    }
-
-    fun setAsset(
-        url: String,
-        animType: EffectAnimType? = null,
-        extraConfig: AnimExtraConfig? = null,
-        onPlayStart: (() -> Unit)? = null,
-        onPlayEnd: (() -> Unit)? = null,
-        onPlayError: ((errorCode: String) -> Unit)? = null,
-    ) {
-        val listener = if (onPlayStart != null || onPlayEnd != null || onPlayError != null) {
-            object : IWeAnimPlayListener {
-                override fun onPlayStart() {
-                    onPlayStart?.invoke()
-                }
-
-                override fun onPlayEnd() {
-                    onPlayEnd?.invoke()
-                }
-
-                override fun onPlayError(errorCode: String) {
-                    onPlayError?.invoke(errorCode)
-                }
-            }
-        } else {
-            null
-        }
-
-        setAsset(url, animType, extraConfig, listener)
-    }
-
-    fun setAsset(
-        assetName: String,
-        animType: EffectAnimType? = null,
-        extraConfig: AnimExtraConfig? = null,
-        listener: IWeAnimPlayListener? = null
-    ) {
-        Log.d(TAG, "hashCode:${hashCode()}, setAsset, assetName: $assetName")
-
-        this.path = assetName
-        this.pathType = PathType.ASSERT
-        this.animType = animType
-        this.extraConfig = extraConfig
-        this.listener = listener
-
-        var finalAnimType = animType
-        if (animType == null) {
-            //未指定animType,根据后缀判断
-            finalAnimType = getEffectAnimTypeBySuffix(assetName)
-        }
-        if (finalAnimType == null) {
-            stopPlay()
-            gone()
-            return
-        }
-        when {
-            finalAnimType == EffectAnimType.SVGA -> {
-                playSVGA(assetName, PathType.ASSERT, extraConfig, listener)
-            }
-
-            finalAnimType == EffectAnimType.MP4 && !TCEffectManager.isTcEffectEnable() -> {
-                cancelDownloadJob()
-                downloadJob = launch {
-                    val localPath = copyAssetToCache(assetName)
-                    withContext(Dispatcher.UI) {
-                        playVapMp4File(localPath, extraConfig, listener)
-                    }
-                }
-            }
-
-            finalAnimType == EffectAnimType.MP4 || finalAnimType == EffectAnimType.TC -> {
-                cancelDownloadJob()
-                downloadJob = launch {
-                    val localPath = copyAssetToCache(assetName)
-                    withContext(Dispatcher.UI) {
-                        playMp4File(localPath, extraConfig, listener)
-                    }
-                }
-            }
-
-            else -> {
-                //其他暂不支持
-                stopPlay()
-                gone()
-            }
-        }
-    }
-
-    fun setFile(
-        filePath: String,
-        animType: EffectAnimType? = null,
-        extraConfig: AnimExtraConfig? = null,
-        onPlayStart: (() -> Unit)? = null,
-        onPlayEnd: (() -> Unit)? = null,
-        onPlayError: ((errorCode: String) -> Unit)? = null,
-    ) {
-        val listener = if (onPlayStart != null || onPlayEnd != null || onPlayError != null) {
-            object : IWeAnimPlayListener {
-                override fun onPlayStart() {
-                    onPlayStart?.invoke()
-                }
-
-                override fun onPlayEnd() {
-                    onPlayEnd?.invoke()
-                }
-
-                override fun onPlayError(errorCode: String) {
-                    onPlayError?.invoke(errorCode)
-                }
-            }
-        } else {
-            null
-        }
-
-        setFile(filePath, animType, extraConfig, listener)
-    }
-
-    fun setFile(
-        filePath: String,
-        animType: EffectAnimType? = null,
-        extraConfig: AnimExtraConfig? = null,
-        listener: IWeAnimPlayListener? = null
-    ) {
-        Log.d(TAG, "hashCode:${hashCode()}, setFile, filePath: $filePath")
-
-        this.path = filePath
-        this.pathType = PathType.FILE
-        this.animType = animType
-        this.extraConfig = extraConfig
-        this.listener = listener
-
-        var finalAnimType = animType
-        if (animType == null) {
-            //未指定animType,根据后缀判断
-            finalAnimType = getEffectAnimTypeBySuffix(filePath)
-        }
-        if (finalAnimType == null) {
-            stopPlay()
-            gone()
-            return
-        }
-        when {
-            finalAnimType == EffectAnimType.SVGA -> {
-                playSVGA(filePath, PathType.FILE, extraConfig, listener)
-            }
-
-            finalAnimType == EffectAnimType.MP4 && !TCEffectManager.isTcEffectEnable() -> {
-                playVapMp4File(filePath, extraConfig, listener)
-            }
-
-            finalAnimType == EffectAnimType.MP4 || finalAnimType == EffectAnimType.TC -> {
-                playMp4File(filePath, extraConfig, listener)
-            }
-
-            else -> {
-                //其他暂不支持
-                stopPlay()
-                gone()
-            }
-        }
-    }
-
-    fun setUrl(
-        url: String,
-        animType: EffectAnimType? = null,
-        extraConfig: AnimExtraConfig? = null,
-        onPlayStart: (() -> Unit)? = null,
-        onPlayEnd: (() -> Unit)? = null,
-        onPlayError: ((errorCode: String) -> Unit)? = null,
-    ) {
-        val listener = if (onPlayStart != null || onPlayEnd != null || onPlayError != null) {
-            object : IWeAnimPlayListener {
-                override fun onPlayStart() {
-                    onPlayStart?.invoke()
-                }
-
-                override fun onPlayEnd() {
-                    onPlayEnd?.invoke()
-                }
-
-                override fun onPlayError(errorCode: String) {
-                    onPlayError?.invoke(errorCode)
-                }
-            }
-        } else {
-            null
-        }
-
-        setUrl(url, animType, extraConfig, listener)
-    }
-
-
-    fun setUrl(
-        url: String,
-        animType: EffectAnimType? = null,
-        extraConfig: AnimExtraConfig? = null,
-        listener: IWeAnimPlayListener? = null
-    ) {
-        Log.d(TAG, "hashCode:${hashCode()}, setUrl, url: $url")
-
-        this.path = url
-        this.pathType = PathType.URL
-        this.animType = animType
-        this.extraConfig = extraConfig
-        this.listener = listener
-
-        var finalAnimType = animType
-        if (animType == null) {
-            //未指定animType,根据后缀判断
-            finalAnimType = getEffectAnimTypeBySuffix(url)
-        }
-        if (finalAnimType == null) {
-            stopPlay()
-            gone()
-            return
-        }
-        when {
-            finalAnimType == EffectAnimType.SVGA -> {
-                playSVGA(url, PathType.URL, extraConfig, listener)
-            }
-
-            finalAnimType == EffectAnimType.MP4 && !TCEffectManager.isTcEffectEnable() -> {
-                downloadEffect(url) { effectSavePath ->
-                    if (effectSavePath.isNullOrEmpty()) {
-                        gone()
-                        return@downloadEffect
-                    }
-                    playVapMp4File(effectSavePath, extraConfig, listener)
-                }
-            }
-
-            finalAnimType == EffectAnimType.MP4 || finalAnimType == EffectAnimType.TC -> {
-                downloadEffect(url) { effectSavePath ->
-                    if (effectSavePath.isNullOrEmpty()) {
-                        gone()
-                        return@downloadEffect
-                    }
-                    playMp4File(effectSavePath, extraConfig, listener)
-                }
-            }
-
-            else -> {
-                //其他暂不支持
-                stopPlay()
-                gone()
-            }
-        }
-    }
-
-    private fun downloadEffect(url: String, onResult: (path: String?) -> Unit) {
-        cancelDownloadJob()
-        downloadJob = launch {
-            var effectSavePath: String? = null
-            val downloadRlt = downloadManager.downloadResource(
-                FilePath.effectPath ?: FilePath.backupEffectPath,
-                url,
-                TaskPriority.HIGH
-            )
-            if (downloadRlt is Rlt.Success) {
-                effectSavePath = downloadRlt.data
-            }
-            withContext(Dispatcher.UI) {
-                if (effectSavePath.isNullOrEmpty()) {
-                    onResult.invoke(null)
-                    return@withContext
-                }
-                onResult.invoke(effectSavePath)
-            }
-        }
-    }
-
-    fun startPlay() {
-        svgaAnimView?.startAnimation()
-        tcAnimView?.resume()
-        if (vapAnimView?.isVisible == true) {
-            //vap不支持恢复播放,额外处理
-            val path = path
-            val pathType = pathType
-            if (path != null && pathType != null) {
-                when (pathType) {
-                    PathType.ASSERT -> setAsset(path, EffectAnimType.MP4, extraConfig, listener)
-                    PathType.FILE -> setFile(path, EffectAnimType.MP4, extraConfig, listener)
-                    PathType.URL -> setUrl(path, EffectAnimType.MP4, extraConfig, listener)
-                }
-            }
-        }
-    }
-
-    fun pausePlay() {
-        svgaAnimView?.pauseAnimation()
-        tcAnimView?.pause()
-        //vap不支持暂停,直接停止
-        vapAnimView?.stopPlay()
-    }
-
-    fun stopPlay() {
-        this.path = null
-        this.pathType = null
-        this.animType = null
-        this.extraConfig = null
-        this.listener= null
-
-        svgaAnimView?.apply {
-            stopAnimation(true)
-            setImageDrawable(null)
-        }
-        cancelDownloadJob()
-        tcAnimView?.stopPlay(true)
-        vapAnimView?.stopPlay()
-    }
-
-    private fun playSVGA(
-        path: String,
-        pathType: PathType,
-        extraConfig: AnimExtraConfig?,
-        listener: IWeAnimPlayListener?
-    ) {
-        inflateAnimView(AnimViewType.SVGA)
-        show()
-        autoPlay = extraConfig?.autoPlay ?: autoPlay
-        svgaAnimView?.apply {
-            setRatio(extraConfig?.ratio ?: 1f)
-            val loopCnt = extraConfig?.loop ?: 0
-            //svga循环次数要特殊处理 <0代表无限循环,大于等于0需要+1
-            loops = if (loopCnt >= 0) loopCnt + 1 else loopCnt
-            extraConfig?.svgaExtraConfig?.let {
-                clearsAfterDetached = it.clearsAfterDetached
-                fillMode = it.fillMode
-            }
-            setAutoPlay(autoPlay)
-            extraConfig?.scaleType?.let {
-                scaleType = it
-            }
-        }
-        val dynamicEntitySupplier = extraConfig?.svgaExtraConfig?.dynamicEntitySupplier
-        var controllerListener: ControllerListener? = null
-        if (listener != null) {
-            controllerListener = object : ControllerListener {
-                override fun onBeforeImageSet(id: String?, svgaInfo: SvgaInfo?) {
-                    super.onBeforeImageSet(id, svgaInfo)
-                    listener.onGetSvgaInfo(svgaInfo)
-                    listener.onPlayStart()
-                }
-
-                override fun onFinalImageSet(id: String?, svgaInfo: SvgaInfo?) {
-                    super.onFinalImageSet(id, svgaInfo)
-                    listener.onPlayEnd()
-                }
-
-                override fun onFailure(id: String?, throwable: Throwable?) {
-                    super.onFailure(id, throwable)
-                    listener.onPlayError(id ?: "")
-                }
-            }
-        }
-        svgaAnimView?.volume = if (extraConfig?.mute == true) 0f else 1f
-        when (pathType) {
-            PathType.FILE -> {
-                svgaAnimView?.setFile(File(path), dynamicEntitySupplier, controllerListener)
-            }
-
-            PathType.ASSERT -> {
-                svgaAnimView?.setAsset(path, dynamicEntitySupplier, controllerListener)
-            }
-
-            PathType.URL -> {
-                svgaAnimView?.setUrl(path, dynamicEntitySupplier, controllerListener)
-            }
-
-            else -> {
-                //Ntd.
-            }
-        }
-    }
-
-    private fun playMp4File(
-        filePath: String,
-        extraConfig: AnimExtraConfig?,
-        listener: IWeAnimPlayListener?
-    ) {
-        inflateAnimView(AnimViewType.TC)
-        show()
-        setRatio(extraConfig?.ratio ?: 1f)
-        tcAnimView?.setPlayListener(object : TCEffectAnimView.IAnimPlayListener {
-            override fun onPlayStart() {
-                runOnUiThread {
-                    listener?.onPlayStart()
-                    listener?.onGetTcInfo(tcAnimView?.tcAnimInfo)
-                }
-            }
-
-            override fun onPlayEnd() {
-                runOnUiThread {
-                    listener?.onPlayEnd()
-                }
-            }
-
-            override fun onPlayError(p0: Int) {
-                runOnUiThread {
-                    listener?.onPlayError(p0.toString())
-                }
-            }
-
-            override fun onPlayEvent(p0: Int, p1: Bundle?) {
-
-            }
-        })
-        extraConfig?.tcExtraConfig?.tcFetchResource?.let {
-            tcAnimView?.setFetchResource(it)
-        }
-        val loopCnt = extraConfig?.loop ?: 0
-        //tc循环次数要特殊处理 <=0代表无限循环
-        val loops = when {
-            loopCnt < 0 -> {
-                INFINITE_LOOP
-            }
-            loopCnt == 0 -> {
-                1
-            }
-            else -> {
-                loopCnt
-            }
-        }
-        tcAnimView?.setScaleType(
-            getTCScaleTypeBy(
-                extraConfig?.scaleType ?: ImageView.ScaleType.FIT_CENTER
-            )
-        )
-        tcAnimView?.setLoopCount(loops)
-        tcAnimView?.setMute(extraConfig?.mute == true)
-        tcAnimView?.startPlay(filePath)
-        autoPlay = extraConfig?.autoPlay ?: autoPlay
-        if (!autoPlay) {
-            tcAnimView?.post {
-                tcAnimView?.pause()
-            }
-        }
-    }
-
-    private fun playVapMp4File(
-        filePath: String,
-        extraConfig: AnimExtraConfig?,
-        listener: IWeAnimPlayListener?
-    ) {
-        inflateAnimView(AnimViewType.VAP)
-        show()
-        setRatio(extraConfig?.ratio ?: 1f)
-        vapAnimView?.setAnimListener(object : IAnimListener {
-            override fun onVideoConfigReady(config: AnimConfig): Boolean {
-                runOnUiThread{
-                    listener?.onGetVapInfo(config)
-                }
-                return super.onVideoConfigReady(config)
-            }
-            override fun onFailed(errorType: Int, errorMsg: String?) {
-                runOnUiThread{
-                    listener?.onPlayError("errorType:$errorType, errorMsg:$errorMsg")
-                }
-            }
-
-            override fun onVideoComplete() {
-                runOnUiThread{
-                    listener?.onPlayEnd()
-                }
-            }
-
-            override fun onVideoDestroy() {}
-
-            override fun onVideoRender(frameIndex: Int, config: AnimConfig?) {}
-
-            override fun onVideoStart() {
-                runOnUiThread{
-                    listener?.onPlayStart()
-                }
-            }
-
-        })
-        extraConfig?.vapExtraConfig?.vapFetchResource?.let {
-            vapAnimView?.setFetchResource(it)
-        }
-        val loopCnt = extraConfig?.loop ?: 0
-        //vap循环次数要特殊处理 <=0代表无限循环
-        val loops = when {
-            loopCnt < 0 -> {
-                Int.MAX_VALUE
-            }
-
-            loopCnt == 0 -> {
-                1
-            }
-
-            else -> {
-                loopCnt
-            }
-        }
-        ScaleType.getScaleTypeBy(extraConfig?.scaleType ?: ImageView.ScaleType.FIT_CENTER)?.apply {
-            vapAnimView?.setScaleType(this)
-        }
-        vapAnimView?.setLoop(loops)
-        vapAnimView?.setMute(extraConfig?.mute == true)
-        autoPlay = extraConfig?.autoPlay ?: autoPlay
-        if (autoPlay) {
-            vapAnimView?.startPlay(File(filePath))
-        }
-    }
-
-    private fun getTCScaleTypeBy(type: ImageView.ScaleType): TCEffectPlayerConstant.ScaleType? {
-        return when (type) {
-            ImageView.ScaleType.MATRIX -> null
-            ImageView.ScaleType.FIT_XY -> TCEffectPlayerConstant.ScaleType.FIT_XY
-            ImageView.ScaleType.FIT_START -> null
-            ImageView.ScaleType.FIT_CENTER -> TCEffectPlayerConstant.ScaleType.FIT_CENTER
-            ImageView.ScaleType.FIT_END -> null
-            ImageView.ScaleType.CENTER -> null
-            ImageView.ScaleType.CENTER_CROP -> TCEffectPlayerConstant.ScaleType.CENTER_CROP
-            ImageView.ScaleType.CENTER_INSIDE -> null
-        }
-    }
-
-    fun setRatio(ratio: Float) {
-        if (width == 0 || height == 0) {
-            // 视图尚未布局完成,添加布局监听器
-            viewTreeObserver.addOnGlobalLayoutListener(object :
-                ViewTreeObserver.OnGlobalLayoutListener {
-                override fun onGlobalLayout() {
-                    val actualWidth = width
-                    val actualHeight = height
-
-                    // 可能前面的回调还没有完成布局,拿不到宽高,这时无需处理,也不要removeOnGlobalLayoutListener,否则会得不到实际宽高
-                    if (actualWidth == 0 && actualHeight == 0) {
-                        return
-                    }
-
-                    viewTreeObserver.removeOnGlobalLayoutListener(this)
-                    updateViewSize(actualWidth, actualHeight, ratio)
-                }
-            })
-            return
-        }
-        // 视图已布局完成,直接获取实际宽高
-        updateViewSize(width, height, ratio)
-    }
-
-    /**
-     * 设置视图的缩放大小
-     */
-    private fun updateViewSize(width: Int, height: Int, ratio: Float) {
-        if (originWidth == 0) {
-            originWidth = width
-        }
-        if (originHeight == 0) {
-            originHeight = height
-        }
-
-        val lp = layoutParams
-        lp.width = (originWidth * ratio).toInt()
-        lp.height = (originHeight * ratio).toInt()
-        layoutParams = lp
-    }
-
-    /**
-     * 预加载资源
-     */
-    fun preloadAssetFile(assetName: String): String {
-        return copyAssetToCache(assetName)
-    }
-
-    private fun copyAssetToCache(assetName: String): String {
-        createOrExistsDir(FilePath.effectPath)
-        val cacheFile = File(FilePath.effectPath, assetName)
-        if (!cacheFile.exists()) {
-            AppUtil.appContext.assets.open(assetName).use { inputStream ->
-                FileOutputStream(cacheFile).use { outputStream ->
-                    inputStream.copyTo(outputStream)
-                }
-            }
-        }
-        return cacheFile.absolutePath
-    }
-
-    private fun getEffectAnimTypeBySuffix(name: String): EffectAnimType? {
-        return when {
-            isSVGAImage(name) -> EffectAnimType.SVGA
-            isMP4(name) && !TCEffectManager.isTcEffectEnable() -> EffectAnimType.MP4
-            (isMP4(name) && TCEffectManager.isTcEffectEnable()) || isTCMP4(name) -> EffectAnimType.TC
-            else -> null
-        }
-    }
-
-    private fun inflateAnimView(type: AnimViewType) {
-        when (type) {
-            AnimViewType.SVGA -> {
-                if (svgaAnimView?.parent == null) {
-                    svgaAnimView = WenextSvgaView(context)
-                    addView(svgaAnimView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
-                    svgaAnimView?.show()
-                }
-                removeAnimView(AnimViewType.TC)
-                removeAnimView(AnimViewType.VAP)
-            }
-            AnimViewType.TC -> {
-                if (tcAnimView?.parent == null) {
-                    tcAnimView = TCEffectAnimView(context)
-                    val tceConfigExtendMap: HashMap<String, Any> = hashMapOf(
-                        TCEffectPlayerConstant.PARAM_OPTIONAL_STRING_EXTRA_LICENSE_KEY to TCEffectManager.getOldLicense()
-                    )
-                    tcAnimView?.setConfig(
-                        TCEffectConfig.Builder().setExtendMapParams(tceConfigExtendMap).build()
-                    )
-                    addView(tcAnimView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
-                    tcAnimView?.show()
-                }
-                removeAnimView(AnimViewType.SVGA)
-                removeAnimView(AnimViewType.VAP)
-            }
-            AnimViewType.VAP -> {
-                if (vapAnimView?.parent == null) {
-                    vapAnimView = AnimView(context)
-                    addView(vapAnimView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
-                    vapAnimView?.show()
-                }
-                removeAnimView(AnimViewType.SVGA)
-                removeAnimView(AnimViewType.TC)
-            }
-        }
-    }
-
-    private fun removeAnimView(type: AnimViewType) {
-        when (type) {
-            AnimViewType.SVGA -> {
-                svgaAnimView?.let {
-                    it.stopAnimation(true)
-                    removeView(it)
-                }
-            }
-            AnimViewType.TC -> {
-                tcAnimView?.let {
-                    it.stopPlay(true)
-                    removeView(it)
-                }
-            }
-            AnimViewType.VAP -> {
-                vapAnimView?.let {
-                    it.stopPlay()
-                    removeView(it)
-                }
-            }
-        }
-    }
-
-    fun cancelDownloadJob() {
-        downloadJob?.cancel()
-        downloadJob = null
-    }
-
-    override fun onAttachedToWindow() {
-        super.onAttachedToWindow()
-        Log.d(TAG, "hashCode:${hashCode()}, onAttachedToWindow")
-        if (tcAnimView?.isVisible == true || vapAnimView?.isVisible == true) {
-            val path = path
-            val pathType = pathType
-            if (path != null && pathType != null) {
-                Log.d(TAG, "hashCode:${hashCode()}, onAttachedToWindow, path:${path}, pathType:${pathType}, animType:${animType}")
-                when (pathType) {
-                    PathType.ASSERT -> setAsset(path, animType, extraConfig, listener)
-                    PathType.FILE -> setFile(path, animType, extraConfig, listener)
-                    PathType.URL -> setUrl(path, animType, extraConfig, listener)
-                }
-            }
-        }
-    }
-
-    override fun onDetachedFromWindow() {
-        super.onDetachedFromWindow()
-        Log.d(TAG, "hashCode:${hashCode()}, onDetachedFromWindow")
-        cancelDownloadJob()
-    }
-
-    fun setImageMatrix(matrix: Matrix) {
-        svgaAnimView?.imageMatrix = matrix
-    }
-
-    fun isResourceReady(): Boolean {
-        return path.isNullOrEmpty().not()
-    }
-
-    interface IWeAnimPlayListener {
-        fun onGetTcInfo(tcAnimInfo: TCEffectAnimInfo?) {}
-        fun onGetVapInfo(vapInfo: AnimConfig) {}
-        fun onGetSvgaInfo(svgaInfo: SvgaInfo?) {}
-        fun onPlayStart() {}
-        fun onPlayEnd() {}
-        fun onPlayError(errorCode: String) {}
-    }
-
-    companion object {
-        private const val TAG = "WeAnimView"
-    }
-
-    enum class AnimViewType {
-        SVGA,
-        VAP,
-        TC
-    }
-}

+ 0 - 289
app/src/main/java/com/adealink/weparty/exoplayer/ExoPlayerHelper.kt

@@ -1,289 +0,0 @@
-package com.adealink.weparty.exoplayer
-
-import android.os.Build
-import android.view.View
-import androidx.annotation.OptIn
-import androidx.lifecycle.DefaultLifecycleObserver
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleOwner
-import androidx.media3.common.MediaItem
-import androidx.media3.common.PlaybackException
-import androidx.media3.common.Player
-import androidx.media3.common.Player.STATE_BUFFERING
-import androidx.media3.common.Player.STATE_READY
-import androidx.media3.common.util.UnstableApi
-import androidx.media3.database.StandaloneDatabaseProvider
-import androidx.media3.datasource.DefaultDataSource
-import androidx.media3.datasource.cache.Cache
-import androidx.media3.datasource.cache.CacheDataSource
-import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
-import androidx.media3.datasource.cache.SimpleCache
-import androidx.media3.exoplayer.DefaultRenderersFactory
-import androidx.media3.exoplayer.ExoPlayer
-import androidx.media3.exoplayer.source.MediaSource
-import androidx.media3.exoplayer.source.ProgressiveMediaSource
-import androidx.media3.ui.PlayerView
-import com.adealink.frame.log.Log
-import com.adealink.frame.util.md5
-import com.adealink.weparty.storage.file.FilePath
-import java.io.File
-import java.lang.ref.WeakReference
-
-@UnstableApi
-class ExoPlayerHelper : DefaultLifecycleObserver {
-
-    private var playerViewRef: WeakReference<View?> = WeakReference(null)
-    private val playerView: View?
-        get() {
-            return playerViewRef.get()
-        }
-    private var uri: String? = null
-    private var scaleMode: Int? = null
-    private var repeatMode = Player.REPEAT_MODE_OFF
-    private var playWhenReady = true
-    private var volume = 1f
-    private var player: ExoPlayer? = null
-    private var cache: Cache? = null
-
-    var doOnReadyCallback: (() -> Unit)? = null
-    var onErrorCallback: ((error: PlaybackException) -> Unit)? = null
-
-    //Player初始化回调
-    private var onPlayerInit: ((player: Player) -> Unit)? = null
-
-    //缓冲导致的播放暂停
-    private var onPauseWhenBuffering: ((isPlaying: Boolean) -> Unit)? = null
-
-    fun observe(lifecycle: Lifecycle) {
-        lifecycle.addObserver(this)
-    }
-
-    fun unObserve(lifecycle: Lifecycle) {
-        lifecycle.removeObserver(this)
-    }
-
-    fun getPlayer(): ExoPlayer? {
-        return player
-    }
-
-    class Builder(val targetView: View, val onPlayerInit: ((player: Player) -> Unit) ? = null) {
-
-        var uri: String? = null
-        var scaleMode: Int? = null
-        var repeatMode = Player.REPEAT_MODE_OFF
-        var playWhenReady = true
-        private var volume = 1f
-        var doOnReadyCallback: (() -> Unit)? = null
-        var onErrorCallback: ((error: PlaybackException) -> Unit)? = null
-        private var onPauseWhenBuffering: ((isPlaying: Boolean) -> Unit)? = null
-
-        fun uri(uri: String): Builder {
-            this.uri = uri
-            return this
-        }
-
-        fun scaleMode(mode: Int): Builder {
-            this.scaleMode = mode
-            return this
-        }
-
-        fun repeatMode(mode: Int): Builder {
-            this.repeatMode = mode
-            return this
-        }
-
-        fun playWhenReady(playWhenReady: Boolean): Builder {
-            this.playWhenReady = playWhenReady
-            return this
-        }
-
-        fun volume(volume: Float): Builder {
-            this.volume = volume
-            return this
-        }
-
-        fun playListener(
-            doOnReadyCallback: (() -> Unit)? = null,
-            onErrorCallback: ((error: PlaybackException) -> Unit)? = null
-        ): Builder {
-            this.doOnReadyCallback = doOnReadyCallback
-            this.onErrorCallback = onErrorCallback
-            return this
-        }
-
-        fun onPauseWhenBuffering(listener: ((isPlaying: Boolean) -> Unit)?): Builder {
-            this.onPauseWhenBuffering = listener
-            return this
-        }
-
-        fun build(): ExoPlayerHelper {
-            val helper = ExoPlayerHelper().apply {
-                this.playerViewRef = WeakReference(targetView)
-                this.onPlayerInit = this@Builder.onPlayerInit
-
-                this.uri = this@Builder.uri
-                this.scaleMode = this@Builder.scaleMode
-                this.repeatMode = this@Builder.repeatMode
-                this.playWhenReady = this@Builder.playWhenReady
-                this.volume = this@Builder.volume
-                this.doOnReadyCallback = this@Builder.doOnReadyCallback
-                this.onErrorCallback = this@Builder.onErrorCallback
-                this.onPauseWhenBuffering = this@Builder.onPauseWhenBuffering
-            }
-            return helper
-        }
-    }
-
-    @OptIn(UnstableApi::class)
-    private fun initializePlayer() {
-        Log.d(TAG, "initializePlayer")
-        val playerView = (playerView as? PlayerView) ?: return
-        player = ExoPlayer.Builder(playerView.context, DefaultRenderersFactory(playerView.context).setEnableDecoderFallback(true))
-            .build()
-            .also { player ->
-                playerView.player = player
-                uri?.let {
-                    player.setMediaItem(MediaItem.fromUri(it))
-                }
-                scaleMode?.let { mode ->
-                    player.videoScalingMode = mode
-                }
-                player.playWhenReady = playWhenReady
-                player.repeatMode = repeatMode
-                player.volume = volume
-
-                player.addListener(object : Player.Listener {
-                    override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
-                        super.onPlayWhenReadyChanged(playWhenReady, reason)
-                        Log.d(TAG, "onPlayWhenReadyChanged, playWhenReady:$playWhenReady, reason:$reason")
-                    }
-
-                    override fun onIsPlayingChanged(isPlaying: Boolean) {
-                        super.onIsPlayingChanged(isPlaying)
-                        Log.d(TAG, "onIsPlayingChanged, isPlaying:$isPlaying")
-                        when (player.playbackState) {
-                            STATE_BUFFERING -> {
-                                //缓冲中
-                                onPauseWhenBuffering?.invoke(isPlaying)
-                            }
-
-                            else -> {
-                                //缓冲完毕
-                                onPauseWhenBuffering?.invoke(true)
-                            }
-                        }
-                    }
-
-                    override fun onEvents(player: Player, events: Player.Events) {
-                        super.onEvents(player, events)
-                        Log.d(TAG, "onIsPlayingChanged, player:$player, events:$events")
-                    }
-
-                    override fun onPlaybackStateChanged(playbackState: Int) {
-                        Log.d(TAG, "onPlaybackStateChanged, playbackState: $playbackState")
-                        when (playbackState) {
-                            STATE_READY -> {
-                                doOnReadyCallback?.invoke()
-                                doOnReadyCallback = null
-                            }
-                            STATE_BUFFERING -> {
-                                //缓冲中
-                                onPauseWhenBuffering?.invoke(player.isPlaying)
-                            }
-
-                            else -> {
-                                //缓冲完毕
-                                onPauseWhenBuffering?.invoke(true)
-                            }
-                        }
-                    }
-
-                    override fun onPlayerError(error: PlaybackException) {
-                        super.onPlayerError(error)
-                        Log.d(TAG, "onPlayerError, error: $error")
-                        onErrorCallback?.invoke(error)
-                    }
-
-                    override fun onPlayerErrorChanged(error: PlaybackException?) {
-                        super.onPlayerErrorChanged(error)
-                        Log.d(TAG, "onPlayerErrorChanged, error:$error")
-                    }
-
-                })
-
-                player.prepare()
-                onPlayerInit?.invoke(player)
-            }
-    }
-
-    private fun releasePlayer() {
-        Log.d(TAG, "releasePlayer")
-        cache?.release()
-        cache = null
-        player?.release()
-        player = null
-    }
-
-    //----ExoPlayer的生命周期
-    override fun onStart(owner: LifecycleOwner) {
-        Log.d(TAG, "onStart")
-        super.onStart(owner)
-        if (Build.VERSION.SDK_INT >= 24) {
-            initializePlayer()
-        }
-    }
-
-    private fun getCachePath(url: String): String {
-        return "${FilePath.videoPath}${File.separator}${"${url.md5()}.${url.split(".").last()}"}"
-    }
-
-    private fun buildMediaSource(): Pair<Cache, MediaSource>? {
-        val ctx = playerView?.context ?: return null
-        val uriString = uri ?: return null
-
-        //1. 构建缓存文件
-        val cacheFile = File(getCachePath(uriString))
-        //2. 构建缓存实例
-        val cache = SimpleCache(cacheFile, LeastRecentlyUsedCacheEvictor(MAX_CACHE_BYTE), StandaloneDatabaseProvider(ctx))
-        val mediaItem = MediaItem.fromUri(uriString)
-        //3. 构建 DataSourceFactory
-        val cacheDataSourceFactory = CacheDataSource.Factory()
-            .setCache(cache)
-            .setUpstreamDataSourceFactory(DefaultDataSource.Factory(ctx))
-            .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
-        val mediaSource = ProgressiveMediaSource.Factory(cacheDataSourceFactory)
-            .createMediaSource(mediaItem)
-        return Pair(cache, mediaSource)
-    }
-
-    override fun onResume(owner: LifecycleOwner) {
-        Log.d(TAG, "onResume")
-        super.onResume(owner)
-        if ((Build.VERSION.SDK_INT < 24 || player == null)) {
-            initializePlayer()
-        }
-    }
-
-    override fun onPause(owner: LifecycleOwner) {
-        Log.d(TAG, "onPause")
-        super.onPause(owner)
-        if (Build.VERSION.SDK_INT < 24) {
-            releasePlayer()
-        }
-    }
-
-    override fun onStop(owner: LifecycleOwner) {
-        Log.d(TAG, "onStop")
-        super.onStop(owner)
-        if (Build.VERSION.SDK_INT >= 24) {
-            releasePlayer()
-        }
-    }
-
-    companion object {
-        private const val TAG = "ExoPlayerHelper"
-
-        private const val MAX_CACHE_BYTE = 50 * 1024 * 1024L
-    }
-
-}

+ 0 - 2
app/src/main/java/com/adealink/weparty/googleservice/GoogleServiceConfig.kt

@@ -1,8 +1,6 @@
 package com.adealink.weparty.googleservice
 
 import com.adealink.frame.googleservice.IGoogleServiceConfig
-import com.adealink.frame.log.ILog
-import com.adealink.frame.log.Log
 import com.adealink.frame.util.AppUtil
 import com.adealink.weparty.module.account.AccountModule
 import com.adealink.weparty.stat.reportEnterApp

+ 2 - 2
app/src/main/java/com/adealink/weparty/im/IMConfig.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.im
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.imkit.config.IIMConfig
 import com.adealink.frame.util.PackageUtil
 import com.adealink.weparty.BuildConfig
@@ -8,7 +8,7 @@ import com.adealink.weparty.channel.getChannel
 import com.adealink.weparty.module.account.AccountModule
 
 class IMConfig: IIMConfig {
-    override val appKey: String = when(AppBaseInfo.isProdEnv) {
+    override val appKey: String = when(AppBase.isProdEnv) {
         true -> "8w7jv4qb85ruy"
         else -> "vnroth0kv2woo"
     }

+ 17 - 0
app/src/main/java/com/adealink/weparty/image/ImageConfig.kt

@@ -3,8 +3,10 @@ package com.adealink.weparty.image
 import android.content.Context
 import com.adealink.frame.data.json.froJsonErrorNull
 import com.adealink.frame.image.config.IImageConfig
+import com.adealink.frame.image.constant.ImageFetchResultData
 import com.adealink.frame.image.constant.TAG_IMAGE_CONFIG
 import com.adealink.frame.log.Log
+import com.adealink.frame.network.stat.NetMonitorStatEvent
 import com.adealink.frame.util.runOnUiThread
 import com.adealink.weparty.App
 import com.adealink.weparty.config.GlobalConfigType
@@ -35,6 +37,21 @@ class ImageConfig : IImageConfig, IGlobalConfigListener {
         return App.instance.networkService.replaceUrlHost(oldUrl)
     }
 
+    override fun report(data: ImageFetchResultData) {
+        val (url, host, size, duration, protocol, tlsVersion, awsXAmzCfId) = data
+        NetMonitorStatEvent(NetMonitorStatEvent.Action.TRAFFIC)
+            .apply {
+                uri to url
+                this.host to host
+                amount to size
+                this.duration to duration
+                this.protocol to protocol
+                this.tlsVersion to tlsVersion
+                xAmzCfId to awsXAmzCfId
+            }
+            .send()
+    }
+
     //TODO 全量CDN之后以下部分需要被移除,减少判断性能消耗
     private val aliOssHosts = hashSetOf(
         "yoki-resource-cf.wenext.media",

+ 6 - 9
app/src/main/java/com/adealink/weparty/imageselect/selectpreview/SelectPreviewActivity.kt

@@ -2,11 +2,9 @@ package com.adealink.weparty.imageselect.selectpreview
 
 import android.content.Intent
 import android.view.View
-import androidx.annotation.OptIn
-import androidx.media3.common.C
-import androidx.media3.common.Player.REPEAT_MODE_ONE
-import androidx.media3.common.util.UnstableApi
 import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.effect.data.INFINITE_LOOP
+import com.adealink.frame.effect.video.controller.VideoScalingMode
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.router.Router
 import com.adealink.frame.util.onClick
@@ -16,7 +14,6 @@ import com.adealink.weparty.commonui.ext.isGIFImage
 import com.adealink.weparty.commonui.ext.show
 import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.weparty.databinding.ActivitySelectPreviewBinding
-import com.adealink.weparty.exoplayer.ExoPlayerHelper
 import com.adealink.weparty.imageselect.SelectImageRequest.Companion.SOURCE_EDIT_PROFILE_COVER
 import com.adealink.weparty.module.profile.ProfileModule
 import com.adealink.weparty.module.profile.data.SVIPLevel
@@ -87,11 +84,11 @@ class SelectPreviewActivity : BaseActivity() {
         finish()
     }
 
-    @OptIn(UnstableApi::class)
     private fun playVideo(url: String) {
-        ExoPlayerHelper.Builder(binding.videoView).uri(url)
-            .scaleMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING).repeatMode(REPEAT_MODE_ONE)
-            .playWhenReady(true).build().observe(this.lifecycle)
+        binding.videoView.setVideoScalingMode(VideoScalingMode.ScaleToFitWithCropping)
+        binding.videoView.setAutoPlay(true)
+        binding.videoView.setLoopCount(INFINITE_LOOP)
+        binding.videoView.setUri(url)
     }
 
     /**

+ 0 - 27
app/src/main/java/com/adealink/weparty/json/JsonConfig.kt

@@ -1,27 +0,0 @@
-package com.adealink.weparty.json
-
-import com.adealink.frame.data.json.IJsonConfig
-import com.adealink.frame.log.ILog
-import com.adealink.frame.log.Log
-
-/**
- * Created by sunxiaodong on 2021/9/10.
- */
-class JsonConfig : IJsonConfig, ILog {
-
-    override val log: ILog
-        get() = this
-
-    override fun logD(tag: String, msg: String) {
-        Log.d(tag, msg)
-    }
-
-    override fun logI(tag: String, msg: String) {
-        Log.i(tag, msg)
-    }
-
-    override fun logE(tag: String, msg: String, e: Exception?) {
-        Log.e(tag, msg, e)
-    }
-
-}

+ 8 - 5
app/src/main/java/com/adealink/weparty/log/LogConfig.kt

@@ -1,13 +1,20 @@
 package com.adealink.weparty.log
 
 import com.adealink.frame.log.ILogConfig
-import com.adealink.weparty.BuildConfig
+import com.adealink.frame.network.INetworkService
+import com.adealink.frame.oss.IOssService
+import com.adealink.weparty.App
 
 /**
  * Created by sunxiaodong on 2021/6/20.
  */
 class LogConfig : ILogConfig {
 
+    override val networkService: INetworkService
+        get() = App.instance.networkService
+    override val ossService: IOssService
+        get() = App.instance.ossService
+
     override fun stat(tag: String, msg: String) {
 //        LogErrorStatEvent(LogErrorStatEvent.Action.LOG)
 //            .apply {
@@ -16,8 +23,4 @@ class LogConfig : ILogConfig {
 //            }
 //            .send()
     }
-
-    override val isOfficial: Boolean
-        get() = BuildConfig.OFFICIAL
-
 }

+ 0 - 22
app/src/main/java/com/adealink/weparty/log/data/LogData.kt

@@ -1,22 +0,0 @@
-package com.adealink.weparty.log.data
-
-import com.google.gson.annotations.SerializedName
-
-/**
- * Created by sunxiaodong on 2021/8/14.
- */
-data class ReportLogReq(
-    @SerializedName("uid") val uid: Long,
-    @SerializedName("seqid") val seqId: Long = System.currentTimeMillis(),
-)
-
-/**
- * 日志上报通知
- */
-data class ReportLogNotify(@SerializedName("seqId") val seqId: Long)
-
-enum class UploadLogType {
-    TODAY,
-    FIVE_DAY,
-    ALL
-}

+ 0 - 4
app/src/main/java/com/adealink/weparty/log/data/Tags.kt

@@ -1,4 +0,0 @@
-package com.adealink.weparty.log.data
-
-const val TAG_LOG = "tag_log"
-const val TAG_LOG_UPLOAD = "${TAG_LOG}_upload"

+ 0 - 17
app/src/main/java/com/adealink/weparty/log/datasource/remote/LogHttpService.kt

@@ -1,17 +0,0 @@
-package com.adealink.weparty.log.datasource.remote
-
-import com.adealink.frame.base.Rlt
-import com.adealink.frame.network.data.Res
-import com.adealink.weparty.log.data.ReportLogReq
-import retrofit2.http.Body
-import retrofit2.http.POST
-
-/**
- * Created by sunxiaodong on 2021/8/14.
- */
-interface LogHttpService {
-
-    @POST("config/reportUserLog")
-    suspend fun reportLog(@Body req: ReportLogReq): Rlt<Res<Any>>
-
-}

+ 0 - 19
app/src/main/java/com/adealink/weparty/log/manager/ILogManager.kt

@@ -1,19 +0,0 @@
-package com.adealink.weparty.log.manager
-
-import com.adealink.frame.base.Rlt
-import com.adealink.weparty.log.data.UploadLogType
-
-/**
- * Created by sunxiaodong on 2021/8/14.
- */
-interface ILogManager {
-
-    suspend fun reportLog(uid: Long): Rlt<Any>
-
-    suspend fun uploadLog(type: UploadLogType): Rlt<String>
-
-    suspend fun uploadLongString(fileName: String, str: String): Rlt<String>
-
-    fun subscribeReportLogNotify()
-
-}

+ 0 - 311
app/src/main/java/com/adealink/weparty/log/manager/LogManager.kt

@@ -1,311 +0,0 @@
-package com.adealink.weparty.log.manager
-
-import android.text.SpannableStringBuilder
-import com.adealink.frame.base.Rlt
-import com.adealink.frame.coroutine.dispatcher.Dispatcher
-import com.adealink.frame.log.Log
-import com.adealink.frame.log.XLogHelper
-import com.adealink.frame.network.ISocketNotify
-import com.adealink.frame.oss.data.UploadFile
-import com.adealink.weparty.storage.file.FilePath
-import com.adealink.frame.util.PackageUtil
-import com.adealink.frame.util.compress
-import com.adealink.frame.util.createDirByDeleteOldDir
-import com.adealink.frame.util.deleteFiles
-import com.adealink.weparty.App
-import com.adealink.weparty.log.data.ReportLogNotify
-import com.adealink.weparty.log.data.ReportLogReq
-import com.adealink.weparty.log.data.TAG_LOG_UPLOAD
-import com.adealink.weparty.log.data.UploadLogType
-import com.adealink.weparty.log.datasource.remote.LogHttpService
-import com.adealink.weparty.module.account.AccountModule
-import io.rong.imlib.RongIMClient
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.io.File
-import java.text.DateFormat
-import java.text.SimpleDateFormat
-import java.util.*
-import java.util.regex.Pattern
-
-
-/**
- * Created by sunxiaodong on 2021/8/14.
- */
-
-val logManager: ILogManager by lazy { LogManager() }
-
-internal class LogManager : ILogManager,
-    CoroutineScope by CoroutineScope(SupervisorJob() + Dispatcher.WENEXT_THREAD_POOL) {
-
-    private val logHttpService by lazy { App.instance.networkService.getHttpService(LogHttpService::class.java) }
-
-    private val reportLogNotify = object : ISocketNotify<ReportLogNotify> {
-
-        override val uri: String = "REPORT_USERLOG"
-
-        override fun needHandle(data: ReportLogNotify?): Boolean {
-            return data != null
-        }
-
-        override fun onNotify(data: ReportLogNotify) {
-            launch {
-                uploadLog(UploadLogType.ALL)
-            }
-        }
-
-    }
-
-    override fun subscribeReportLogNotify() {
-        App.instance.networkService.subscribeNotify(reportLogNotify)
-    }
-
-    override suspend fun reportLog(uid: Long): Rlt<Any> {
-        return when (val result = logHttpService.reportLog(ReportLogReq(uid))) {
-            is Rlt.Success -> Rlt.Success(Any())
-            is Rlt.Failed -> result
-        }
-    }
-
-    override suspend fun uploadLog(type: UploadLogType): Rlt<String> {
-        return withContext(Dispatcher.WENEXT_THREAD_POOL) {
-            Log.appenderFlush(true)
-
-            uploadTCMediaXLog()
-
-            // 检查融云连接状态和登录状态,如果已登录且融云未连接则上传融云日志
-            val imConnectionStatus = App.instance.imService.getCurrentConnectionStatus()
-            if (AccountModule.isLogin() && imConnectionStatus != RongIMClient.ConnectionStatusListener.ConnectionStatus.CONNECTED) {
-                Log.i(TAG_LOG_UPLOAD, "IM not connected, uploading RongCloud logs")
-                uploadRongCloudLog()
-            }
-            
-            val logFileDir = File(FilePath.logPath)
-            if (!logFileDir.exists()
-                || !logFileDir.isDirectory
-                || logFileDir.listFiles().isNullOrEmpty()
-            ) {
-                return@withContext Rlt.Success("")
-            }
-
-            val zipFileDir = File(FilePath.xlogZipPath)
-            val fileMatch: String = getFileMatch(type)
-            val sdf = SimpleDateFormat("yyMMddHHmm", Locale.ENGLISH)
-            val zipFileNameNoSuffix = "${PackageUtil.getVersionCode()}_${sdf.format(Date())}"
-            val zipFile = File(zipFileDir.absolutePath, "${zipFileNameNoSuffix}.zip")
-            compress(
-                logFileDir.absolutePath,
-                zipFile.absolutePath,
-                null,
-                null,
-                fileMatch
-            )
-            return@withContext when (val result = App.instance.ossService.suspendUploadFile(
-                UploadFile.LocalFile(
-                    zipFile.absolutePath,
-                    UploadFile.FileType.LOG,
-                    zipFileNameNoSuffix
-                )
-            )) {
-                is Rlt.Success -> {
-                    //clear log file
-                    XLogHelper.clearLogFiles()
-                    //clear log zip file
-                    createDirByDeleteOldDir(zipFileDir)
-                    result
-                }
-                is Rlt.Failed -> result
-            }
-        }
-    }
-
-    private suspend fun uploadTCMediaXLog() {
-        withContext(Dispatcher.WENEXT_THREAD_POOL) {
-            val logDirPath = FilePath.tcMediaXLog
-            val logsDir = File(logDirPath)
-            if (!logsDir.exists() || !logsDir.isDirectory) {
-                return@withContext
-            }
-            val dateFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
-            val dayList = mutableListOf<String>()
-            val calendar = Calendar.getInstance()
-            for (i in 0 until 5) {
-                dayList.add(dateFormat.format(calendar.time))
-                calendar.add(Calendar.DAY_OF_YEAR, -1)
-            }
-
-            val logFiles = logsDir.listFiles { file ->
-                dayList.any { date -> file.name.contains(date) }
-            }?.toList() ?: emptyList()
-
-            if (logFiles.isEmpty()) {
-                return@withContext
-            }
-
-            val fileMatchSb = SpannableStringBuilder()
-            dayList.forEachIndexed { index, date ->
-                fileMatchSb.append("(.*")
-                fileMatchSb.append(date)
-                fileMatchSb.append("\\.(xlog|txt)\$)")
-                if (index < dayList.size - 1) {
-                    fileMatchSb.append("|")
-                }
-            }
-
-            val sdf = SimpleDateFormat("yyMMddHHmm", Locale.ENGLISH)
-            val zipFileNameNoSuffix =
-                "${PackageUtil.getVersionCode()}_${sdf.format(Date())}_TCMediaX"
-            val zipFile = File(logsDir.absolutePath, "${zipFileNameNoSuffix}.zip")
-            compress(
-                logsDir.absolutePath,
-                zipFile.absolutePath,
-                null,
-                null,
-                fileMatchSb.toString()
-            )
-            when (App.instance.ossService.suspendUploadFile(
-                UploadFile.LocalFile(
-                    zipFile.absolutePath,
-                    UploadFile.FileType.LOG,
-                    zipFileNameNoSuffix
-                )
-            )) {
-                is Rlt.Success -> {
-                    deleteFiles(zipFile)
-                    logFiles.forEach { f ->
-                        deleteFiles(f)
-                    }
-                }
-                else -> {
-                    deleteFiles(zipFile)
-                }
-            }
-
-        }
-    }
-
-    /**
-     * 上传融云日志
-     */
-    private suspend fun uploadRongCloudLog() {
-        withContext(Dispatcher.WENEXT_THREAD_POOL) {
-            val rongCloudLogDir = App.instance.imService.getRongCloudLogDir()
-            val logsDir = File(rongCloudLogDir)
-
-            if (!logsDir.exists() || !logsDir.isDirectory) {
-                Log.w(TAG_LOG_UPLOAD, "RongCloud log directory does not exist or is not a directory")
-                return@withContext
-            }
-
-            val logFiles = logsDir.listFiles()?.toList() ?: emptyList()
-
-            if (logFiles.isEmpty()) {
-                Log.w(TAG_LOG_UPLOAD, "No files found in RongCloud log directory")
-                return@withContext
-            }
-
-            Log.d(TAG_LOG_UPLOAD, "Found ${logFiles.size} files in RongCloud log directory")
-
-            val sdf = SimpleDateFormat("yyMMddHHmm", Locale.ENGLISH)
-            val zipFileNameNoSuffix = "${PackageUtil.getVersionCode()}_${sdf.format(Date())}_RongCloud"
-            val zipFile = File(logsDir.parent, "${zipFileNameNoSuffix}.zip")
-
-            // 压缩整个融云日志目录
-            compress(
-                logsDir.absolutePath,
-                zipFile.absolutePath,
-                null,
-                null,
-                ""  // 空字符串表示压缩所有文件
-            )
-
-            if (!zipFile.exists()) {
-                Log.e(TAG_LOG_UPLOAD, "Failed to create RongCloud log zip file")
-                return@withContext
-            }
-
-            // 上传压缩文件
-            when (val result = App.instance.ossService.suspendUploadFile(
-                UploadFile.LocalFile(
-                    zipFile.absolutePath,
-                    UploadFile.FileType.LOG,
-                    zipFileNameNoSuffix
-                )
-            )) {
-                is Rlt.Success -> {
-                    Log.d(TAG_LOG_UPLOAD, "RongCloud log uploaded successfully: ${result.data}")
-                    deleteFiles(zipFile)
-                }
-                is Rlt.Failed -> {
-                    Log.e(TAG_LOG_UPLOAD, "Failed to upload RongCloud log: ${result.error}")
-                    deleteFiles(zipFile)
-                }
-            }
-        }
-    }
-
-
-    override suspend fun uploadLongString(
-        fileName: String,
-        str: String,
-    ): Rlt<String> {
-        return withContext(Dispatcher.WENEXT_THREAD_POOL) {
-            return@withContext App.instance.ossService.suspendUploadFile(
-                UploadFile.ByteFile(
-                    bytes = str.toByteArray(),
-                    fileType = UploadFile.FileType.LONG_STRING,
-                    public = true,
-                    fileName = fileName
-                )
-            )
-        }
-    }
-
-    private fun getFileMatch(uploadLogType: UploadLogType): String {
-        when (uploadLogType) {
-            UploadLogType.ALL -> {
-                return ""
-            }
-            UploadLogType.FIVE_DAY -> {
-                val dayList = mutableListOf<Date>()
-                val todayDate = Date(System.currentTimeMillis())
-                dayList.add(todayDate)
-                val calendar = Calendar.getInstance()
-                calendar.time = todayDate
-                for (i in 1..4) {
-                    calendar.add(Calendar.DAY_OF_MONTH, -1)
-                    dayList.add(calendar.time)
-                }
-                val dateFormat: DateFormat = SimpleDateFormat("yyyyMMdd", Locale.ENGLISH)
-                val sb = SpannableStringBuilder()
-                dayList.forEachIndexed { index, date ->
-                    sb.append("(.*")
-                    sb.append(dateFormat.format(date))
-                    sb.append(".*")
-                    sb.append("\\.(xlog|clog)\$)")
-                    if (index < dayList.size - 1) {
-                        sb.append("|")
-                    }
-                }
-                return sb.toString()
-            }
-            else -> {
-                val time = System.currentTimeMillis()
-                val date = Date(time)
-                val dateFormat: DateFormat = SimpleDateFormat("yyyyMMdd", Locale.ENGLISH)
-                val curDate = dateFormat.format(date)
-                val dateNumber = curDate.substring(curDate.length - 1)
-                val dateMatch = "[0-9]"
-                val pattern = Pattern.compile(dateMatch)
-                val cur = Integer.decode(dateNumber)
-                if (!pattern.matcher(dateNumber).matches()) {
-                    return ""
-                }
-                return ".*\\d[$cur]\\.*.(xlog|clog)$"
-            }
-        }
-    }
-
-}

+ 0 - 32
app/src/main/java/com/adealink/weparty/log/viewmodel/LogViewModel.kt

@@ -1,32 +0,0 @@
-package com.adealink.weparty.log.viewmodel
-
-import androidx.lifecycle.LiveData
-import com.adealink.frame.base.Rlt
-import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
-import com.adealink.frame.mvvm.viewmodel.BaseViewModel
-import com.adealink.weparty.log.data.UploadLogType
-import com.adealink.weparty.log.manager.logManager
-import kotlinx.coroutines.launch
-
-/**
- * Created by sunxiaodong on 2021/8/14.
- */
-class LogViewModel : BaseViewModel() {
-
-    fun reportLog(uid: Long): LiveData<Rlt<Any>> {
-        val liveData = OnceMutableLiveData<Rlt<Any>>()
-        viewModelScope.launch {
-            liveData.send(logManager.reportLog(uid))
-        }
-        return liveData
-    }
-
-    fun uploadLog(type: UploadLogType): LiveData<Rlt<String>> {
-        val liveData = OnceMutableLiveData<Rlt<String>>()
-        viewModelScope.launch {
-            liveData.send(logManager.uploadLog(type))
-        }
-        return liveData
-    }
-
-}

+ 24 - 0
app/src/main/java/com/adealink/weparty/log/viewmodel/LogViewModelFactory.kt

@@ -0,0 +1,24 @@
+package com.adealink.weparty.log.viewmodel
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.adealink.frame.log.viewmodel.LogViewModel
+import com.adealink.weparty.App
+
+/**
+ * Created by sunxiaodong on 2025/9/1.
+ */
+@Suppress("UNCHECKED_CAST")
+class LogViewModelFactory: ViewModelProvider.NewInstanceFactory() {
+
+    override fun <T : ViewModel> create(modelClass: Class<T>): T {
+        return with(modelClass) {
+            when {
+                isAssignableFrom(LogViewModel::class.java) -> LogViewModel(App.instance.logService)
+                else ->
+                    throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
+            } as T
+        }
+    }
+
+}

+ 33 - 11
app/src/main/java/com/adealink/weparty/media/MediaConfig.kt

@@ -1,14 +1,19 @@
 package com.adealink.weparty.media
 
 import android.content.Context
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.media.config.IMediaConfig
 import com.adealink.frame.media.data.RtcType
-import com.adealink.weparty.storage.file.FilePath
+import com.adealink.frame.media.rtc.IRtcCallback
+import com.adealink.frame.media.rtc.IRtcEngine
+import com.adealink.frame.media.rtc.RtcConfig
+import com.adealink.frame.storage.file.rtcLogPath
 import com.adealink.weparty.App
 import com.adealink.weparty.BuildConfig
 import com.adealink.weparty.module.room.RoomModule
+import com.wenext.agorartc.AgoraRtcEngine
+import com.wenext.trtcpro.TRtcProEngine
 
 /**
  * Created by sunxiaodong on 2021/7/14.
@@ -19,16 +24,33 @@ object MediaConfig : IMediaConfig {
         get() = App.instance
     override val lowBitrate: Boolean
         get() = false
-    override val mediaPath: String
-        get() = FilePath.logPath
-    override val agoraAppId: String
-        get() = BuildConfig.AGORA_APP_ID
-    override val tRtcAppId: Int
-        get() = if (AppBaseInfo.isProdEnv) {
-            BuildConfig.TRTC_APP_ID
-        } else {
-            BuildConfig.TRTC_APP_ID_DEBUG
+
+    override fun createRtcEngine(rtcType: RtcType, callback: IRtcCallback): IRtcEngine? {
+        val rtcEngine = when (rtcType) {
+            RtcType.AGORA_RTC -> {
+                val appId = if (AppBase.isProdEnv) {
+                    BuildConfig.AGORA_APP_ID
+                } else {
+                    BuildConfig.AGORA_APP_ID
+                }
+                AgoraRtcEngine(RtcConfig(appId, context, rtcLogPath), callback)
+            }
+
+            RtcType.T_RTC -> {
+                val appId = if (AppBase.isProdEnv) {
+                    BuildConfig.TRTC_APP_ID
+                } else {
+                    BuildConfig.TRTC_APP_ID_DEBUG
+                }
+                TRtcProEngine(RtcConfig(appId.toString(), context, rtcLogPath), callback)
+            }
+
+            RtcType.VOLC_RTC -> null
+
+            RtcType.ZEGO_RTC -> null
         }
+        return rtcEngine
+    }
 
     override suspend fun getChannelToken(channel: String, rtcType: RtcType): Rlt<String> {
         return RoomModule.getChannelToken(channel, rtcType)

+ 3 - 3
app/src/main/java/com/adealink/weparty/module/call/CallConfig.kt

@@ -1,19 +1,19 @@
 package com.adealink.weparty.module.call
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.weparty.BuildConfig
 
 object CallConfig {
 
     val APP_ID: Int
-        get() = if (AppBaseInfo.isProdEnv) {
+        get() = if (AppBase.isProdEnv) {
             BuildConfig.TRTC_APP_ID
         } else {
             BuildConfig.TRTC_APP_ID_DEBUG
         }
 
     val SECRET_KEY: String
-        get() = if (AppBaseInfo.isProdEnv) {
+        get() = if (AppBase.isProdEnv) {
             BuildConfig.TRTC_SECRET_KEY
         } else {
             BuildConfig.TRTC_SECRET_KEY_DEBUG

+ 3 - 3
app/src/main/java/com/adealink/weparty/module/call/match/data/CallMatchData.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.module.call.match.data
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.util.PackageUtil
 import com.adealink.weparty.module.profile.data.UserInfo
 import com.adealink.weparty.module.profile.tags.data.UserLabel
@@ -36,7 +36,7 @@ data class CallMatchReq(
     @SerializedName("newDeviceId") val newDeviceId: String = "",
     @SerializedName("matchType") val matchType: Int = MatchType.VOICE_CHAT.type,
     @SerializedName("paidMatch") val paid: Boolean = false,
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("clientVersion") val clientVersion: Int = PackageUtil.getVersionCode(),
 )
 
@@ -103,7 +103,7 @@ data class CallTopicsRes(
 data class TakeMatchOrderReq(
     @SerializedName("matchOrderId") val orderId: String,
     @SerializedName("takeOrderUserType") val userType: Int,
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("clientVersion") val clientVersion: Int = PackageUtil.getVersionCode(),
 )
 

+ 8 - 36
app/src/main/java/com/adealink/weparty/module/entereffect/effect/CarEffectView.kt

@@ -11,31 +11,28 @@ import android.view.View
 import android.view.ViewGroup
 import android.view.animation.DecelerateInterpolator
 import android.widget.FrameLayout
+import android.widget.ImageView
 import androidx.annotation.Keep
 import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.base.fastLazy
 import com.adealink.frame.effect.data.ERROR_ENTITY_NULL
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.frame.effect.data.IEffectEntity
 import com.adealink.frame.effect.listener.IPlayListener
-import com.adealink.frame.effect.svga.data.PathType
-import com.adealink.frame.effect.svga.data.SVGAEffectEntity
-import com.adealink.frame.effect.video.data.VideoEffectEntity
 import com.adealink.frame.effect.view.EffectView
 import com.adealink.frame.effect.view.IEffectView
+import com.adealink.frame.effect.view.WeEffectEntity
 import com.adealink.frame.log.Log
-import com.adealink.frame.tceffect.effect.data.TCEffectEntity
 import com.adealink.frame.util.DisplayUtil
 import com.adealink.weparty.R
 import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.commonui.ext.gone
 import com.adealink.weparty.commonui.ext.show
-import com.adealink.weparty.effect.EffectAnimType
 import com.adealink.weparty.module.entereffect.data.CarBannerType
 import com.adealink.weparty.module.entereffect.effect.data.CarEffectEntity
 import com.adealink.weparty.module.entereffect.view.CarCustomizedUserView
 import com.adealink.weparty.module.entereffect.view.CoupleEnterBannerView
 import com.adealink.weparty.module.entereffect.view.UserEnterBannerView
-import com.tencent.qgame.animplayer.util.ScaleType as VIDEO_SCALE_TYPE
 
 @Keep
 class CarEffectView @JvmOverloads constructor(
@@ -450,41 +447,16 @@ class CarEffectView @JvmOverloads constructor(
 
         effectView.play()
         when (entity.animType) {
-            EffectAnimType.SVGA -> {
+            EffectAnimType.SVGA, EffectAnimType.MP4, EffectAnimType.TC -> {
                 effectView.add(
-                    SVGAEffectEntity(
+                    WeEffectEntity(
                         path = carPath,
-                        pathType = PathType.FILE,
-                        scaleType = entity.scaleType,
-                        loop = entity.loop,
-                        playListener = playListener
-                    )
-                )
-            }
-
-            EffectAnimType.MP4 -> {
-                effectView.add(
-                    VideoEffectEntity(
-                        path = carPath,
-                        height = ViewGroup.LayoutParams.WRAP_CONTENT,
                         mute = carEntity.mute,
-                        loop = entity.loop,
-                        scaleType = VIDEO_SCALE_TYPE.getScaleTypeBy(entity.scaleType)
-                            ?: VIDEO_SCALE_TYPE.CENTER_CROP,
-                        playListener = playListener,
-                    )
-                )
-            }
-
-            EffectAnimType.TC -> {
-                effectView.add(
-                    TCEffectEntity(
-                        path = carPath,
+                        height = if (entity.animType == EffectAnimType.SVGA) null else ViewGroup.LayoutParams.WRAP_CONTENT,
                         effectUrl = entity.effectUrl,
-                        height = ViewGroup.LayoutParams.WRAP_CONTENT,
-                        playListener = playListener,
-                        mute = carEntity.mute,
+                        scaleType = ImageView.ScaleType.CENTER_CROP,
                         loop = entity.loop,
+                        playListener = playListener
                     )
                 )
             }

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/entereffect/effect/data/CarEffectEntity.kt

@@ -6,7 +6,7 @@ import android.widget.ImageView
 import com.adealink.frame.effect.data.IEffectEntity
 import com.adealink.frame.effect.data.defaultPriority
 import com.adealink.frame.effect.listener.IPlayListener
-import com.adealink.weparty.effect.EffectAnimType
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.weparty.module.entereffect.data.CarBannerType
 import com.adealink.weparty.module.entereffect.data.RoomUserEnterAttr
 import com.adealink.weparty.module.entereffect.effect.CarEffectView

+ 22 - 16
app/src/main/java/com/adealink/weparty/module/entereffect/view/CarCustomizedUserView.kt

@@ -3,18 +3,20 @@ package com.adealink.weparty.module.entereffect.view
 import android.content.Context
 import android.graphics.Color
 import android.util.AttributeSet
+import android.util.Size
 import android.view.LayoutInflater
 import androidx.constraintlayout.widget.ConstraintLayout
 import com.adealink.frame.aab.util.getCompatColor
 import com.adealink.frame.image.imageService
 import com.adealink.weparty.R
 import com.adealink.weparty.databinding.LayoutCarCutomizedUserBinding
-import com.adealink.weparty.effect.AnimExtraConfig
-import com.adealink.weparty.effect.SVGAExtraConfig
+import com.adealink.frame.effect.data.AnimExtraConfig
+import com.adealink.frame.effect.data.DynamicAnimImage
+import com.adealink.frame.effect.data.DynamicAnimText
+import com.adealink.frame.effect.data.IAnimDynamicProvider
 import com.adealink.weparty.module.entereffect.data.RoomUserEnterAttr
 import com.adealink.weparty.module.profile.decorate.data.CarCustomizedConfig
 import com.adealink.weparty.module.profile.view.UserNameTextView.Companion.getDisplayName
-import com.opensource.svgaplayer.SVGADynamicEntity
 
 class CarCustomizedUserView @JvmOverloads constructor(
     context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0,
@@ -22,22 +24,26 @@ class CarCustomizedUserView @JvmOverloads constructor(
     val binding = LayoutCarCutomizedUserBinding.inflate(LayoutInflater.from(context), this, true)
 
     fun updateUserInfo(config: CarCustomizedConfig, userEnterAttr: RoomUserEnterAttr) {
+        binding.nameBgIv.setConfig(AnimExtraConfig(loop = 1))
         binding.nameBgIv.setUrl(
             config.nickBg,
-            extraConfig = AnimExtraConfig(
-                loop = 1,
-                svgaExtraConfig = SVGAExtraConfig(dynamicEntitySupplier = {
-                    SVGADynamicEntity().apply {
-                        val bitmap = imageService.getBitmapSync(
-                            url = userEnterAttr.roomUserInfo?.userInfo?.url
-                                ?: userEnterAttr.userAvatarUrl, 90
-                        )
-                        bitmap?.let {
-                            setDynamicImage(bitmap = it, forKey = "avatar")
+            dynamicProvider = object : IAnimDynamicProvider {
+                override fun provideImage(callback: (Map<String, DynamicAnimImage>?) -> Unit) {
+                    callback(hashMapOf(
+                        "avatar" to DynamicAnimImage {
+                            imageService.getBitmapSync(
+                                url = userEnterAttr.roomUserInfo?.userInfo?.url
+                                    ?: userEnterAttr.userAvatarUrl, Size(90, 90)
+                            )
                         }
-                    }
-                })
-            )
+                    ))
+                }
+
+                override fun provideText(callback: (Map<String, DynamicAnimText>?) -> Unit) {
+                    callback(null)
+                }
+
+            }
         )
         val resultText = getDisplayName(userEnterAttr.uid, userEnterAttr.userNick)
         binding.nameTv.text = resultText

+ 2 - 1
app/src/main/java/com/adealink/weparty/module/entereffect/viewmodel/IEnterEffectViewModel.kt

@@ -3,6 +3,7 @@ package com.adealink.weparty.module.entereffect.viewmodel
 import androidx.lifecycle.LiveData
 import com.adealink.frame.download.task.TaskPriority
 import com.adealink.frame.mvvm.livedata.ExtLiveData
+import com.adealink.frame.storage.file.WeFile
 import com.adealink.weparty.effect.EffectSaveResource
 import com.adealink.weparty.module.entereffect.data.RoomUserEnterAttr
 import com.adealink.weparty.module.profile.decorate.data.RoomGiftLevelUpSpeedUpDecor
@@ -11,7 +12,7 @@ interface IEnterEffectViewModel {
     val roomUserEnterNotifyLD: ExtLiveData<RoomUserEnterAttr>
     val roomSpeedUpConfigLD: LiveData<RoomGiftLevelUpSpeedUpDecor>
     fun getUnhandledUserEnterNotifications(): List<RoomUserEnterAttr>
-    fun downloadResource(url: String, priority: TaskPriority = TaskPriority.NORMAL): LiveData<String?>
+    fun downloadResource(url: String, priority: TaskPriority = TaskPriority.NORMAL): LiveData<WeFile?>
     fun downloadResource(
         oldCarUrl: String,
         newCarUrl: String?,

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/family/data/FamilyData.kt

@@ -7,7 +7,7 @@ import androidx.annotation.StringRes
 import com.adealink.frame.tceffect.TCEffectManager
 import com.adealink.weparty.R
 import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
-import com.adealink.weparty.effect.EffectAnimType
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.weparty.effect.EffectResource
 import com.adealink.weparty.family.data.SortOrder
 import com.adealink.weparty.family.data.SortType

+ 2 - 2
app/src/main/java/com/adealink/weparty/module/game/data/GameData.kt

@@ -2,7 +2,7 @@ package com.adealink.weparty.module.game.data
 
 import android.os.Parcelable
 import androidx.annotation.StringRes
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.util.PackageUtil
 import com.adealink.weparty.R
 import com.adealink.weparty.module.room.data.RewardDetailData
@@ -29,7 +29,7 @@ data class GameShowConfigReq(
     @SerializedName("configTypes") val configTypes: List<Int>,
     @SerializedName("versionCode") val versionCode: Int,
     @SerializedName("channel") val channel: String,
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("packageName") val packageName: String = PackageUtil.getPackageName(),
 )
 

+ 25 - 5
app/src/main/java/com/adealink/weparty/module/game/data/GameHubData.kt

@@ -3,6 +3,7 @@ package com.adealink.weparty.module.game.data
 import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.base.IError
 import com.adealink.weparty.R
+import com.adealink.weparty.util.UnitUtil.formatByte
 import com.google.gson.annotations.GsonNullable
 import com.google.gson.annotations.SerializedName
 
@@ -15,15 +16,18 @@ data class GameHubItemInfo(
     val remoteVersion: GameHubItemVersionData?, //远端版本配置
 
     val path: String = "",
-    var downloadProgress: Int = -1,
-    var downloadError: Boolean = false
 ) {
+    var downloadProgress: Int? = null
+    var downloadCurrentSize: Long = 0
+    var downloadTotalSize: Long = 0
+    var downloadError: Boolean = false
+
     fun hasStartDownload(): Boolean {
-        return downloadProgress >= 0
+        return (downloadProgress ?: -1) >= 0 || downloadCurrentSize > 0
     }
 
     fun isDownloadFinish(): Boolean {
-        return downloadProgress > DOWNLOAD_FINISH
+        return (downloadProgress ?: -1) > DOWNLOAD_FINISH
     }
 }
 
@@ -77,4 +81,20 @@ class GameDownloadingError : IError(getCompatString(R.string.game_downloading_ti
 
 class GameAppVersionOldCanPlayGameError : IError(getCompatString(R.string.game_app_version_old_can_play_game_error))
 
-class GameAppVersionOldNeedUpgradeError : IError(getCompatString(R.string.game_app_version_old_need_upgrade_error))
+class GameAppVersionOldNeedUpgradeError : IError(getCompatString(R.string.game_app_version_old_need_upgrade_error))
+
+/**
+ * @param progress 下载进度
+ * @param currentSize 已下载大小(单位:Byte)
+ * @param totalSize 总下载大小(单位:Byte)
+ */
+fun getGameDownloadDesc(progress: Int?, currentSize: Long, totalSize: Long): String {
+    if (progress != null && progress >= 0) {
+        return getCompatString(R.string.game_downloading, progress.toString())
+    }
+    if (totalSize > 0) {
+        return getCompatString(R.string.game_downloading_size, "${formatByte(currentSize)}/${formatByte(totalSize)}")
+    }
+    //progress未知
+    return getCompatString(R.string.game_downloading_size, formatByte(currentSize))
+}

+ 33 - 8
app/src/main/java/com/adealink/weparty/module/game/gamehub/GameHubManager.kt

@@ -52,6 +52,13 @@ class GameHubManager : BaseFrame<IGameHubListener>(), IGameHubManager {
 
     private val downloadListener = object : TaskListener {
 
+        override fun onStart(task: Task) {
+            Log.d(TAG_GAME, "DownloadTask(${task}), download start")
+            getGameIdFromDownloadTask(task.id)?.let {
+                notifyTaskDownloadStart(it)
+            }
+        }
+
         override fun onFinished(task: Task) {
             Log.d(TAG_GAME, "DownloadTask(${task}), download finish")
             getGameIdFromDownloadTask(task.id)?.let {
@@ -59,9 +66,9 @@ class GameHubManager : BaseFrame<IGameHubListener>(), IGameHubManager {
             }
         }
 
-        override fun onProgress(task: Task, progress: Int) {
+        override fun onProgress(task: Task, progress: Int?, currentSize: Long, totalSize: Long) {
             getGameIdFromDownloadTask(task.id)?.let {
-                notifyTaskDownloadUpdate(it, progress)
+                notifyTaskDownloadUpdate(it, progress, currentSize, totalSize)
             }
         }
 
@@ -170,9 +177,10 @@ class GameHubManager : BaseFrame<IGameHubListener>(), IGameHubManager {
         if (!game.needDownloadResource) {
             return GameHubItemInfo(
                 GameVersion(0, "", "", ""),
-                null,
-                downloadProgress = DOWNLOAD_UNZIP_FINISH
-            )
+                null
+            ).also {
+                it.downloadProgress = DOWNLOAD_UNZIP_FINISH
+            }
         }
 
         val path = getGameRootPath(game)
@@ -207,8 +215,9 @@ class GameHubManager : BaseFrame<IGameHubListener>(), IGameHubManager {
                 gameVersion,
                 remoteVersion,
                 path = path,
-                downloadProgress = DOWNLOAD_UNZIP_FINISH
-            )
+            ).also {
+                it.downloadProgress = DOWNLOAD_UNZIP_FINISH
+            }
         }
     }
 
@@ -298,7 +307,12 @@ class GameHubManager : BaseFrame<IGameHubListener>(), IGameHubManager {
         return Rlt.Success(Any())
     }
 
-    private fun notifyTaskDownloadUpdate(game: Game, progress: Int) {
+    private fun notifyTaskDownloadUpdate(
+        game: Game,
+        progress: Int?,
+        currentSize: Long,
+        totalSize: Long
+    ) {
         val gameHubItemInfo = gameHubInfoMap[game] ?: return
         if (gameHubItemInfo.downloadProgress == progress) {
             //进度没有变化就不通知,避免频繁刷新
@@ -306,6 +320,8 @@ class GameHubManager : BaseFrame<IGameHubListener>(), IGameHubManager {
         }
         Log.d(TAG_GAME, "notifyTaskDownloadUpdate: game:$game, progress:$progress")
         gameHubItemInfo.downloadProgress = progress
+        gameHubItemInfo.downloadCurrentSize = currentSize
+        gameHubItemInfo.downloadTotalSize = totalSize
         gameHubItemInfo.downloadError = false
         dispatch {
             it.onGameDownloadUpdated(game, gameHubItemInfo)
@@ -322,6 +338,15 @@ class GameHubManager : BaseFrame<IGameHubListener>(), IGameHubManager {
         }
     }
 
+    private fun notifyTaskDownloadStart(game: Game) {
+        Log.d(TAG_GAME, "notifyTaskDownloadStart: game:$game")
+        val currentGameHubItemInfo = gameHubInfoMap[game] ?: return
+        currentGameHubItemInfo.downloadProgress = 0
+        currentGameHubItemInfo.downloadCurrentSize = 0
+        currentGameHubItemInfo.downloadTotalSize = 0
+        currentGameHubItemInfo.downloadError = false
+    }
+
     private fun notifyTaskDownloadFinish(game: Game) {
         launch {
             val currentGameHubItemInfo = gameHubInfoMap[game] ?: return@launch

+ 2 - 1
app/src/main/java/com/adealink/weparty/module/game/rocket/Data.kt

@@ -1,6 +1,7 @@
 package com.adealink.weparty.module.game.rocket
 
 import android.os.Parcelable
+import com.adealink.frame.storage.file.WeFile
 import com.adealink.weparty.module.room.data.RoomLimitTimeGiftData
 import com.google.gson.annotations.GsonNullable
 import com.google.gson.annotations.SerializedName
@@ -146,7 +147,7 @@ data class RocketUpgradeNotify(
 ) {
     var receiveNotifyTime = 0L
 
-    var effectPath: String? = null
+    var effectPath: WeFile? = null
 }
 
 data class RocketRewardIssueNotify(

+ 2 - 1
app/src/main/java/com/adealink/weparty/module/game/rocket/view/RocketHeadlineView.kt

@@ -34,7 +34,8 @@ class RocketHeadlineView @JvmOverloads constructor(
 
     fun updateUI(notify: RocketUpgradeNotify) {
         this.notify = notify
-        playBackgroundSvga(notify.level, notify.effectPath)
+        val effectPath = notify.effectPath?.use()
+        playBackgroundSvga(notify.level, effectPath)
         notify.roundNum.toString().also { binding.layoutRocketRound.tvRoundNum.text = it }
         binding.layoutRocketRound.root.show(notify.roundNum > 0)
         binding.titleTv.text = getCompatString(R.string.game_rocket_headline_title, notify.roomId)

+ 4 - 3
app/src/main/java/com/adealink/weparty/module/game/rocket/viewmodel/IRocketViewModel.kt

@@ -3,6 +3,7 @@ package com.adealink.weparty.module.game.rocket.viewmodel
 import androidx.lifecycle.LiveData
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.mvvm.livedata.ExtLiveData
+import com.adealink.frame.storage.file.WeFile
 import com.adealink.weparty.module.game.rocket.RocketKingRes
 import com.adealink.weparty.module.game.rocket.RocketKingUserInfo
 import com.adealink.weparty.module.game.rocket.RocketLevel
@@ -62,11 +63,11 @@ interface IRocketViewModel {
 
     fun getDownloadedLaunchPadRocketEffectPath(level: RocketLevel): String?
 
-    fun getLaunchPadRocketEffectPath(level: RocketLevel): LiveData<Rlt<String>>
+    fun getLaunchPadRocketEffectPath(level: RocketLevel): LiveData<Rlt<WeFile>>
 
-    fun getLaunchPadEffectPath(): LiveData<Rlt<String>>
+    fun getLaunchPadEffectPath(): LiveData<Rlt<WeFile>>
 
-    fun getRocketLaunchEffectPath(level: RocketLevel): LiveData<Rlt<String>>
+    fun getRocketLaunchEffectPath(level: RocketLevel): LiveData<Rlt<WeFile>>
 
     fun getRocketKingList(): LiveData<Rlt<RocketKingRes>>
 }

+ 5 - 191
app/src/main/java/com/adealink/weparty/module/gift/data/GiftData.kt

@@ -1,13 +1,10 @@
 package com.adealink.weparty.module.gift.data
 
-import android.graphics.Bitmap
 import android.graphics.Color
 import android.graphics.Paint
 import android.os.Parcelable
 import android.text.TextPaint
 import com.adealink.frame.base.Rlt
-import com.adealink.frame.ext.safeParseColor
-import com.adealink.frame.image.imageService
 import com.adealink.frame.locale.language.data.Language
 import com.adealink.frame.network.data.Res
 import com.adealink.frame.tceffect.TCEffectManager
@@ -22,15 +19,8 @@ import com.google.gson.annotations.GsonNullable
 import com.google.gson.annotations.Must
 import com.google.gson.annotations.SerializedName
 import com.opensource.svgaplayer.SVGADynamicEntity
-import com.tencent.qgame.animplayer.inter.IFetchResource
-import com.tencent.qgame.animplayer.mix.Resource
-import com.tencent.tcmediax.tceffectplayer.api.data.TCEffectText
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResourceImgResult
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResourceTxtResult
 import kotlinx.parcelize.IgnoredOnParcel
 import kotlinx.parcelize.Parcelize
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResource as TCFetchResource
-import com.tencent.tcmediax.tceffectplayer.api.mix.Resource as TCResource
 
 /**
  * Created by sunxiaodong on 2021/5/10.
@@ -226,40 +216,6 @@ data class GiftInfo(
         return (System.currentTimeMillis() - giftAddTime) < 432_000_000 //5天内
     }
 
-    fun getSVGAGiftDynamicEntity(): SVGADynamicEntity? {
-        if (dynamicEntities.isNullOrEmpty()) {
-            return null
-        }
-        val dynamicEntity = SVGADynamicEntity()
-        dynamicEntities.forEach {
-            when (DynamicEntityType.map(it.type)) {
-                DynamicEntityType.Text -> {
-                    val textPaint = TextPaint()
-                    textPaint.textSize = 20f
-                    textPaint.isFakeBoldText = true
-                    textPaint.color = Color.WHITE
-                    textPaint.textAlign = Paint.Align.CENTER
-                    var text = it.value
-                    text = if (text.length > 8) {
-                        text.substring(0, 8) + "..."
-                    } else {
-                        text
-                    }
-                    dynamicEntity.setDynamicText(text, textPaint, it.key)
-                }
-
-                DynamicEntityType.PictureUrl -> {
-                    dynamicEntity.setDynamicImage(it.value, it.key)
-                }
-
-                else -> {
-                    //ntd
-                }
-            }
-        }
-        return dynamicEntity
-    }
-
     fun getFreeGiftStatus(): Pair<FreeGiftStatus, Long> {
         //检查当天是否有可赠送
         val nowMs = System.currentTimeMillis()
@@ -282,152 +238,6 @@ data class GiftInfo(
     }
 }
 
-fun getSVGAGiftDynamicEntity(dynamicEntities: List<GiftDynamicEntity>?): SVGADynamicEntity? {
-    if (dynamicEntities.isNullOrEmpty()) {
-        return null
-    }
-    val dynamicEntity = SVGADynamicEntity()
-    dynamicEntities.forEach {
-        when (DynamicEntityType.map(it.type)) {
-            DynamicEntityType.Text -> {
-                val textPaint = TextPaint()
-                textPaint.textSize = it.sizePx?.toFloat() ?: 20f
-                textPaint.isFakeBoldText = true
-                textPaint.color = safeParseColor(it.color ?: "#ffffff")
-                textPaint.textAlign = Paint.Align.CENTER
-                var text = it.value
-                text = if (text.length > 8) {
-                    text.substring(0, 8) + "..."
-                } else {
-                    text
-                }
-                dynamicEntity.setDynamicText(text, textPaint, it.key)
-            }
-
-            DynamicEntityType.PictureUrl -> {
-                dynamicEntity.setDynamicImage(it.value, it.key)
-            }
-
-            else -> {
-                //ntd
-            }
-        }
-    }
-    return dynamicEntity
-}
-
-fun getVapFetchResource(dynamicEntities: List<GiftDynamicEntity>?): IFetchResource? {
-    if (dynamicEntities.isNullOrEmpty()) {
-        return null
-    }
-    val imageExtraConfigs = HashMap<String, GiftDynamicEntity>()
-    val textExtraConfigs = HashMap<String, GiftDynamicEntity>()
-    dynamicEntities.forEach { config ->
-        when (DynamicEntityType.map(config.type)) {
-            DynamicEntityType.PictureUrl -> {
-                imageExtraConfigs[config.key] = config
-            }
-
-            DynamicEntityType.Text -> {
-                textExtraConfigs[config.key] = config
-            }
-
-            else -> {
-                //ntd.
-            }
-        }
-    }
-
-    return object : IFetchResource {
-        override fun fetchImage(resource: Resource, result: (Bitmap?) -> Unit) {
-            val dynamicEntity = imageExtraConfigs[resource.tag]
-            if (dynamicEntity != null) {
-                result(imageService.getBitmapSync(dynamicEntity.value, dynamicEntity.sizePx ?: 150, roundAsCircle = true))
-            } else {
-                result(null)
-            }
-
-        }
-
-        override fun fetchText(resource: Resource, result: (String?) -> Unit) {
-            val dynamicEntity = textExtraConfigs[resource.tag]
-            if (dynamicEntity != null) {
-                result(dynamicEntity.value)
-            } else {
-                result(null)
-            }
-        }
-
-        override fun releaseResource(resources: List<Resource>) {
-            resources.forEach {
-                it.bitmap?.recycle()
-            }
-        }
-    }
-
-}
-
-fun getTCFetchResource(dynamicEntities: List<GiftDynamicEntity>?): TCFetchResource? {
-    if (dynamicEntities.isNullOrEmpty()) {
-        return null
-    }
-    val imageExtraConfigs = HashMap<String, GiftDynamicEntity>()
-    val textExtraConfigs = HashMap<String, GiftDynamicEntity>()
-    dynamicEntities.forEach { config ->
-        when (DynamicEntityType.map(config.type)) {
-            DynamicEntityType.PictureUrl -> {
-                imageExtraConfigs[config.key] = config
-            }
-
-            DynamicEntityType.Text -> {
-                textExtraConfigs[config.key] = config
-            }
-
-            else -> {
-                //ntd.
-            }
-        }
-    }
-
-    return object : TCFetchResource {
-        override fun fetchImage(
-            resource: TCResource,
-            result: IFetchResourceImgResult
-        ) {
-            val dynamicEntity = imageExtraConfigs[resource.tag]
-            if (dynamicEntity != null) {
-                result.fetch(imageService.getBitmapSync(dynamicEntity.value, dynamicEntity.sizePx ?: 150))
-            } else {
-                result.fetch(null)
-            }
-        }
-
-        override fun fetchText(
-            resource: TCResource,
-            result: IFetchResourceTxtResult
-        ) {
-            val config = textExtraConfigs[resource.tag]
-            if (config != null) {
-                val tcEffectText = TCEffectText()
-                tcEffectText.text = config.value
-                tcEffectText.color = safeParseColor(config.color ?: "#ffffff")
-                tcEffectText.alignment = TCEffectText.TEXT_ALIGNMENT_CENTER
-                result.loadTextForPlayer(tcEffectText)
-            } else {
-                result.loadTextForPlayer(null)
-            }
-        }
-
-        override fun releaseResource(resources: MutableList<TCResource>) {
-            resources.forEach {
-                it.bitmap?.recycle()
-            }
-        }
-
-    }
-}
-
-
 @Parcelize
 data class GiftDynamicEntity(
     @SerializedName("key")
@@ -440,6 +250,10 @@ data class GiftDynamicEntity(
     @SerializedName("sizePx") val sizePx: Int?,
     @GsonNullable
     @SerializedName("color") val color: String?,
+    @GsonNullable
+    @SerializedName("shape") val shape: String? = null, //形状,圆形、方形等,详见:EffectExtraShape
+    @GsonNullable
+    @SerializedName("heightPx") val heightPx: Int? = null
 ) : Parcelable
 
 enum class DynamicEntityType(val type: Int) {
@@ -448,7 +262,7 @@ enum class DynamicEntityType(val type: Int) {
 
     companion object {
         fun map(type: Int): DynamicEntityType? {
-            return values().find { it.type == type }
+            return entries.find { it.type == type }
         }
     }
 }

+ 79 - 0
app/src/main/java/com/adealink/weparty/module/gift/data/GiftDynamicExt.kt

@@ -0,0 +1,79 @@
+package com.adealink.weparty.module.gift.data
+
+import android.util.Patterns
+import android.util.Size
+import com.adealink.frame.effect.data.DynamicAnimImage
+import com.adealink.frame.effect.data.DynamicAnimText
+import com.adealink.frame.effect.data.IAnimDynamicProvider
+import com.adealink.frame.image.imageService
+import com.adealink.weparty.module.profile.decorate.data.EffectExtraShape
+
+fun List<GiftDynamicEntity>.getGiftAnimDynamicProvider(): IAnimDynamicProvider? {
+    if (this.isEmpty()) {
+        return null
+    }
+    val imageExtraConfigs = HashMap<String, GiftDynamicEntity>()
+    val textExtraConfigs = HashMap<String, GiftDynamicEntity>()
+    this.forEach { config ->
+        when (DynamicEntityType.map(config.type)) {
+            DynamicEntityType.PictureUrl -> {
+                imageExtraConfigs[config.key] = config
+            }
+
+            DynamicEntityType.Text -> {
+                textExtraConfigs[config.key] = config
+            }
+
+            else -> {
+                //ntd.
+            }
+        }
+    }
+    return object : IAnimDynamicProvider {
+        override fun provideImage(callback: (Map<String, DynamicAnimImage>?) -> Unit) {
+            val dynamicMap = hashMapOf<String, DynamicAnimImage>()
+            imageExtraConfigs.forEach { entry ->
+                val dynamicConfig = entry.value
+                val url = dynamicConfig.value
+                if (!Patterns.WEB_URL.matcher(url).matches()) {
+                    return@forEach
+                }
+                dynamicMap[entry.key] = DynamicAnimImage {
+                    var imageWidth = 0
+                    var imageHeight = 0
+                    var roundAsCircle = true
+                    when (EffectExtraShape.map(dynamicConfig.shape)) {
+                        EffectExtraShape.CIRCLE, EffectExtraShape.UNKNOWN -> {
+                            //默认都裁圆角
+                            imageWidth = dynamicConfig.sizePx ?: 150
+                            imageHeight = imageWidth
+                        }
+                        EffectExtraShape.SQUARE -> {
+                            imageWidth = dynamicConfig.sizePx ?: 150
+                            imageHeight = dynamicConfig.heightPx ?: imageWidth
+                            roundAsCircle = false
+                        }
+                    }
+                    imageService.getBitmapSync(
+                        imageService.getResizeUrl(url, imageWidth, imageHeight),
+                        Size(imageWidth, imageHeight),
+                        roundAsCircle
+                    )
+                }
+            }
+            callback(dynamicMap)
+        }
+
+        override fun provideText(callback: (Map<String, DynamicAnimText>?) -> Unit) {
+            val dynamicMap = hashMapOf<String, DynamicAnimText>()
+            textExtraConfigs.forEach { entry ->
+                dynamicMap[entry.key] = DynamicAnimText(
+                    text = entry.value.value,
+                    fontSizePx = entry.value.sizePx ?: 20,
+                    color = entry.value.color ?: "#ffffff"
+                )
+            }
+            callback(dynamicMap)
+        }
+    }
+}

+ 3 - 4
app/src/main/java/com/adealink/weparty/module/gift/effect/SendGiftNoticeView.kt

@@ -14,7 +14,7 @@ import androidx.constraintlayout.widget.ConstraintSet
 import androidx.core.view.updateLayoutParams
 import com.adealink.frame.aab.util.getCompatColor
 import com.adealink.frame.base.fastLazy
-import com.adealink.frame.effect.data.INFINITE_LOOP
+import com.adealink.frame.effect.data.AnimExtraConfig
 import com.adealink.frame.ext.safeSetSpan
 import com.adealink.frame.router.Router
 import com.adealink.frame.util.DisplayUtil
@@ -30,8 +30,6 @@ import com.adealink.weparty.commonui.ext.gone
 import com.adealink.weparty.commonui.ext.hide
 import com.adealink.weparty.commonui.ext.show
 import com.adealink.weparty.databinding.LayoutSendGiftNoticeBinding
-import com.adealink.weparty.effect.AnimExtraConfig
-import com.adealink.weparty.module.gift.Gift
 import com.adealink.weparty.module.gift.data.ComboTarget
 import com.adealink.weparty.module.gift.data.SendBackpackItemNotify
 import com.adealink.weparty.module.gift.data.SendGiftNotify
@@ -151,7 +149,8 @@ class SendGiftNoticeView @JvmOverloads constructor(
 
                 binding.clContent.setPadding(0, 10.dp(), 0, 0)
                 binding.tvReceiverName.setTextColor(getCompatColor(R.color.color_FFFFFD00))
-                binding.wavBg.setUrl(roomSendGiftNoticeUrl, extraConfig = AnimExtraConfig(loop = INFINITE_LOOP, scaleType = ImageView.ScaleType.FIT_XY))
+                binding.wavBg.setConfig(AnimExtraConfig(scaleType = ImageView.ScaleType.FIT_XY))
+                binding.wavBg.setUrl(roomSendGiftNoticeUrl)
             }
             val combo = sendGiftNotify.combo
 

+ 15 - 19
app/src/main/java/com/adealink/weparty/module/gift/view/EdgeFlashEffectView.kt

@@ -13,9 +13,13 @@ import com.adealink.frame.base.Rlt
 import com.adealink.frame.coroutine.dispatcher.Dispatcher
 import com.adealink.frame.download.listener.TaskListener
 import com.adealink.frame.download.task.Task
-import com.adealink.frame.effect.video.isVapVideo
+import com.adealink.frame.effect.video.Mp4BoxType
+import com.adealink.frame.effect.video.hasBoxType
 import com.adealink.frame.image.view.NetworkImageView
 import com.adealink.frame.log.Log
+import com.adealink.frame.storage.file.WeFile
+import com.adealink.frame.storage.file.getCacheFilePathByUrl
+import com.adealink.frame.storageService
 import com.adealink.frame.util.createOrExistsDir
 import com.adealink.frame.util.isFileExists
 import com.adealink.frame.util.md5
@@ -88,8 +92,9 @@ class EdgeFlashEffectView @JvmOverloads constructor(
                 downloadVap(vapUrl)
             }
             if (downloadRlt is Rlt.Success) {
+                val path = downloadRlt.data.use() ?: return@launch
                 val isVapVideo = withContext(Dispatcher.WENEXT_THREAD_POOL) {
-                    isVapVideo(downloadRlt.data)
+                    hasBoxType(path, Mp4BoxType.VAP)
                 }
                 if (vapUrl != effectUrl) {
                     //和当前不是同一个动效文件
@@ -107,13 +112,13 @@ class EdgeFlashEffectView @JvmOverloads constructor(
                     }
                     val vapView = inflateVapView()
                     vapView.show()
-                    vapView.startPlay(File(downloadRlt.data))
+                    vapView.startPlay(File(path))
                 }
             }
         }
     }
 
-    private suspend fun downloadVap(vapUrl: String): Rlt<String> {
+    private suspend fun downloadVap(vapUrl: String): Rlt<WeFile> {
         return suspendCancellableCoroutine { continuation ->
             addDownloadTask(
                 vapUrl,
@@ -133,12 +138,13 @@ class EdgeFlashEffectView @JvmOverloads constructor(
 
     private fun addDownloadTask(
         url: String,
-        success: ((path: String) -> Unit)? = null,
+        success: ((path: WeFile) -> Unit)? = null,
         failed: ((error: IError) -> Unit)? = null,
     ) {
-        val savePath = getSavePath(url)
-        if (isFileExists(savePath)) {
-            success?.invoke(savePath)
+        val savePath = getCacheFilePathByUrl(url)
+        val file = storageService.file.createWeFile(savePath)
+        if (file.exists()) {
+            success?.invoke(file)
             return
         }
 
@@ -152,7 +158,7 @@ class EdgeFlashEffectView @JvmOverloads constructor(
 
             override fun onFinished(task: Task) {
                 super.onFinished(task)
-                success?.invoke(savePath)
+                success?.invoke(file)
                 Log.d(
                     TAG,
                     "addDownloadTask, download success, task:$task"
@@ -172,16 +178,6 @@ class EdgeFlashEffectView @JvmOverloads constructor(
         App.instance.downloadService.addTask(task)
     }
 
-    private fun getSaveDir(): String {
-        val dir = "${FilePath.videoPath}${File.separator}"
-        createOrExistsDir(dir)
-        return dir
-    }
-
-    private fun getSavePath(url: String): String {
-        return "${getSaveDir()}${"${url.md5()}.${url.split(".").last()}"}"
-    }
-
     private fun inflateImageView(): NetworkImageView {
         var imageView = findViewById<NetworkImageView>(R.id.edge_flash_effect_view_image)
         if (imageView != null) {

+ 1 - 5
app/src/main/java/com/adealink/weparty/module/message/reminder/MessageReminderDialog.kt

@@ -13,7 +13,6 @@ import androidx.lifecycle.lifecycleScope
 import com.adealink.frame.aab.util.getCompatColor
 import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.base.Rlt
-import com.adealink.frame.base.fastLazy
 import com.adealink.frame.dot.NumDot
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.router.Router
@@ -25,8 +24,6 @@ import com.adealink.weparty.R
 import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
 import com.adealink.weparty.commonui.ext.getActivity
 import com.adealink.weparty.databinding.DialogMessageReminderBinding
-import com.adealink.weparty.effect.AnimExtraConfig
-import com.adealink.weparty.effect.EffectAnimType
 import com.adealink.weparty.module.message.Message
 import com.adealink.weparty.module.message.MessageModule
 import com.adealink.weparty.module.message.data.EnterConversationFrom
@@ -46,7 +43,6 @@ class MessageReminderDialog : BaseDialogFragment(R.layout.dialog_message_reminde
     var message: io.rong.imlib.model.Message? = null
 
     private val binding by viewBinding(DialogMessageReminderBinding::bind)
-    private val config by fastLazy { AnimExtraConfig(loop = -1) }
 
     companion object {
         const val KEY_BTN_TEXT = "text"
@@ -77,7 +73,7 @@ class MessageReminderDialog : BaseDialogFragment(R.layout.dialog_message_reminde
                 }
             }
         }
-        binding.headAnimationView.setUrl(getHeadAnimationUrl(), EffectAnimType.TC, config)
+        binding.headAnimationView.setUrl(getHeadAnimationUrl())
         binding.replyBtn.setAsset(
             "message_reminder_reply_btn.svga", supplier = {
                 val textPaint = TextPaint().apply {

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/operation/reward/preview/BaseRewardPreviewDialog.kt

@@ -5,7 +5,7 @@ import android.os.Bundle
 import androidx.annotation.LayoutRes
 import androidx.fragment.app.FragmentManager
 import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
-import com.adealink.weparty.effect.EffectAnimType
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.weparty.module.operation.Operation
 
 abstract class BaseRewardPreviewDialog(@LayoutRes layoutId: Int, tag: String) : BaseDialogFragment(layoutId), IRewardPreviewDialog {

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/operation/reward/preview/CarPreviewDialog.kt

@@ -10,7 +10,7 @@ import com.adealink.frame.effect.data.INFINITE_LOOP
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.weparty.R
 import com.adealink.weparty.databinding.DialogPreviewCarBinding
-import com.adealink.weparty.effect.AnimExtraConfig
+import com.adealink.frame.effect.data.AnimExtraConfig
 import com.adealink.weparty.effect.IPreviewView
 
 class CarPreviewDialog : BaseRewardPreviewDialog(R.layout.dialog_preview_car, "CarReviewDialog"),

+ 16 - 10
app/src/main/java/com/adealink/weparty/module/operation/reward/preview/FramePreviewDialog.kt

@@ -10,9 +10,9 @@ import com.adealink.weparty.R
 import com.adealink.weparty.commonui.ext.gone
 import com.adealink.weparty.commonui.ext.show
 import com.adealink.weparty.databinding.DialogPreviewFrameBinding
-import com.adealink.weparty.effect.AnimExtraConfig
-import com.adealink.weparty.effect.SVGAExtraConfig
-import com.adealink.weparty.effect.TCExtraConfig
+import com.adealink.frame.effect.data.AnimExtraConfig
+import com.adealink.frame.effect.view.IWeAnimPlayListener
+import com.adealink.frame.ext.isViewBindingValid
 import com.adealink.weparty.module.profile.decorate.data.GoodsExtraConfig
 
 class FramePreviewDialog :
@@ -53,16 +53,22 @@ class FramePreviewDialog :
             val animExtraConfig = AnimExtraConfig(
                 loop = INFINITE_LOOP,
                 ratio = ratio,
-                svgaExtraConfig = SVGAExtraConfig(dynamicEntitySupplier = extraConfig?.createSVGADynamicSupplier()),
-                tcExtraConfig = TCExtraConfig(tcFetchResource = extraConfig?.createTCFetchResource()),
             )
+            binding.animView.show()
+            binding.animView.setConfig(animExtraConfig)
+            binding.animView.setListener(object : IWeAnimPlayListener {
+                override fun onPlayStart() {
+                    super.onPlayStart()
+                    if (!isViewBindingValid()) {
+                        return
+                    }
+                    binding.vLoading.gone()
+                }
+            })
             binding.animView.setUrl(
                 url,
-                animType,
-                extraConfig = animExtraConfig,
-                onPlayStart = {
-                    binding.vLoading.gone()
-                })
+                dynamicProvider = extraConfig?.createAnimDynamicProvider()
+            )
         }
     }
 

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/operation/reward/preview/IRewardPreviewDialog.kt

@@ -1,7 +1,7 @@
 package com.adealink.weparty.module.operation.reward.preview
 
 import androidx.fragment.app.FragmentManager
-import com.adealink.weparty.effect.EffectAnimType
+import com.adealink.frame.effect.data.EffectAnimType
 
 interface IRewardPreviewDialog {
     var resourceUrl: String?

+ 1 - 2
app/src/main/java/com/adealink/weparty/module/operation/reward/preview/MedalPreviewDialog.kt

@@ -9,7 +9,6 @@ import com.adealink.weparty.commonui.ext.show
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.weparty.R
 import com.adealink.weparty.databinding.DialogPreviewMedalBinding
-import com.adealink.weparty.effect.AnimExtraConfig
 
 class MedalPreviewDialog : BaseRewardPreviewDialog(R.layout.dialog_preview_medal, "MedalReviewFragment") {
 
@@ -59,7 +58,7 @@ class MedalPreviewDialog : BaseRewardPreviewDialog(R.layout.dialog_preview_medal
         } else if (playUrl.endsWith(".svga") || playUrl.endsWith(".mp4") || playUrl.endsWith(".webp")) {
             binding.effectView.show()
             binding.ivImg.gone()
-            binding.effectView.setUrl(playUrl, extraConfig = AnimExtraConfig(loop = -1))
+            binding.effectView.setUrl(playUrl)
         } else {
             dismiss()
         }

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/operation/reward/preview/OtherPreviewDialog.kt

@@ -14,7 +14,7 @@ import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.commonui.ext.gone
 import com.adealink.weparty.commonui.ext.show
 import com.adealink.weparty.databinding.DialogPreviewOtherBinding
-import com.adealink.weparty.effect.AnimExtraConfig
+import com.adealink.frame.effect.data.AnimExtraConfig
 import com.adealink.weparty.effect.IPreviewView
 
 class OtherPreviewDialog :

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/operation/reward/preview/RewardPreviewDialogBuilder.kt

@@ -2,7 +2,7 @@ package com.adealink.weparty.module.operation.reward.preview
 
 import android.os.Bundle
 import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
-import com.adealink.weparty.effect.EffectAnimType
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.weparty.module.operation.data.ProductTypeConstant
 import com.adealink.weparty.module.operation.Operation
 

+ 6 - 22
app/src/main/java/com/adealink/weparty/module/operation/reward/preview/ThemePreviewDialog.kt

@@ -2,7 +2,6 @@ package com.adealink.weparty.module.operation.reward.preview
 
 import android.graphics.Color
 import android.graphics.drawable.ColorDrawable
-import android.media.MediaPlayer
 import android.view.View
 import android.view.Window
 import android.view.WindowManager
@@ -15,7 +14,6 @@ import com.adealink.weparty.commonui.ext.gone
 import com.adealink.weparty.commonui.ext.show
 import com.adealink.weparty.databinding.DialogPreviewThemeBinding
 import com.adealink.weparty.module.theme.ThemeModule
-import com.adealink.weparty.module.theme.data.DynamicThemeResourceType
 import com.opensource.svgaplayer.control.ControllerListener
 import com.opensource.svgaplayer.entities.SvgaInfo
 
@@ -84,31 +82,17 @@ class ThemePreviewDialog : BaseRewardPreviewDialog(R.layout.dialog_preview_theme
 
             dynamicUrl.endsWith(".mp4") -> {
                 binding.vLoading.show()
-                themeViewModel?.downloadTheme(dynamicUrl, DynamicThemeResourceType.MP4)
+                themeViewModel?.downloadTheme(dynamicUrl)
                     ?.observe(viewLifecycleOwner) { pathRlt ->
                         binding.vLoading.gone()
                         if (pathRlt is Rlt.Success) {
-                            binding.videoTheme.setOnPreparedListener(MediaPlayer.OnPreparedListener { mp ->
-                                if (!isUIValid()) {
-                                    return@OnPreparedListener
-                                }
-                                binding.videoTheme.visibility = View.VISIBLE
-                                try {
-                                    mp.isLooping = true
-                                    mp.start()
-                                } catch (e: Exception) {
-                                    showThemeImg(resourceUrl)
-                                }
-                            })
-                            binding.videoTheme.setOnErrorListener(MediaPlayer.OnErrorListener { _: MediaPlayer?, _: Int, _: Int ->
-                                if (!isUIValid()) {
-                                    return@OnErrorListener false
-                                }
+                            val path = pathRlt.data.use()
+                            if (path.isNullOrEmpty()) {
                                 showThemeImg(resourceUrl)
-                                false
-                            })
-                            binding.videoTheme.setVideoPath(pathRlt.data)
+                                return@observe
+                            }
                             binding.videoTheme.visibility = View.VISIBLE
+                            binding.videoTheme.setFile(path)
                         } else {
                             showThemeImg(resourceUrl)
                         }

+ 63 - 79
app/src/main/java/com/adealink/weparty/module/profile/decorate/data/ExtraConfigData.kt

@@ -1,9 +1,13 @@
 package com.adealink.weparty.module.profile.decorate.data
 
-import android.graphics.Bitmap
 import android.graphics.Paint
 import android.os.Parcelable
 import android.text.TextPaint
+import android.util.Patterns
+import android.util.Size
+import com.adealink.frame.effect.data.DynamicAnimImage
+import com.adealink.frame.effect.data.DynamicAnimText
+import com.adealink.frame.effect.data.IAnimDynamicProvider
 import com.adealink.frame.ext.safeParseColor
 import com.adealink.frame.image.imageService
 import com.google.gson.annotations.GsonNullable
@@ -11,11 +15,6 @@ import com.google.gson.annotations.Must
 import com.google.gson.annotations.SerializedName
 import com.opensource.svgaplayer.SVGADynamicEntity
 import com.opensource.svgaplayer.utils.Supplier
-import com.tencent.qgame.animplayer.inter.IFetchResource
-import com.tencent.qgame.animplayer.mix.Resource
-import com.tencent.tcmediax.tceffectplayer.api.data.TCEffectText
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResourceImgResult
-import com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResourceTxtResult
 import kotlinx.parcelize.Parcelize
 
 @Parcelize
@@ -66,7 +65,7 @@ data class GoodsExtraConfig(
         }
     }
 
-    fun createFetchResource(): IFetchResource? {
+    fun createAnimDynamicProvider(): IAnimDynamicProvider? {
         if (effectExtraConfigs.isNullOrEmpty()) {
             return null
         }
@@ -87,87 +86,56 @@ data class GoodsExtraConfig(
                 }
             }
         }
-        return object : IFetchResource {
-            override fun fetchImage(resource: Resource, result: (Bitmap?) -> Unit) {
-                imageExtraConfigs.forEach {
-                    if (resource.tag == it.key) {
-                        result(imageService.getBitmapSync(it.value, it.sizePx))
-                    } else {
-                        result(null)
+        return object : IAnimDynamicProvider {
+            override fun provideImage(callback: (Map<String, DynamicAnimImage>?) -> Unit) {
+                val dynamicMap = hashMapOf<String, DynamicAnimImage>()
+                imageExtraConfigs.forEach { dynamicConfig ->
+                    val url = dynamicConfig.value
+                    if (!Patterns.WEB_URL.matcher(url).matches()) {
+                        return@forEach
                     }
-                }
-            }
-
-            override fun fetchText(resource: Resource, result: (String?) -> Unit) {
-                textExtraConfigs.forEach {
-                    if (resource.tag == it.key) {
-                        result(it.value)
-                    } else {
-                        result(null)
-                    }
-                }
-            }
-
-            override fun releaseResource(resources: List<Resource>) {
-                resources.forEach {
-                    it.bitmap?.recycle()
-                }
-            }
-        }
-    }
-
-    fun createTCFetchResource(): com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResource? {
-        if (effectExtraConfigs.isNullOrEmpty()) {
-            return null
-        }
-        val imageExtraConfigs = arrayListOf<EffectExtraConfig>()
-        val textExtraConfigs = arrayListOf<EffectExtraConfig>()
-        effectExtraConfigs.forEach { config ->
-            when (EffectExtraType.map(config.type)) {
-                EffectExtraType.IMAGE -> {
-                    imageExtraConfigs.add(config)
-                }
-
-                EffectExtraType.TEXT -> {
-                    textExtraConfigs.add(config)
-                }
-
-                else -> {
-                    //ntd.
-                }
-            }
-        }
-        return object : com.tencent.tcmediax.tceffectplayer.api.mix.IFetchResource {
-            override fun fetchImage(resource: com.tencent.tcmediax.tceffectplayer.api.mix.Resource, result: IFetchResourceImgResult) {
-                imageExtraConfigs.forEach {
-                    if (resource.tag == it.key) {
-                        result.fetch(imageService.getBitmapSync(it.value, it.sizePx))
-                    } else {
-                        result.fetch(null)
+                    dynamicMap[dynamicConfig.key] = DynamicAnimImage {
+                        var imageWidth = 0
+                        var imageHeight = 0
+                        var roundAsCircle = true
+                        when (EffectExtraShape.map(dynamicConfig.shape)) {
+                            EffectExtraShape.CIRCLE, EffectExtraShape.UNKNOWN -> {
+                                //默认都裁圆角
+                                imageWidth = dynamicConfig.sizePx
+                                imageHeight = imageWidth
+                            }
+                            EffectExtraShape.SQUARE -> {
+                                imageWidth = dynamicConfig.sizePx
+                                imageHeight = dynamicConfig.heightPx ?: imageWidth
+                                roundAsCircle = false
+
+                            }
+                        }
+                        imageService.getBitmapSync(
+                            imageService.getResizeUrl(url, imageWidth, imageHeight),
+                            Size(imageWidth, imageHeight),
+                            roundAsCircle = roundAsCircle
+                        )
                     }
                 }
+                callback(dynamicMap)
             }
 
-            override fun fetchText(resource: com.tencent.tcmediax.tceffectplayer.api.mix.Resource, result: IFetchResourceTxtResult) {
-                textExtraConfigs.forEach {
-                    if (resource.tag == it.key) {
-                        val tcEffectText = TCEffectText()
-                        tcEffectText.text = it.value
-                        tcEffectText.alignment = TCEffectText.TEXT_ALIGNMENT_CENTER
-                        result.loadTextForPlayer(tcEffectText)
-                    } else {
-                        result.loadTextForPlayer(null)
-                    }
+            override fun provideText(callback: (Map<String, DynamicAnimText>?) -> Unit) {
+                val dynamicMap = hashMapOf<String, DynamicAnimText>()
+                textExtraConfigs.forEach { entry ->
+                    dynamicMap[entry.key] = DynamicAnimText(
+                        text = entry.value,
+                        fontSizePx = entry.sizePx,
+                        color = entry.color,
+                    )
                 }
+                callback(dynamicMap)
             }
 
-            override fun releaseResource(resources: List<com.tencent.tcmediax.tceffectplayer.api.mix.Resource>) {
-                resources.forEach {
-                    it.bitmap?.recycle()
-                }
-            }
         }
     }
+
 }
 
 @Parcelize
@@ -180,6 +148,10 @@ data class EffectExtraConfig(
     @SerializedName("value") val value: String,
     @SerializedName("sizePx") val sizePx: Int,
     @SerializedName("color") val color: String,
+    @GsonNullable
+    @SerializedName("shape") val shape: String? = null, //形状,圆形、方形等
+    @GsonNullable
+    @SerializedName("heightPx") val heightPx: Int? = null
 ) : Parcelable
 
 enum class EffectExtraType(val type: Int) {
@@ -227,4 +199,16 @@ data class CarCustomizedConfig(
 data class CommonLevelConfig(
     @SerializedName("levelType") val levelType: Int,
     @SerializedName("level") val level: Int
-) : Parcelable
+) : Parcelable
+
+enum class EffectExtraShape(val shape: String) {
+    CIRCLE("circle"), //圆形
+    SQUARE("square"), //方形
+    UNKNOWN("unknown"); //未知形状
+
+    companion object {
+        fun map(shape: String?): EffectExtraShape {
+            return entries.firstOrNull { it.shape == shape } ?: UNKNOWN
+        }
+    }
+}

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/profile/decorate/data/UserDecorateData.kt

@@ -2,7 +2,7 @@ package com.adealink.weparty.module.profile.decorate.data
 
 import android.os.Parcelable
 import com.adealink.frame.tceffect.TCEffectManager
-import com.adealink.weparty.effect.EffectAnimType
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.weparty.effect.EffectResource
 import com.adealink.weparty.module.game.data.DragonTigerEntrance
 import com.adealink.weparty.module.game.data.GameEntrance

+ 7 - 11
app/src/main/java/com/adealink/weparty/module/profile/view/UserVoiceView.kt

@@ -192,24 +192,20 @@ class UserVoiceView(context: Context, attrs: AttributeSet? = null) :
         if (url.isEmpty()) {
             return
         }
-        val dir = FilePath.recordPath ?: return
 
         val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
         val viewModelStoreOwner = findViewTreeViewModelStoreOwner() ?: return
         val downloadViewModel =
             ViewModelProvider(viewModelStoreOwner)[DownloadViewModel::class.java]
 
-        downloadViewModel.downloadResource(dir = dir, url = url)
-            .observe(lifecycleOwner) { rlt ->
-                when (rlt) {
-                    is Rlt.Success -> {
-                        startPlay(rlt.data)
-                    }
-
-                    is Rlt.Failed -> {
-                        Log.e(TAG, "downloadResource error: ${rlt.error}")
-                    }
+        downloadViewModel.downloadResource(url = url)
+            .observe(lifecycleOwner) { file ->
+                val path = file?.use()
+                if (path.isNullOrEmpty()) {
+                    Log.e(TAG, "downloadResource error, path:$path")
+                    return@observe
                 }
+                startPlay(path)
             }
 
         lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {

+ 1 - 10
app/src/main/java/com/adealink/weparty/module/profile/widget/VipLevelView.kt

@@ -4,12 +4,9 @@ import android.content.Context
 import android.util.AttributeSet
 import android.view.LayoutInflater
 import androidx.constraintlayout.widget.ConstraintLayout
-import com.adealink.frame.effect.data.INFINITE_LOOP
 import com.adealink.frame.oss.ossService
 import com.adealink.weparty.R
 import com.adealink.weparty.databinding.LayoutMiniVipLevelBinding
-import com.adealink.weparty.effect.AnimExtraConfig
-import com.adealink.weparty.effect.EffectAnimType
 import com.adealink.weparty.module.profile.ProfileModule
 
 /**
@@ -33,13 +30,7 @@ class VipLevelView @JvmOverloads constructor(
     init {
         // 默认显示 VIP
         binding.tvVipLevel.text = context.getString(R.string.commonui_vip_recharge)
-        binding.wvVipLevelAnim.setUrl(
-            VIP_LEVEL_COS_URL,
-            animType = EffectAnimType.TC,
-            extraConfig = AnimExtraConfig(
-                loop = INFINITE_LOOP
-            ),
-        )
+        binding.wvVipLevelAnim.setUrl(VIP_LEVEL_COS_URL)
     }
     /**
      * 设置VIP等级

+ 6 - 16
app/src/main/java/com/adealink/weparty/module/rank/view/MarkProfileView.kt

@@ -10,17 +10,10 @@ import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.updateLayoutParams
 import com.adealink.frame.aab.util.getCompatDrawable
 import com.adealink.frame.aab.util.getCompatString
-import com.adealink.frame.base.IError
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.coroutine.dispatcher.Dispatcher
-import com.adealink.frame.download.listener.TaskListener
 import com.adealink.frame.download.manager.downloadManager
-import com.adealink.frame.download.task.Task
 import com.adealink.frame.download.task.TaskPriority
-import com.adealink.frame.util.createOrExistsDir
-import com.adealink.frame.util.isFileExists
-import com.adealink.frame.util.md5
-import com.adealink.weparty.App
 import com.adealink.weparty.R
 import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.commonui.text.WenextTextView
@@ -41,21 +34,14 @@ import com.adealink.weparty.module.rank.resource.TYPE_ANNUAL_ROOM
 import com.adealink.weparty.module.rank.resource.TYPE_GUARD_ROOM
 import com.adealink.weparty.module.rank.resource.TYPE_WITNESS_CP
 import com.adealink.weparty.module.rank.resource.Top.Companion.intToTop
-import com.adealink.weparty.storage.file.FilePath
 import com.opensource.svgaplayer.SVGADynamicEntity
-import com.opensource.svgaplayer.SVGAParser
-import com.opensource.svgaplayer.SVGAVideoEntity
 import com.opensource.svgaplayer.WenextSvgaView
 import com.opensource.svgaplayer.control.ControllerListener
-import com.opensource.svgaplayer.control.SVGAManager.Companion.parser
 import com.opensource.svgaplayer.entities.SvgaInfo
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.withContext
 import java.io.File
-import java.net.URL
-import kotlin.coroutines.resume
 
 
 class MarkProfileView @JvmOverloads constructor(
@@ -132,12 +118,16 @@ class MarkProfileView @JvmOverloads constructor(
             val markSvgaView = generateDynamicView()
             val downloadRlt = withContext(Dispatcher.WENEXT_THREAD_POOL) {
                 getDynamicMarkResourceUrl(markItem.type)?.let {
-                    downloadManager.downloadResource(FilePath.labelPath ?: FilePath.backupEffectPath, it, TaskPriority.HIGH)
+                    downloadManager.downloadResource( it, TaskPriority.HIGH)
                 }
             }
             if (downloadRlt is Rlt.Success) {
+                val path = downloadRlt.data.use()
+                if (path.isNullOrEmpty()) {
+                    return@launch
+                }
                 markSvgaView.setFile(
-                    File(downloadRlt.data),
+                    File(path),
                     supplier = {
                         SVGADynamicEntity().apply {
                             val url = getDynamicMarkPlaceholder(markItem.type)

+ 2 - 2
app/src/main/java/com/adealink/weparty/module/room/data/RoomAttrData.kt

@@ -1,7 +1,7 @@
 package com.adealink.weparty.module.room.data
 
 import android.os.Parcelable
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.util.PackageUtil
 import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
 import com.adealink.weparty.module.room.RoomModule
@@ -25,7 +25,7 @@ data class GlobalRoomConfigReqNew(
     @SerializedName("roomId") val roomId: Long,
     @SerializedName("configs") val configs: List<Int>,
     @SerializedName("versionCode") val versionCode: Int = PackageUtil.getVersionCode(),
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("packageName") val packageName: String = PackageUtil.getPackageName(),
     @SerializedName("channel") val channel: String = RoomModule.getAppChannel() ?: "",
 )

+ 3 - 3
app/src/main/java/com/adealink/weparty/module/room/data/RoomFlowData.kt

@@ -1,7 +1,7 @@
 package com.adealink.weparty.room.data
 
 import android.os.Parcelable
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.room.data.RoomMemberOnlineInfo
 import com.adealink.frame.room.data.TagInfo
 import com.adealink.frame.util.PackageUtil
@@ -130,7 +130,7 @@ data class JoinRoomReq(
     @SerializedName("password") val password: String? = null,
     @SerializedName("reconnectJoinRoom") val reconnectJoinRoom: Boolean = false,
     @SerializedName("versionCode") val versionCode: Int = PackageUtil.getVersionCode(),
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("packageName") val packageName: String = PackageUtil.getPackageName(),
 )
 
@@ -162,7 +162,7 @@ data class SocketJoinRoomReq(
     @SerializedName("reconnectJoinRoom") val reconnectJoinRoom: Boolean = false,
     @SerializedName("invisibleJoin") val invisibleJoin: Boolean? = null,
     @SerializedName("versionCode") val versionCode: Int = PackageUtil.getVersionCode(),
-    @SerializedName("platform") val platform: String = AppBaseInfo.platform,
+    @SerializedName("platform") val platform: String = AppBase.platform,
     @SerializedName("packageName") val packageName: String = PackageUtil.getPackageName(),
     @SerializedName("breakInvisibleJoin") val breakInvisibleJoin: Boolean? = null,
 )

+ 1 - 1
app/src/main/java/com/adealink/weparty/module/store/data/StoreData.kt

@@ -10,7 +10,7 @@ import com.adealink.frame.tceffect.TCEffectManager
 import com.adealink.frame.util.getRemainDay
 import com.adealink.weparty.R
 import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
-import com.adealink.weparty.effect.EffectAnimType
+import com.adealink.frame.effect.data.EffectAnimType
 import com.adealink.weparty.effect.EffectResource
 import com.adealink.weparty.module.profile.decorate.data.GoodsExtraConfig
 import com.google.gson.annotations.GsonNullable

+ 2 - 2
app/src/main/java/com/adealink/weparty/module/task/ExceptionHandlerEx.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.module.task
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.log.Log
 
 
@@ -15,7 +15,7 @@ inline fun tryCatch(tryBlock: () -> Unit) {
 }
 
 var exceptionHandler: (Throwable) -> Unit = {
-    if (!AppBaseInfo.isRelease) {
+    if (!AppBase.isRelease) {
         throw it
     } else {
         Log.e(TAG, "catch exception", it)

+ 2 - 1
app/src/main/java/com/adealink/weparty/module/theme/data/ThemeData.kt

@@ -3,6 +3,7 @@ package com.adealink.weparty.module.theme.data
 import android.os.Parcelable
 import android.util.Patterns
 import com.adealink.frame.data.json.gson
+import com.adealink.frame.storage.file.WeFile
 import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
 import com.google.gson.annotations.GsonNullable
 import com.google.gson.annotations.JsonAdapter
@@ -138,7 +139,7 @@ enum class DynamicThemeResourceType(val suffix: String) {
 data class ThemeResource(
     val staticResourceUrl: String? = null,
     val dynamicResourceUrl: String? = null,
-    var savePath: String? = null,
+    var savePath: WeFile? = null,
     var themeExtraConfigInfo: String? = null,
     val themeType: String? = null,
 ) {

+ 2 - 2
app/src/main/java/com/adealink/weparty/module/theme/viewmodel/IThemeViewModel.kt

@@ -2,6 +2,7 @@ package com.adealink.weparty.module.theme.viewmodel
 
 import androidx.lifecycle.LiveData
 import com.adealink.frame.base.Rlt
+import com.adealink.frame.storage.file.WeFile
 import com.adealink.weparty.module.theme.data.DynamicThemeResourceType
 import com.adealink.weparty.module.theme.data.ThemeInfo
 import com.adealink.weparty.module.theme.data.ThemePreFetchType
@@ -15,8 +16,7 @@ interface IThemeViewModel {
     fun updateTheme(themeInfo: ThemeInfo): LiveData<Rlt<Any>>
     fun downloadTheme(
         themeResUrl: String,
-        dynamicThemeResourceType: DynamicThemeResourceType,
-    ): LiveData<Rlt<String>>
+    ): LiveData<Rlt<WeFile>>
     fun addStaticTheme(imgPath: String, payToAdd: Boolean? = null): LiveData<Rlt<List<ThemeInfo>>>
     fun addDynamicTheme(videoPath: String, payToAdd: Boolean? = null): LiveData<Rlt<List<ThemeInfo>>>
     fun deleteTheme(themeId: Long): LiveData<Rlt<Any>>

+ 27 - 6
app/src/main/java/com/adealink/weparty/network/NetworkConfig.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.network
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.base.IError
 import com.adealink.frame.locale.country.getNewCountryCode
 import com.adealink.frame.locale.language.languageManager
@@ -50,7 +50,7 @@ class NetworkConfig : INetworkConfig {
     override val baseUrl: String
         get() {
             return when {
-                AppBaseInfo.isRelease -> "https://${getLocalHost()}/api/"
+                AppBase.isRelease -> "https://${getLocalHost()}/api/"
                 else -> DebugPrefs.httpUrl
             }
         }
@@ -58,7 +58,7 @@ class NetworkConfig : INetworkConfig {
     override val wssUrl: String
         get() {
             return when {
-                AppBaseInfo.isRelease -> "wss://${getLocalHost()}/api/websocket"
+                AppBase.isRelease -> "wss://${getLocalHost()}/api/websocket"
                 else -> DebugPrefs.socketUrl
             }
         }
@@ -71,14 +71,14 @@ class NetworkConfig : INetworkConfig {
     override val hardcodeMainHosts: List<String>
         get() {
             return when {
-                AppBaseInfo.isRelease -> RELEASE_HOSTS
+                AppBase.isRelease -> RELEASE_HOSTS
                 else -> listOf(getHost(DebugPrefs.httpUrl))
             }
         }
     override val hardcodeBackupHosts: List<String>
         get() {
             return when {
-                AppBaseInfo.isRelease -> BACKUP_HOSTS
+                AppBase.isRelease -> BACKUP_HOSTS
                 else -> listOf()
             }
         }
@@ -98,16 +98,33 @@ class NetworkConfig : INetworkConfig {
         get() = App.instance.deviceIdService.getMemDeviceId()
     override val packageName: String
         get() = PackageUtil.getPackageName()
+
+    // 缓存时间一般不会很长, 一般是1-3分钟. 加入首页, 房间用到的域名即可
+    override val preloadDomains: List<String>
+        get() = buildList {
+            addAll(RELEASE_HOSTS)
+            add(CDN_HOST)
+        }
+
     override val protocolCachePath: String
-        get() = FilePath.httpCachePath ?: ""
+        get() = FilePath.httpCachePath
     override val protocolCacheSize: Long
         get() = 10 * 1024 * 1024
     override val token: String
         get() = AccountModule.token
+    override val uid: Long
+        get() = AccountModule.uid
     override val userRegion: String
         get() = ProfileModule.getMyUserInfo()?.region ?: ""
     override val versionCode: String
         get() = BuildConfig.VERSION_CODE.toString()
+
+    override val webCachePath: String
+        get() = FilePath.webPath
+
+    override val webCacheSize: Long
+        get() = 50 * 1024 * 1024 // 50M
+
     override val loggedIn: Boolean
         get() = AccountModule.isLogin()
 
@@ -142,6 +159,10 @@ class NetworkConfig : INetworkConfig {
         }
     }
 
+    override fun getExtraHeaders(): Map<String, String>? {
+        return null
+    }
+
     override fun onNetworkResponseError(code: Int, msg: String?, data: Any?) {
         when (code) {
             ServerCode.TOKEN_EXPIRE.code -> {

+ 0 - 10
app/src/main/java/com/adealink/weparty/network/NetworkConfig.kt.rej

@@ -1,10 +0,0 @@
-diff a/app/src/main/java/com/adealink/weparty/network/NetworkConfig.kt b/app/src/main/java/com/adealink/weparty/network/NetworkConfig.kt	(rejected hunks)
-@@ -151,7 +151,7 @@ class NetworkConfig : INetworkConfig {
-         event.country = getDeviceCountryCode()
-         event.isp = getNetworkOperator()
-         Log.d("tag_serve_report", "reportWebSocketEvent, event:${event}")
--        CoroutineScope(Dispatcher.WENEXT_THREAD_POOL).launch {
-+        CoroutineScope(Dispatcher.WENEXT_THREAD_POOL).launch {
-             statHttpService.reportWebSocket(event)
-         }
-     }

+ 2 - 2
app/src/main/java/com/adealink/weparty/network/NetworkEnv.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.network
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 
 
 /**
@@ -23,7 +23,7 @@ val WEB_PRIMARY_DOMAINS = listOf(
 )
 
 fun getLocalHost(): String {
-    return if (AppBaseInfo.isRelease) {
+    return if (AppBase.isRelease) {
         RELEASE_HOSTS[0]
     } else {
         DEBUG_HOST_CN

+ 19 - 0
app/src/main/java/com/adealink/weparty/push/PushMessageManager.kt

@@ -1,13 +1,32 @@
 package com.adealink.weparty.push
 
 import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.coroutine.dispatcher.Dispatcher
+import com.adealink.frame.data.json.froJsonErrorNull
+import com.adealink.frame.log.data.NotifyLogType
+import com.adealink.frame.log.data.ReportLogReason
 import com.adealink.frame.push.data.PushMessage
 import com.adealink.frame.util.AppUtil
+import com.adealink.weparty.App
 import com.adealink.weparty.R
+import com.adealink.weparty.push.data.PushMessageType
 import com.adealink.weparty.push.data.WeNextPushMessage
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 object PushMessageManager {
     fun processPushMessage(pushMessage: PushMessage) {
+        if (pushMessage.messageType == PushMessageType.UPLOAD_USER_LOG.type) {
+            CoroutineScope(Dispatcher.WENEXT_THREAD_POOL).launch {
+                App.instance.logService.uploadLog(
+                    ReportLogReason.Notify(
+                        NotifyLogType.PUSH,
+                        froJsonErrorNull(pushMessage.pushContent)
+                    )
+                )
+            }
+            return
+        }
         PushStatEvent(PushStatEvent.Action.RECEIVE).apply {
             type to "${pushMessage.messageType}"
             pushId to "${pushMessage.pushId}"

+ 1 - 0
app/src/main/java/com/adealink/weparty/push/data/PushData.kt

@@ -14,6 +14,7 @@ import com.google.gson.annotations.GsonNullable
 import com.google.gson.annotations.SerializedName
 
 enum class PushMessageType(val type: Long) {
+    UPLOAD_USER_LOG(-2), //上传用户日志
     ACTIVITY(5), //自建活动
     IM(40), //1v1会话提示
     SEND_GIFT(41), //送礼提示

+ 2 - 2
app/src/main/java/com/adealink/weparty/router/RouterConfig.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.router
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.router.config.IRouterConfig
 import com.adealink.weparty.BuildConfig
 
@@ -9,7 +9,7 @@ import com.adealink.weparty.BuildConfig
  */
 class RouterConfig : IRouterConfig {
 
-    override val scheme: String = AppBaseInfo.deeplinkScheme
+    override val scheme: String = AppBase.deeplinkScheme
 
     override val host: String = BuildConfig.DEEP_LINK_HOST
 

+ 0 - 22
app/src/main/java/com/adealink/weparty/security/SecurityConfig.kt

@@ -1,31 +1,9 @@
 package com.adealink.weparty.security
 
-import com.adealink.frame.log.ILog
-import com.adealink.frame.log.Log
 import com.adealink.frame.security.config.ISecurityConfig
-import com.adealink.weparty.storage.file.FilePath
 
 class SecurityConfig : ISecurityConfig {
-    override val log: ILog
-        get() = object : ILog {
-
-            override fun logD(tag: String, msg: String) {
-                Log.d(tag, msg)
-            }
-
-            override fun logI(tag: String, msg: String) {
-                Log.i(tag, msg)
-            }
-
-            override fun logE(tag: String, msg: String, e: Exception?) {
-                Log.e(tag, msg, e)
-            }
-
-        }
 
     override val remoteVirtualAppConfigUrl: String
         get() = "https://inchat-resource.wenext.media/security_config/blacklist_packages.json"
-
-    override val virtualAppConfigPath: String
-        get() = FilePath.virtualAppConfigPath.toString()
 }

+ 1 - 1
app/src/main/java/com/adealink/weparty/share/CommonShareFragment.kt

@@ -52,7 +52,7 @@ class CommonShareFragment: BaseFragment(R.layout.layout_common_share) {
             showToast(getCompatString(R.string.common_thanks_share))
         }
 
-        override fun onShareFailed(channel: ShareChannel, code: Int) {
+        override fun onShareFailed(channel: ShareChannel, code: Int, msg: String?) {
             (activity as? BaseActivity)?.dismissLoading()
             if (code == SHARE_FAIL_CODE_NO_INSTALL) {
                 showToast(getCompatString(R.string.common_no_install, ShareModule.getShareChannelName(channel)))

+ 0 - 4
app/src/main/java/com/adealink/weparty/share/ShareConfig.kt

@@ -4,16 +4,12 @@ import com.adealink.frame.share.IShareConfig
 import com.adealink.frame.share.data.DynamicLinkType
 import com.adealink.weparty.BuildConfig
 import com.adealink.weparty.module.share.ShareModule
-import com.adealink.weparty.storage.file.FilePath
 
 /**
  * Created by sunxiaodong on 2022/10/15.
  */
 class ShareConfig : IShareConfig {
 
-    override val shareImagePath: String
-        get() = FilePath.shareImagePath ?: ""
-
     override val httpDeepLinkHost: String = BuildConfig.HTTP_DEEP_LINK_HOST
 
     override val iOSPackageName: String = "com.partyjoy.yoki"

+ 4 - 0
app/src/main/java/com/adealink/weparty/sound/SoundPlayerConfig.kt

@@ -53,6 +53,10 @@ class SoundPlayerConfig : ISoundPlayerConfig, IMediaSdkSoundEffect {
         App.instance.mediaService.resumeSoundEffect(effectId)
     }
 
+    override fun setSoundEffectRate(soundId: Int, rate: Float) {
+        App.instance.mediaService.setSoundEffectRate(soundId, rate)
+    }
+
     override fun stopSoundEffect(effectId: Int) {
         App.instance.mediaService.stopSoundEffect(effectId)
     }

+ 39 - 31
app/src/main/java/com/adealink/weparty/sound/UserProfileSoundViewModel.kt

@@ -1,9 +1,11 @@
 package com.adealink.weparty.sound
 
 import androidx.lifecycle.LiveData
+import com.adealink.frame.base.CommonDataNullError
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.data.json.gson
 import com.adealink.frame.download.manager.downloadManager
+import com.adealink.frame.download.task.TaskPriority
 import com.adealink.frame.log.Log
 import com.adealink.frame.mvvm.livedata.ExtMutableLiveData
 import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
@@ -24,7 +26,6 @@ import com.adealink.weparty.module.profile.decorate.data.DecorType
 import com.adealink.weparty.module.profile.decorate.data.ProfileMusicConfig
 import com.adealink.weparty.module.profile.decorate.data.ProfileMusicDecor
 import com.adealink.weparty.sound.manager.soundManager
-import com.adealink.weparty.storage.file.FilePath
 import kotlinx.coroutines.launch
 import java.io.File
 
@@ -38,8 +39,8 @@ class UserProfileSoundViewModel : BaseSoundViewModel() {
 
     val currentMusicConfig = ExtMutableLiveData<ProfileMusicConfig?>()
 
-    //下载到本地的音乐文件名,audio目录下
-    var currentSoundName = ""
+    //下载到本地的音乐路径
+    var currentSoundPath = ""
 
 
     fun getProfileMusic(uid: Long) {
@@ -64,15 +65,16 @@ class UserProfileSoundViewModel : BaseSoundViewModel() {
         Log.i(TAG_MUSIC, "downloadAndPlayMusic url=$url")
         val onceMutableLiveData = OnceMutableLiveData<String>()
         viewModelScope.launch {
-            val saveDir = FilePath.audioPath ?: return@launch
             val downloadRlt = downloadManager.downloadResource(
-                dir = saveDir,
                 url = url,
+                TaskPriority.NORMAL,
             )
             Log.logRltD(TAG_MUSIC, "downloadAndPlayMusic", downloadRlt)
             if (downloadRlt is Rlt.Success) {
-                val soundName = File(downloadRlt.data).name
-                onceMutableLiveData.send(soundName)
+                downloadRlt.data.use()?.let { path ->
+                    val soundPath = File(path).absolutePath
+                    onceMutableLiveData.send(soundPath)
+                }
             }
         }
         return onceMutableLiveData
@@ -91,7 +93,7 @@ class UserProfileSoundViewModel : BaseSoundViewModel() {
         viewModelScope.launch {
 
             var mp3RemoteUrl = ""
-            var mp3LocalPath = ""
+            var mp3LocalPath: String? = null
             if (musicItem.isLocalMusic()) {
                 //上传音乐
                 val uploadRlt = App.instance.ossService.suspendUploadFile(
@@ -115,16 +117,22 @@ class UserProfileSoundViewModel : BaseSoundViewModel() {
                 mp3LocalPath = musicItem.path
             } else {
                 mp3RemoteUrl = musicItem.url
-                val saveDir = FilePath.audioPath ?: return@launch
                 val downloadRlt = downloadManager.downloadResource(
-                    dir = saveDir,
                     url = musicItem.url,
+                    TaskPriority.NORMAL
                 )
-                if (downloadRlt !is Rlt.Success) {
+                if (downloadRlt is Rlt.Failed) {
                     onceMutableLiveData.send(downloadRlt)
                     return@launch
                 }
-                mp3LocalPath = downloadRlt.data
+                if (downloadRlt is Rlt.Success) {
+                    mp3LocalPath = downloadRlt.data.use()
+                }
+            }
+
+            if (mp3LocalPath.isNullOrEmpty()) {
+                onceMutableLiveData.send(Rlt.Failed(CommonDataNullError()))
+                return@launch
             }
 
             val md5 = fileMd5(File(mp3LocalPath))
@@ -142,7 +150,7 @@ class UserProfileSoundViewModel : BaseSoundViewModel() {
             )
             if (updateRlt is Rlt.Success) {
                 currentMusicConfig.send(profileMusicConfig)
-                onceMutableLiveData.send(Rlt.Success(File(mp3LocalPath).name))
+                onceMutableLiveData.send(Rlt.Success(File(mp3LocalPath).absolutePath))
             } else {
                 onceMutableLiveData.send(Rlt.Failed((updateRlt as Rlt.Failed).error))
             }
@@ -177,20 +185,20 @@ class UserProfileSoundViewModel : BaseSoundViewModel() {
 
 
     fun playMusic(localFileName: String) {
-        Log.i(TAG_MUSIC, "playMusic soundName=$localFileName")
-        currentSoundName = localFileName
-        if (currentSoundName.isNotEmpty()) {
-            if (soundManager.isStop(currentSoundName)) {
-                soundManager.playCanInBg(
+        Log.i(TAG_MUSIC, "playMusic localFilePath=${currentSoundPath}")
+        currentSoundPath = localFileName
+        if (currentSoundPath.isNotEmpty()) {
+            if (soundManager.isStop(currentSoundPath)) {
+                soundManager.playPathCanInBg(
                     scene = SoundScene.UserProfile,
-                    soundName = localFileName,
+                    filePath = localFileName,
                     soundType = SoundType.MUSIC,
                     priority = SoundPriority.HIGH,
                     loop = SOUND_LOOP_INFINITE,
                     playerType = PlayerType.SYSTEM_MEDIA
                 )
             } else {
-                soundManager.resume(scene, currentSoundName)
+                soundManager.resume(scene, currentSoundPath)
             }
         }
     }
@@ -198,34 +206,34 @@ class UserProfileSoundViewModel : BaseSoundViewModel() {
     fun playOrPauseMusic() {
         Log.i(
             TAG_MUSIC,
-            "playOrPauseMusic soundName=$currentSoundName, isResume:${
-                soundManager.isResume(
-                    currentSoundName
+            "playOrPauseMusic localFilePath=${currentSoundPath}, isPlay:${
+                soundManager.isPlay(
+                    currentSoundPath
                 )
             }"
         )
 
-        if (soundManager.isResume(currentSoundName)) {
+        if (soundManager.isPlay(currentSoundPath) || soundManager.isResume(currentSoundPath)) {
             pauseMusic()
         } else {
-            playMusic(currentSoundName)
+            playMusic(currentSoundPath)
         }
     }
 
     fun isPlayingMusic(): Boolean {
-        return soundManager.isResume(currentSoundName)
+        return soundManager.isResume(currentSoundPath)
     }
 
     fun stopMusic() {
-        if (currentSoundName.isNotEmpty()) {
-            soundManager.stop(currentSoundName)
+        if (currentSoundPath.isNotEmpty()) {
+            soundManager.stop(currentSoundPath)
         }
-        currentSoundName = ""
+        currentSoundPath = ""
     }
 
     fun pauseMusic() {
-        if (currentSoundName.isNotEmpty()) {
-            soundManager.pause(currentSoundName)
+        if (currentSoundPath.isNotEmpty()) {
+            soundManager.pause(currentSoundPath)
         }
     }
 }

+ 9 - 0
app/src/main/java/com/adealink/weparty/sound/manager/ISoundManager.kt

@@ -39,6 +39,15 @@ interface ISoundManager : IBaseFrame<ISoundListener> {
         playerType: PlayerType? = null
     )
 
+    fun playPathCanInBg(
+        scene: SoundScene,
+        filePath: String,
+        soundType: SoundType,
+        priority: SoundPriority,
+        loop: Int,
+        playerType: PlayerType? = null
+    )
+
     fun resume(scene: SoundScene, soundName: String)
 
     fun resumeAll(scene: SoundScene, soundNames: Set<String>)

+ 18 - 0
app/src/main/java/com/adealink/weparty/sound/manager/SoundManager.kt

@@ -156,6 +156,24 @@ class SoundManager : BaseFrame<ISoundListener>(), ISoundManager {
         App.instance.soundPlayer.playCanInBg(fileName, soundType, priority, loop, playerType)
     }
 
+    override fun playPathCanInBg(
+        scene: SoundScene,
+        filePath: String,
+        soundType: SoundType,
+        priority: SoundPriority,
+        loop: Int,
+        playerType: PlayerType?
+    ) {
+        if (scene == SoundScene.Global && !globalSoundOpen) {
+            return
+        }
+        val sceneSoundOpen = sceneSoundSettings[scene.value] ?: true
+        if (!sceneSoundOpen) {
+            return
+        }
+        App.instance.soundPlayer.playPathCanInBg(filePath, soundType, priority, loop, playerType)
+    }
+
     override fun resume(scene: SoundScene, soundName: String) {
         if (scene == SoundScene.Global &&!globalSoundOpen) {
             return

+ 2 - 2
app/src/main/java/com/adealink/weparty/stat/data/StatData.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.stat.data
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.util.PackageUtil
 import com.adealink.frame.util.getDeviceName
 import com.google.gson.annotations.SerializedName
@@ -71,7 +71,7 @@ data class ClientFatalErrorReportReq(
     @SerializedName("sid") var sid: Long? = null,//用户ID-可以为空
     @SerializedName("region") var region: String? = null,
     @SerializedName("country") var country: String? = null,
-    @SerializedName("platform") var platform: String = AppBaseInfo.platform,// ios/android
+    @SerializedName("platform") var platform: String = AppBase.platform,// ios/android
     @SerializedName("packName") var packName: String = PackageUtil.getPackageName(),//包名
     @SerializedName("clientVersion") var clientVersion: String = PackageUtil.getVersionCode().toString(),//客户端版本
 )

+ 4 - 4
app/src/main/java/com/adealink/weparty/stat/standard/StandardStatEvent.kt

@@ -1,6 +1,6 @@
 package com.adealink.weparty.stat.standard
 
-import com.adealink.frame.base.AppBaseInfo
+import com.adealink.frame.base.AppBase
 import com.adealink.frame.coroutine.dispatcher.Dispatcher
 import com.adealink.weparty.module.wallet.data.ProductInfo
 import com.adealink.frame.coroutine.dispatcher.Dispatcher.submit
@@ -13,7 +13,7 @@ object StandardStatEvent {
     private val serialHandler = Dispatcher.getSerialHandler()
 
     fun reportPurchase(productInfo: ProductInfo, orderId: String, thirdPartyOrderId: String) {
-        if (!AppBaseInfo.isRelease) {
+        if (!AppBase.isRelease) {
             return
         }
         serialHandler.submit({
@@ -26,7 +26,7 @@ object StandardStatEvent {
     }
 
     fun reportRegister(type: String) {
-        if (!AppBaseInfo.isRelease) {
+        if (!AppBase.isRelease) {
             return
         }
         serialHandler.submit({
@@ -35,7 +35,7 @@ object StandardStatEvent {
     }
 
     fun reportOpenAppSecondDay() {
-        if (!AppBaseInfo.isRelease) {
+        if (!AppBase.isRelease) {
             return
         }
         serialHandler.submit({

+ 16 - 0
app/src/main/java/com/adealink/weparty/storage/CacheSubDir.kt

@@ -0,0 +1,16 @@
+package com.adealink.weparty.storage
+
+import com.adealink.frame.storage.file.ICacheSubDir
+
+enum class AppCacheResource(val value: String) {
+    Emotion("emotion"),
+    SKIN("skin");
+
+    fun getCacheSubDir(resourceId: String): ICacheSubDir {
+        return object : ICacheSubDir {
+            override fun appUniqueDirName(): String {
+                return "${value}_$resourceId"
+            }
+        }
+    }
+}

+ 47 - 12
app/src/main/java/com/adealink/weparty/storage/config/StorageConfig.kt

@@ -1,35 +1,38 @@
 package com.adealink.weparty.storage.config
 
-import com.adealink.frame.log.ILog
-import com.adealink.frame.log.Log
+import com.adealink.frame.coroutine.dispatcher.Dispatcher
 import com.adealink.frame.stat.IStat
 import com.adealink.frame.storage.config.IStorageConfig
+import com.adealink.frame.storage.file.IFileStorageConfig
+import com.adealink.frame.util.ONE_MINUTE
+import com.adealink.frame.util.deleteFiles
+import com.adealink.frame.util.runOnUiThread
 import com.adealink.weparty.storage.file.FilePath
 import com.adealink.weparty.App
 import com.adealink.weparty.storage.stat.StorageStatEvent
+import java.io.File
 
 /**
  * Created by sunxiaodong on 2021/12/12.
  */
-class StorageConfig : IStorageConfig, ILog, IStat {
+class StorageConfig : IStorageConfig, IStat {
+
+    init {
+        runOnUiThread({
+            clearOldStorage()
+        }, 5 * ONE_MINUTE)
+    }
 
     override val spRootDir: String?
         get() = FilePath.spPath
-    override val log: ILog = this
     override val stat: IStat = this
     override val deviceId: String
         get() = App.instance.deviceIdService.getMemDeviceId() //这里只能使用mem device id,不要从sp中加载,避免mmkv错误引入的循环调用堆栈溢出
 
-    override fun logD(tag: String, msg: String) {
-        Log.d(tag, msg)
-    }
+    override val fileStorageConfig: IFileStorageConfig = object : IFileStorageConfig {
 
-    override fun logI(tag: String, msg: String) {
-        Log.i(tag, msg)
-    }
+        override val cacheMaxSize: Long = 500 * 1024 * 1024
 
-    override fun logE(tag: String, msg: String, e: Exception?) {
-        Log.e(tag, msg, e)
     }
 
     override fun stat(events: Map<String, String>) {
@@ -40,4 +43,36 @@ class StorageConfig : IStorageConfig, ILog, IStat {
             .send()
     }
 
+    private fun clearOldStorage() {
+        Dispatcher.wenextThreadPoolExecutor.submit {
+            val dirList = arrayListOf(
+                FilePath.oldGiftPath,
+                FilePath.oldEmotionPath,
+                FilePath.oldMusicPath,
+                FilePath.oldThemePath,
+                FilePath.oldSkinPath,
+                FilePath.oldCarPath,
+                FilePath.oldActivityPath,
+                FilePath.oldRocketPath,
+                FilePath.oldLevelPath,
+                FilePath.oldCpPath,
+                FilePath.oldVideoPath,
+                FilePath.oldEffectPath,
+                FilePath.oldBackupEffectPath,
+                FilePath.oldLabelPath,
+                FilePath.oldWeddingPath,
+                FilePath.oldFamilyPath,
+                )
+            for (dir in dirList) {
+                dir.let {
+                    try {
+                        deleteFiles(File(it))
+                    } catch (_: Exception) {
+
+                    }
+                }
+            }
+        }
+    }
+
 }

+ 35 - 104
app/src/main/java/com/adealink/weparty/storage/file/FilePath.kt

@@ -1,8 +1,10 @@
 package com.adealink.weparty.storage.file
 
+import com.adealink.frame.storage.file.Path
+import com.adealink.frame.storage.file.privateCachePath
+import com.adealink.frame.storage.file.privateFilesPath
+import com.adealink.frame.storage.file.publicFilesPath
 import com.adealink.frame.util.AppUtil
-import com.adealink.frame.util.createOrExistsDir
-import com.adealink.frame.util.isExternalStorageAvailable
 import java.io.File
 
 /**
@@ -10,141 +12,70 @@ import java.io.File
  */
 object FilePath {
 
-    class Path(val path: String, private val parentPath: String? = null) {
-        val absolutePath: String = ""
-            get() {
-                if (field.isNullOrEmpty().not()) {
-                    return field
-                }
-
-                val absPath: StringBuilder = StringBuilder()
-                if (parentPath.isNullOrEmpty().not()) {
-                    absPath.append(parentPath).append(File.separator)
-                }
-                absPath.append(path).append(File.separator)
-                val fullPath = absPath.toString()
-                return if (createOrExistsDir(fullPath)) {
-                    fullPath
-                } else {
-                    privateCachePath
-                }
-            }
-    }
-
-    /**
-     * 在一个应用私有的目录下生成一个文件路径,其他应用无法访问到该目录,用于存放对安全性比较敏感的文件
-     */
-    private val privateFilesPath by lazy { AppUtil.appContext.filesDir.absolutePath }
-
-    /**
-     * 在一个应用私有的目录下生成一个缓存路径,其他应用无法访问到该目录。
-     * 用于存放对安全性比较敏感的文件,该目录下的文件在系统存储空间不足时,很可能被系统清理掉,所以该目录主要用于存放临时文件。
-     */
-    private val privateCachePath by lazy { AppUtil.appContext.cacheDir.absolutePath }
-
-    /**
-     * 在一个公有的目录下生成一个缓存路径,其他应用都可以访问到该目录。
-     * 用于存放对对安全性不敏感的文件,比如图片,视频,音乐等
-     */
-    private val publicFilesPath by lazy {
-        if (isExternalStorageAvailable()) {
-            AppUtil.appContext.getExternalFilesDir(null)?.absolutePath ?: privateFilesPath
-        } else {
-            privateFilesPath
-        }
-    }
-
-    /**
-     * 在一个公有的目录下生成一个缓存路径,其他应用都可以访问到该目录。
-     * 用于存放对对安全性不敏感的文件,该目录下的文件在系统存储空间不足时,很可能被系统清理掉,所以该目录主要用于存放临时文件
-     */
-    private val publicCachePath by lazy {
-        if (isExternalStorageAvailable()) {
-            AppUtil.appContext.externalCacheDir?.absolutePath ?: privateCachePath
-        } else {
-            privateCachePath
-        }
-    }
-
-    val giftPath by lazy { Path("gift", privateFilesPath).absolutePath }
-
-    val imagePath by lazy { Path("image", publicFilesPath).absolutePath }
-
-    val tempImagePath by lazy { Path("temp", privateFilesPath).absolutePath }
-
     val clipImagePath by lazy { Path("clip_image", publicFilesPath).absolutePath }
 
     val takePhotoImagePath by lazy { Path("take_photo", publicFilesPath).absolutePath }
 
     val spPath by lazy { Path("sp", privateFilesPath).absolutePath }
 
-    val releaseXlogPath by lazy { Path("xlog", privateFilesPath).absolutePath }
-
-    val backupXlogPath by lazy { "${AppUtil.appContext.filesDir}${File.separator}xlog" }
-
-    val xlogZipPath by lazy { Path("xlogz", publicFilesPath).absolutePath }
-
-    val emotionPath by lazy { Path("emotion", publicFilesPath).absolutePath }
-
     val shareImagePath by lazy { Path("share_image", publicFilesPath).absolutePath }
 
-    val musicPath by lazy { Path("music", publicFilesPath).absolutePath }
-
-    val logPath by lazy { releaseXlogPath ?: backupXlogPath }
-
-    val logCachePath by lazy { "${AppUtil.appContext.filesDir}${File.separator}xlog-cache" }
+    val filePath by lazy { Path("file", publicFilesPath).absolutePath }
 
-    val imageProgressPath by lazy { Path("image_progress", publicFilesPath).absolutePath }
+    val webPath by lazy { Path("web", publicFilesPath).absolutePath }
 
-    val videoProgressPath by lazy { Path("video_progress", publicFilesPath).absolutePath }
+    val audioPath by lazy { Path("audio", publicFilesPath).absolutePath }
 
-    val themePath by lazy { Path("theme", publicFilesPath).absolutePath }
+    val recordPath by lazy { Path("record", publicFilesPath).absolutePath }
 
-    val filePath by lazy { Path("file", publicFilesPath).absolutePath }
+    val offlineH5 by lazy { Path("offline_h5", publicFilesPath).absolutePath }
 
-    val skinPath by lazy { Path("skin", publicFilesPath).absolutePath }
+    val httpCachePath by lazy { Path("http_cache", privateCachePath).absolutePath }
 
-    val carPath by lazy { Path("car", publicFilesPath).absolutePath }
+    val gameHubPath by lazy { Path("game_hub", publicFilesPath).absolutePath }
 
-    val videoPath by lazy { Path("video", publicFilesPath).absolutePath }
+    val gameSkinPath by lazy { Path("game_skin", privateFilesPath).absolutePath }
 
-    val webPath by lazy { Path("web", publicFilesPath).absolutePath }
+    val defaultGameSkinPath by lazy { Path("default_game_skin", privateFilesPath).absolutePath }
 
-    val activityPath by lazy { Path("activity", publicFilesPath).absolutePath }
+    val certification by lazy { Path("certification", privateFilesPath).absolutePath }
 
-    val rocketPath by lazy { Path("rocket", publicFilesPath).absolutePath }
+    val videoCachePath by lazy { Path("video_cache", publicFilesPath).absolutePath }
 
-    val levelPath by lazy { Path("level", publicFilesPath).absolutePath }
+    /**start------以下路径不再使用-----**/
+    val oldGiftPath by lazy { Path("gift", privateFilesPath).absolutePath }
 
-    val audioPath by lazy { Path("audio", publicFilesPath).absolutePath }
+    val oldEmotionPath by lazy { Path("emotion", publicFilesPath).absolutePath }
 
-    val recordPath by lazy { Path("record", publicFilesPath).absolutePath }
+    val oldMusicPath by lazy { Path("music", publicFilesPath).absolutePath }
 
-    val offlineH5 by lazy { Path("offline_h5", publicFilesPath).absolutePath }
+    val oldThemePath by lazy { Path("theme", publicFilesPath).absolutePath }
 
-    val cpPath by lazy { Path("cp", publicFilesPath).absolutePath }
+    val oldSkinPath by lazy { Path("skin", publicFilesPath).absolutePath }
 
-    val familyPath by lazy { Path("family", publicFilesPath).absolutePath }
+    val oldCarPath by lazy { Path("car", publicFilesPath).absolutePath }
 
-    val weddingPath by lazy { Path("wedding", publicFilesPath).absolutePath }
+    val oldVideoPath by lazy { Path("video", publicFilesPath).absolutePath }
 
-    val httpCachePath by lazy { Path("http_cache", privateCachePath).absolutePath }
+    val oldActivityPath by lazy { Path("activity", publicFilesPath).absolutePath }
 
-    val effectPath by lazy { Path("effect", privateCachePath).absolutePath }
+    val oldRocketPath by lazy { Path("rocket", publicFilesPath).absolutePath }
 
-    val backupEffectPath by lazy { "${AppUtil.appContext.filesDir}${File.separator}effect"}
+    val oldLevelPath by lazy { Path("level", publicFilesPath).absolutePath }
 
-    val tcMediaXLog by lazy { Path("TCMediaXLog", publicFilesPath).absolutePath }
+    val oldCpPath by lazy { Path("cp", publicFilesPath).absolutePath }
 
-    val gameHubPath by lazy { Path("game_hub", publicFilesPath).absolutePath }
+    val oldEffectPath by lazy { Path("effect", privateCachePath).absolutePath }
 
-    val gameSkinPath by lazy { Path("game_skin", privateFilesPath).absolutePath }
+    val oldBackupEffectPath by lazy { "${AppUtil.appContext.filesDir}${File.separator}effect"}
 
-    val defaultGameSkinPath by lazy { Path("default_game_skin", privateFilesPath).absolutePath }
+    val oldLabelPath by lazy { Path("label", privateCachePath).absolutePath }
 
-    val virtualAppConfigPath by lazy { Path("virtualAppConfigPath", privateFilesPath).absolutePath }
+    val oldWeddingPath by lazy { Path("wedding", publicFilesPath).absolutePath }
 
-    val labelPath by lazy { Path("label", privateCachePath).absolutePath }
+    val oldFamilyPath by lazy { Path("family", publicFilesPath).absolutePath }
 
-    val certification by lazy { Path("certification", privateFilesPath).absolutePath }
+    // TODO 过几个版本再做清理
+    val oldReleaseXlogPath by lazy { Path("xlog", privateFilesPath).absolutePath }
+    /**end------以下路径不再使用-----**/
 }

Some files were not shown because too many files changed in this diff