diff --git a/application/app/build.gradle b/application/app/build.gradle index c2e31d66..21e6a0ee 100644 --- a/application/app/build.gradle +++ b/application/app/build.gradle @@ -3,12 +3,12 @@ apply plugin: 'kotlin-android' android { namespace 'com.tencent.uikit.app' - compileSdk rootProject.compileSdkVersion + compileSdk 34 defaultConfig { applicationId "com.trtc.uikit.livekit.example" - minSdkVersion rootProject.minSdkVersion - targetSdkVersion rootProject.targetSdkVersion + minSdkVersion 21 + targetSdkVersion 34 versionCode 1 versionName "1.0" } @@ -30,6 +30,10 @@ android { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17 + } } dependencies { diff --git a/application/app/src/main/java/com/tencent/uikit/app/main/MainFragment.kt b/application/app/src/main/java/com/tencent/uikit/app/main/MainFragment.kt index 7a80d538..de93d24a 100644 --- a/application/app/src/main/java/com/tencent/uikit/app/main/MainFragment.kt +++ b/application/app/src/main/java/com/tencent/uikit/app/main/MainFragment.kt @@ -3,7 +3,6 @@ package com.tencent.uikit.app.main import android.content.Intent import android.os.Bundle import android.text.TextUtils -import android.util.DisplayMetrics import android.util.Log import android.view.LayoutInflater import android.view.View @@ -14,20 +13,14 @@ import androidx.fragment.app.Fragment import androidx.navigation.Navigation import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.tencent.imsdk.v2.V2TIMManager -import com.tencent.imsdk.v2.V2TIMValueCallback import com.tencent.qcloud.tuicore.TUIConstants import com.tencent.qcloud.tuicore.TUICore import com.tencent.qcloud.tuicore.TUILogin import com.tencent.qcloud.tuicore.TUIThemeManager import com.tencent.qcloud.tuicore.interfaces.ITUINotification import com.tencent.uikit.app.R -import com.tencent.uikit.app.main.call.GroupCallActivity -import com.tencent.uikit.app.main.live.LiveActivity -import com.trtc.uikit.roomkit.RoomHomeActivity import io.trtc.tuikit.atomicx.widget.basicwidget.avatar.AtomicAvatar import io.trtc.tuikit.atomicx.widget.basicwidget.avatar.AtomicAvatar.AvatarContent -import org.json.JSONObject class MainFragment : Fragment() { private var userCenter: AtomicAvatar? = null @@ -71,7 +64,7 @@ class MainFragment : Fragment() { userCenter?.setOnClickListener { v: View? -> navController.navigate(R.id.mine_fragment) } val trtcMainData = TRTCMainData() trtcMainAdapter = TRTCMainAdapter( - isSmallScreenDevice, TUIThemeManager.getInstance().currentLanguage, + TUIThemeManager.getInstance().currentLanguage, trtcMainData.itemDataList as MutableList, object : TRTCMainAdapter.OnItemClickListener { override fun onItemClick(mainItemData: MainItemData?) { mainItemData?.let { item -> @@ -80,7 +73,6 @@ class MainFragment : Fragment() { intent.putExtra("TITLE", getString(item.itemTitle)) intent.putExtra("TYPE", type) startActivity(intent) - observerTUI(item.itemTargetClass) } } }) @@ -95,36 +87,6 @@ class MainFragment : Fragment() { userCenter?.setContent(AvatarContent.URL(TUILogin.getFaceUrl(), R.drawable.app_ic_avatar)) } - private fun observerTUI(activity: Class<*>?) { - var type = 0L - if (activity == GroupCallActivity::class.java) { - type = 1303 - } else if (activity == LiveActivity::class.java) { - type = 1119 - } else if (activity == RoomHomeActivity::class.java) { - type = 1205 - } - - val param = JSONObject().apply { - put("UIComponentType", type) - }.toString() - V2TIMManager.getInstance() - .callExperimentalAPI("reportTUIFeatureUsage", param, object : V2TIMValueCallback { - override fun onSuccess(t: Any?) { - } - override fun onError(code: Int, desc: String?) { - Log.e(TAG, "reportFeatureUsage failed: $code $desc") - } - }) - } - - private val isSmallScreenDevice: Boolean - get() { - val displayMetrics = DisplayMetrics() - requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics) - return displayMetrics.widthPixels <= 720 - } - private fun registerEvent() { TUICore.registerEvent( TUIConstants.TUILogin.EVENT_LOGIN_STATE_CHANGED, @@ -165,7 +127,6 @@ class MainFragment : Fragment() { holder.icon.setImageResource(item.iconRes) holder.title.text = item.title holder.subtitle.text = item.subtitle - holder.tag.text = "" holder.itemView.setOnClickListener { onItemClick() } } @@ -174,7 +135,6 @@ class MainFragment : Fragment() { class SimpleVH(itemView: View) : RecyclerView.ViewHolder(itemView) { val icon: ImageView = itemView.findViewById(R.id.img_main_icon) val title: TextView = itemView.findViewById(R.id.tv_main_title) - val tag: TextView = itemView.findViewById(R.id.tv_main_tag) val subtitle: TextView = itemView.findViewById(R.id.tv_main_subtitle) } } diff --git a/application/app/src/main/java/com/tencent/uikit/app/main/TRTCMainAdapter.kt b/application/app/src/main/java/com/tencent/uikit/app/main/TRTCMainAdapter.kt index 2b70400c..46ae534a 100644 --- a/application/app/src/main/java/com/tencent/uikit/app/main/TRTCMainAdapter.kt +++ b/application/app/src/main/java/com/tencent/uikit/app/main/TRTCMainAdapter.kt @@ -14,7 +14,6 @@ import androidx.recyclerview.widget.RecyclerView import com.tencent.uikit.app.R class TRTCMainAdapter( - private val isSmallScreenDevice: Boolean, private val currentLanguage: String?, private val itemDataList: MutableList, private val onItemClickListener: OnItemClickListener @@ -24,7 +23,6 @@ class TRTCMainAdapter( if (position == itemCount - 1) { return ITEM_TYPE_FOOTER } - val item: MainItemData = itemDataList.get(position) return ITEM_TYPE_ITEM } @@ -46,7 +44,7 @@ class TRTCMainAdapter( override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is ItemViewHolder) { val item: MainItemData? = itemDataList[position] - holder.bind(isSmallScreenDevice, currentLanguage, item, onItemClickListener) + holder.bind(item, onItemClickListener) } else if (holder is WebViewHolder) { val item: MainItemData? = itemDataList[position] holder.bind(item, currentLanguage, onItemClickListener) @@ -65,11 +63,10 @@ class TRTCMainAdapter( private val imageIcon: ImageView = itemView.findViewById(R.id.img_main_icon) private val textTitle: TextView = itemView.findViewById(R.id.tv_main_title) private val textSubTitle: TextView = itemView.findViewById(R.id.tv_main_subtitle) - private val textTag: TextView = itemView.findViewById(R.id.tv_main_tag) private val constraintItem: ConstraintLayout = itemView.findViewById(R.id.cl_main_item) fun bind( - isSmallScreenDevice: Boolean, currentLanguage: String?, mainItemData: MainItemData?, + mainItemData: MainItemData?, onItemClickListener: OnItemClickListener ) { if (mainItemData == null) { @@ -80,10 +77,7 @@ class TRTCMainAdapter( mainItemData ) } - val category: MainItemData.Category? = mainItemData.category - textTag.visibility = if (category === MainItemData.Category.UNDEFINED) View.GONE else View.VISIBLE - textTag.setText(R.string.app_main_item_category_kit) - textTag.setBackgroundResource(R.drawable.app_bg_main_category_kit) + constraintItem.setBackgroundResource( if (mainItemData.category === MainItemData.Category.KIT) R.drawable.app_bg_main_kit_item @@ -93,21 +87,6 @@ class TRTCMainAdapter( textTitle.setText(mainItemData.itemTitle) imageIcon.setImageResource(mainItemData.itemResId) textSubTitle.setText(mainItemData.itemSubTitle) - val layoutParams = if (TextUtils.equals(currentLanguage, ENGLISH_LANGUAGE_CODE)) { - LinearLayout.LayoutParams( - dp2px(ENGLISH_TEXT_WIDTH_DP.toFloat()), - dp2px(ENGLISH_TEXT_HEIGHT_DP.toFloat()) - ) - } else { - LinearLayout.LayoutParams( - dp2px(DEFAULT_TEXT_WIDTH_DP.toFloat()), - dp2px(DEFAULT_TEXT_HEIGHT_DP.toFloat()) - ) - } - textTag.setLayoutParams(layoutParams) - if (isSmallScreenDevice) { - textTag.visibility = View.GONE - } } } @@ -115,7 +94,11 @@ class TRTCMainAdapter( private val textTitle: TextView = itemView.findViewById(R.id.tv_main_title) private val textSubTitle: TextView = itemView.findViewById(R.id.tv_main_subtitle) - fun bind(mainItemData: MainItemData?, currentLanguage: String?, onItemClickListener: OnItemClickListener) { + fun bind( + mainItemData: MainItemData?, + currentLanguage: String?, + onItemClickListener: OnItemClickListener + ) { if (mainItemData == null) { return } @@ -131,7 +114,11 @@ class TRTCMainAdapter( dp2px(DEFAULT_TEXT_HEIGHT_DP.toFloat()) ) } - itemView.setOnClickListener(View.OnClickListener { v: View? -> onItemClickListener.onItemClick(mainItemData) }) + itemView.setOnClickListener(View.OnClickListener { v: View? -> + onItemClickListener.onItemClick( + mainItemData + ) + }) textTitle.setText(mainItemData.itemTitle) textSubTitle.setText(mainItemData.itemSubTitle) } @@ -148,7 +135,11 @@ class TRTCMainAdapter( private const val DEFAULT_TEXT_WIDTH_DP = 32 private const val DEFAULT_TEXT_HEIGHT_DP = 18 private fun dp2px(dp: Float): Int { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().displayMetrics) + return TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp, + Resources.getSystem().displayMetrics + ) .toInt() } } diff --git a/application/app/src/main/java/com/tencent/uikit/app/main/call/GroupCallActivity.kt b/application/app/src/main/java/com/tencent/uikit/app/main/call/GroupCallActivity.kt index d0b88180..d5192e60 100644 --- a/application/app/src/main/java/com/tencent/uikit/app/main/call/GroupCallActivity.kt +++ b/application/app/src/main/java/com/tencent/uikit/app/main/call/GroupCallActivity.kt @@ -7,10 +7,12 @@ import android.view.View import android.widget.EditText import android.widget.RadioGroup import android.widget.RelativeLayout +import com.tencent.qcloud.tuicore.TUILogin import com.tencent.qcloud.tuikit.tuicallkit.TUICallKit import io.trtc.tuikit.atomicx.widget.basicwidget.toast.AtomicToast import com.tencent.uikit.app.R import com.tencent.uikit.app.main.BaseActivity +import com.trtc.tuikit.common.util.ToastUtil import io.trtc.tuikit.atomicxcore.api.call.CallMediaType import io.trtc.tuikit.atomicxcore.api.call.CallParams import java.util.Arrays diff --git a/application/app/src/main/java/com/tencent/uikit/app/main/call/SettingsActivity.kt b/application/app/src/main/java/com/tencent/uikit/app/main/call/SettingsActivity.kt index 07c28fa2..42218f9e 100644 --- a/application/app/src/main/java/com/tencent/uikit/app/main/call/SettingsActivity.kt +++ b/application/app/src/main/java/com/tencent/uikit/app/main/call/SettingsActivity.kt @@ -144,6 +144,7 @@ class SettingsActivity : BaseActivity() { SettingsConfig.isIncomingBanner = isChecked createInstance(application).enableIncomingBanner(isChecked) } + switchAISubtitle?.setOnCheckedChangeListener{ buttonView: CompoundButton?, isChecked: Boolean -> createInstance(application).enableAITranscriber(isChecked) } diff --git a/application/app/src/main/res/drawable/app_avatar.png b/application/app/src/main/res/drawable/app_avatar.png index 4ab41bae..f3afc4c2 100644 Binary files a/application/app/src/main/res/drawable/app_avatar.png and b/application/app/src/main/res/drawable/app_avatar.png differ diff --git a/application/app/src/main/res/drawable/app_ic_avatar.png b/application/app/src/main/res/drawable/app_ic_avatar.png index 4ab41bae..f3afc4c2 100644 Binary files a/application/app/src/main/res/drawable/app_ic_avatar.png and b/application/app/src/main/res/drawable/app_ic_avatar.png differ diff --git a/application/app/src/main/res/layout/app_activity_live.xml b/application/app/src/main/res/layout/app_activity_live.xml index 51c02cfb..0e0d0a25 100644 --- a/application/app/src/main/res/layout/app_activity_live.xml +++ b/application/app/src/main/res/layout/app_activity_live.xml @@ -19,8 +19,8 @@ android:singleLine="true" android:text="@string/app_main_item_live" android:textColor="@color/black" - android:textSize="18sp" - android:textStyle="bold" /> + android:textSize="@dimen/text_size_20" + android:fontFamily="sans-serif-medium" /> - - - - Create Interactive Video Live with Live API for a Seamless Streaming Experience. Voice Room Enable Interactive Voice Room with Live API for an Enhanced Communication Experience. - + You cannot call yourself, please use a different user ID \ No newline at end of file diff --git a/application/app/src/main/res/values-ja/strings.xml b/application/app/src/main/res/values-ja/strings.xml index 447dd9f6..675aa500 100644 --- a/application/app/src/main/res/values-ja/strings.xml +++ b/application/app/src/main/res/values-ja/strings.xml @@ -99,5 +99,6 @@ ライブAPIを介してインタラクティブなビデオライブストリーミングを構築して、明確でスムーズなライブストリーミングエクスペリエンスを提供します。 言語チャットルーム Live APIを使用してインタラクティブな音声チャットルームを構築して、低レイテンシと高品質のエクスペリエンスを提供します。 + 自分自身に電話をかけることはできません。ユーザーIDを変更してください \ No newline at end of file diff --git a/application/app/src/main/res/values-zh/strings.xml b/application/app/src/main/res/values-zh/strings.xml index cdf8effa..fdf21929 100644 --- a/application/app/src/main/res/values-zh/strings.xml +++ b/application/app/src/main/res/values-zh/strings.xml @@ -106,4 +106,5 @@ 开启高性能模式 关闭高级特性 开启测试环境 + 您无法向自己发起通话,请您更换新的用户 ID \ No newline at end of file diff --git a/application/app/src/main/res/values/strings.xml b/application/app/src/main/res/values/strings.xml index 7035233d..b22afd27 100644 --- a/application/app/src/main/res/values/strings.xml +++ b/application/app/src/main/res/values/strings.xml @@ -105,4 +105,5 @@ Enable High Performance Disable Feature Enable Test ENV + You cannot call yourself, please use a different user ID \ No newline at end of file diff --git a/application/build.gradle b/application/build.gradle index 8dc43e0d..44d819a6 100644 --- a/application/build.gradle +++ b/application/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { def gradleMajorVersion = gradle.gradleVersion.tokenize('.')[0].toInteger() if (gradleMajorVersion >= 8) { - classpath 'com.android.tools.build:gradle:8.0.2' + classpath 'com.android.tools.build:gradle:8.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0" } else { classpath 'com.android.tools.build:gradle:4.2.1' @@ -20,13 +20,9 @@ task clean(type: Delete) { } ext { - compileSdkVersion = 34 - buildToolsVersion = "30.0.1" - minSdkVersion = 21 - targetSdkVersion = 34 liteavSdk = "com.tencent.liteav:LiteAVSDK_Professional:13.0.0.19676" - roomEngineSdk = buildEngineSource.toBoolean() ? project(":engine_source") : "io.trtc.uikit:rtc_room_engine:3.6.1.76" - atomicxCoreSdk = buildAtomicxCoreSource.toBoolean() ? project(":atomicxcore") : "io.trtc.uikit:atomicx-core:4.0.3.44" + roomEngineSdk = buildEngineSource.toBoolean() ? project(":engine_source") : "io.trtc.uikit:rtc_room_engine:4.0.1.97" + atomicxCoreSdk = buildAtomicxCoreSource.toBoolean() ? project(":atomicxcore") : "io.trtc.uikit:atomicx-core:4.0.1.90" imSdk = "com.tencent.imsdk:imsdk-plus:8.7.7201" common = "io.trtc.uikit:common:3.5.0.1332" } \ No newline at end of file diff --git a/application/gradle/wrapper/gradle-wrapper.properties b/application/gradle/wrapper/gradle-wrapper.properties index 131d8a4f..51f6b24f 100644 --- a/application/gradle/wrapper/gradle-wrapper.properties +++ b/application/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip diff --git a/atomic_x/build.gradle b/atomic_x/build.gradle index 9031d11e..acbbe922 100644 --- a/atomic_x/build.gradle +++ b/atomic_x/build.gradle @@ -10,8 +10,7 @@ android { defaultConfig { minSdk 21 - versionName "1.0" - versionCode 1 + } buildTypes { @@ -55,9 +54,9 @@ dependencies { api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' api 'com.github.bumptech.glide:glide:4.12.0' - api rootProject.getProperties().containsKey("atomicxCoreSdk") ? rootProject.ext.atomicxCoreSdk : "io.trtc.uikit:atomicx-core:4.0.0.110" - api rootProject.getProperties().containsKey("liteavSdk") ? rootProject.ext.liteavSdk : "com.tencent.liteav:LiteAVSDK_Professional:13.0.0.19676" - api rootProject.getProperties().containsKey("common") ? rootProject.ext.common : "io.trtc.uikit:common:3.3.0.1194" + api rootProject.getProperties().containsKey("roomEngineSdk") ? rootProject.ext.roomEngineSdk : "io.trtc.uikit:rtc_room_engine:4.0.1.71" + api rootProject.getProperties().containsKey("atomicxCoreSdk") ? rootProject.ext.atomicxCoreSdk : "io.trtc.uikit:atomicx-core:4.0.1.71" + api rootProject.getProperties().containsKey("liteavSdk") ? rootProject.ext.liteavSdk : "com.tencent.liteav:LiteAVSDK_Professional:12.8.0.19279" api rootProject.getChildProjects().containsKey("tuicore") ? project(':tuicore') : "com.tencent.liteav.tuikit:tuicore:8.8.7357" implementation 'androidx.appcompat:appcompat:1.3.1' diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/LanguagePickerDialogFragment.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/LanguagePickerDialogFragment.kt similarity index 99% rename from atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/LanguagePickerDialogFragment.kt rename to atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/LanguagePickerDialogFragment.kt index da39df7d..5127a007 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/LanguagePickerDialogFragment.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/LanguagePickerDialogFragment.kt @@ -1,4 +1,4 @@ -package io.trtc.tuikit.atomicx.ai +package io.trtc.tuikit.atomicx.AITranscriber import android.os.Bundle import android.view.Gravity diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/LanguageProvider.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/LanguageProvider.kt similarity index 98% rename from atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/LanguageProvider.kt rename to atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/LanguageProvider.kt index ff65ee2a..05171fda 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/LanguageProvider.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/LanguageProvider.kt @@ -1,4 +1,4 @@ -package io.trtc.tuikit.atomicx.ai +package io.trtc.tuikit.atomicx.AITranscriber import io.trtc.tuikit.atomicx.R import io.trtc.tuikit.atomicxcore.api.ai.SourceLanguage diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/TranscriberSettingsDialogFragment.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/TranscriberSettingsDialogFragment.kt similarity index 98% rename from atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/TranscriberSettingsDialogFragment.kt rename to atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/TranscriberSettingsDialogFragment.kt index 6872a90c..cfcf4958 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/TranscriberSettingsDialogFragment.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/TranscriberSettingsDialogFragment.kt @@ -1,4 +1,4 @@ -package io.trtc.tuikit.atomicx.ai +package io.trtc.tuikit.atomicx.AITranscriber import android.content.DialogInterface import android.os.Bundle @@ -121,7 +121,7 @@ class TranscriberSettingsDialogFragment : DialogFragment() { } companion object { - private const val TAG = "TranscriberSettingsDialogFragment" + internal const val TAG = "TranscriberSettingsDialogFragment" private const val ARG_SOURCE_LANGUAGE = "source_language" private const val ARG_TRANSLATION_LANGUAGE = "translation_language" private const val ARG_BILINGUAL_ENABLED = "bilingual_enabled" diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/TranscriberView.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/TranscriberView.kt similarity index 99% rename from atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/TranscriberView.kt rename to atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/TranscriberView.kt index 6e9b0d5a..609a0ab5 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/ai/TranscriberView.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/AITranscriber/TranscriberView.kt @@ -1,4 +1,4 @@ -package io.trtc.tuikit.atomicx.ai +package io.trtc.tuikit.atomicx.AITranscriber import android.content.Context import android.graphics.Rect diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/CallView.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/CallView.kt index 5f4858c5..fb760c61 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/CallView.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/CallView.kt @@ -3,31 +3,38 @@ package io.trtc.tuikit.atomicx.callview import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater -import androidx.constraintlayout.widget.ConstraintLayout -import io.trtc.tuikit.atomicx.callview.core.CallViewFunction -import io.trtc.tuikit.atomicxcore.api.call.CallParticipantInfo -import io.trtc.tuikit.atomicxcore.api.call.CallStore -import io.trtc.tuikit.atomicxcore.api.view.CallCoreView -import io.trtc.tuikit.atomicxcore.api.view.CallLayoutTemplate -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch import android.widget.FrameLayout import android.widget.LinearLayout -import com.trtc.tuikit.common.util.ScreenUtil.dip2px +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.isVisible import io.trtc.tuikit.atomicx.R +import io.trtc.tuikit.atomicx.callview.core.CallViewFunction import io.trtc.tuikit.atomicx.callview.core.common.utils.CallUtils import io.trtc.tuikit.atomicx.callview.core.common.utils.ImageResourceCache -import io.trtc.tuikit.atomicx.callview.public.multi.MultiCallWaitingView +import io.trtc.tuikit.atomicx.callview.core.common.utils.Logger import io.trtc.tuikit.atomicx.callview.public.controls.MultiCallControlsView import io.trtc.tuikit.atomicx.callview.public.controls.SingleCallControlsView import io.trtc.tuikit.atomicx.callview.public.hint.HintView import io.trtc.tuikit.atomicx.callview.public.hint.TimerView +import io.trtc.tuikit.atomicx.callview.public.multi.MultiCallWaitingView import io.trtc.tuikit.atomicx.callview.public.transcriber.CallTranscriberView +import io.trtc.tuikit.atomicx.common.util.ScreenUtil.dip2px +import io.trtc.tuikit.atomicx.callview.public.smartcellularswitchrecommendation.SmartCellularRecommendationDialog +import io.trtc.tuikit.atomicx.widget.basicwidget.toast.AtomicToast +import io.trtc.tuikit.atomicxcore.api.call.CallParticipantInfo import io.trtc.tuikit.atomicxcore.api.call.CallParticipantStatus +import io.trtc.tuikit.atomicxcore.api.call.CallStore +import io.trtc.tuikit.atomicxcore.api.device.DeviceListener +import io.trtc.tuikit.atomicxcore.api.device.DeviceStore import io.trtc.tuikit.atomicxcore.api.device.NetworkQuality +import io.trtc.tuikit.atomicxcore.api.device.NetworkType +import io.trtc.tuikit.atomicxcore.api.view.CallCoreView +import io.trtc.tuikit.atomicxcore.api.view.CallLayoutTemplate import io.trtc.tuikit.atomicxcore.api.view.VolumeLevel +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch import kotlinx.coroutines.supervisorScope import java.io.File import java.util.concurrent.atomic.AtomicInteger @@ -45,8 +52,8 @@ class CallView @JvmOverloads constructor( var originalUrl: String, var cachedPath: String? ) - private var callMainView: CallCoreView? = null + private var transcriberContainer: FrameLayout? = null private var subscribeStateJob: Job? = null private val participantAvatarInfoMap: MutableMap = mutableMapOf() private val imageResourceCache = ImageResourceCache(context) @@ -55,9 +62,15 @@ class CallView @JvmOverloads constructor( private var layoutTimer: FrameLayout? = null private var layoutCallHint: FrameLayout? = null private var multiCallWaitingViewContainer: LinearLayout? = null - private var disableFeatures: List? = null + private var deviceListener: DeviceListener = object : DeviceListener { + override fun onSmartCellularSwitchRecommended() { + super.onSmartCellularSwitchRecommended() + showSmartCellularRecommendation() + } + } + init { initView() setIconResourcePath() @@ -72,10 +85,12 @@ class CallView @JvmOverloads constructor( addFunctionLayout() addTranscriberLayout() updateWaitingView() + DeviceStore.shared().addListener(deviceListener) subscribeStateJob = CoroutineScope(Dispatchers.Main).launch { supervisorScope { launch { observeSelfInfo() } launch { observeParticipantInfo() } + launch { observeNetworkType() } } } } @@ -83,12 +98,14 @@ class CallView @JvmOverloads constructor( override fun onDetachedFromWindow() { super.onDetachedFromWindow() callMainView?.removeAllViews() + deviceListener.let { DeviceStore.shared().removeListener(it) } subscribeStateJob?.cancel() } private suspend fun observeSelfInfo() { CallStore.shared.observerState.selfInfo.collect { selfInfo -> - if (selfInfo.status == CallParticipantStatus.Accept && callMainView?.visibility == GONE) { + val isAccepted = selfInfo.status == CallParticipantStatus.Accept + if (isAccepted && callMainView?.visibility == GONE) { updateWaitingView() } } @@ -100,6 +117,12 @@ class CallView @JvmOverloads constructor( } } + private suspend fun observeNetworkType() { + DeviceStore.shared().deviceState.networkType.collect { networkType -> + handleNetworkTypeChanged(networkType) + } + } + private fun initView() { LayoutInflater.from(context).inflate(R.layout.callview_root_view, this, true) multiCallWaitingViewContainer = findViewById(R.id.ll_callee_waiting_view) @@ -149,8 +172,8 @@ class CallView @JvmOverloads constructor( if (disableFeatures?.contains(Feature.AI_TRANSCRIBER) == true) { return } - val transcriberContainer = findViewById(R.id.call_layout_transcriber_container) - transcriberContainer.addView(CallTranscriberView(context)) + transcriberContainer = findViewById(R.id.call_layout_transcriber_container) + transcriberContainer?.addView(CallTranscriberView(context)) } private fun addFunctionLayout() { @@ -183,7 +206,7 @@ class CallView @JvmOverloads constructor( } for (participant in participants) { val participantId = participant.id - val currentAvatarUrl = participant.avatarUrl ?: "" + val currentAvatarUrl = participant.avatarURL ?: "" val existingInfo = participantAvatarInfoMap[participantId] if (existingInfo?.originalUrl != currentAvatarUrl) { participantsToUpdate.add(participantId to currentAvatarUrl) @@ -235,6 +258,30 @@ class CallView @JvmOverloads constructor( .mapValues { it.value.cachedPath!! } } + private fun showSmartCellularRecommendation() { + this.post { + try { + val dialog = SmartCellularRecommendationDialog(context) + dialog.onEnableSmartCellular = { + DeviceStore.shared().enableSmartCellularSwitchMode(true) + } + dialog.show() + } catch (e: Exception) { + Logger.e("showSmartCellularRecommendation failed: ${e.message}") + } + } + } + + private fun handleNetworkTypeChanged(type: NetworkType) { + val toastString = when (type) { + NetworkType.CELLULAR -> context.getString(R.string.smart_cellular_switched_to_cellular) + NetworkType.WIFI -> context.getString(R.string.smart_cellular_switched_to_wifi) + else -> return + } + AtomicToast.show(context, toastString) + } + + override fun setLayoutTemplate(template: CallLayoutTemplate) { val isPipView = template == CallLayoutTemplate.Pip layoutFunction?.visibility = if (isPipView) GONE else VISIBLE @@ -244,6 +291,7 @@ class CallView @JvmOverloads constructor( callMainView?.visibility = VISIBLE updateCallCoreViewTopMargin(template) callMainView?.setLayoutTemplate(template) + transcriberContainer?.isVisible = !isPipView } private fun updateCallCoreViewTopMargin(template: CallLayoutTemplate) { diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/CallViewStore.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/CallViewStore.kt new file mode 100644 index 00000000..d88b3e37 --- /dev/null +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/CallViewStore.kt @@ -0,0 +1,39 @@ +package io.trtc.tuikit.atomicx.callview + +import io.trtc.tuikit.atomicxcore.api.call.CallParticipantStatus +import io.trtc.tuikit.atomicxcore.api.call.CallStore +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +object CallViewStore { + + private const val DEFAULT_SHOW_TRANSCRIBER_PANEL = true + + private val _isShowTranscriberPanel = MutableStateFlow(DEFAULT_SHOW_TRANSCRIBER_PANEL) + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) + + init { + scope.launch { + CallStore.shared.observerState.selfInfo.collect { selfInfo -> + if (selfInfo.status != CallParticipantStatus.Accept) { + reset() + } + } + } + } + + val isShowTranscriberPanel: StateFlow = _isShowTranscriberPanel + + fun setShowTranscriberPanel(show: Boolean) { + _isShowTranscriberPanel.value = show + } + + private fun reset() { + _isShowTranscriberPanel.value = DEFAULT_SHOW_TRANSCRIBER_PANEL + } +} + diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/AudioAndVideoCalleeWaitingView.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/AudioAndVideoCalleeWaitingView.kt index 4078e181..8ca86f63 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/AudioAndVideoCalleeWaitingView.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/AudioAndVideoCalleeWaitingView.kt @@ -6,8 +6,8 @@ import android.widget.LinearLayout import android.widget.RelativeLayout import androidx.constraintlayout.utils.widget.ImageFilterView import androidx.core.content.ContextCompat -import com.trtc.tuikit.common.imageloader.ImageLoader import io.trtc.tuikit.atomicx.R +import io.trtc.tuikit.atomicx.common.imageloader.ImageLoader import io.trtc.tuikit.atomicxcore.api.call.CallStore class AudioAndVideoCalleeWaitingView(context: Context) : RelativeLayout(context) { diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/AudioCallerWaitingAndAcceptedView.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/AudioCallerWaitingAndAcceptedView.kt index 91d24da7..21fb6f37 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/AudioCallerWaitingAndAcceptedView.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/AudioCallerWaitingAndAcceptedView.kt @@ -4,9 +4,9 @@ import android.content.Context import android.view.LayoutInflater import android.widget.RelativeLayout import androidx.core.content.ContextCompat -import com.trtc.tuikit.common.imageloader.ImageLoader import io.trtc.tuikit.atomicx.R import io.trtc.tuikit.atomicx.callview.core.common.widget.ControlButton +import io.trtc.tuikit.atomicx.common.imageloader.ImageLoader import io.trtc.tuikit.atomicxcore.api.call.CallStore import io.trtc.tuikit.atomicxcore.api.device.AudioRoute import io.trtc.tuikit.atomicxcore.api.device.DeviceStatus diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/VideoCallerAndCalleeAcceptedView.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/VideoCallerAndCalleeAcceptedView.kt index 8be3a425..79fcc16b 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/VideoCallerAndCalleeAcceptedView.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/VideoCallerAndCalleeAcceptedView.kt @@ -11,20 +11,20 @@ import androidx.constraintlayout.widget.ConstraintSet import androidx.core.content.ContextCompat import androidx.transition.ChangeBounds import androidx.transition.TransitionManager -import com.trtc.tuikit.common.imageloader.ImageLoader import android.graphics.drawable.Drawable import android.view.MotionEvent import com.tencent.cloud.tuikit.engine.call.TUICallEngine import com.tencent.cloud.tuikit.engine.common.TUICommonDefine import com.tencent.qcloud.tuicore.permission.PermissionCallback import io.trtc.tuikit.atomicx.callview.core.common.Constants -import com.trtc.tuikit.common.util.ScreenUtil import io.trtc.tuikit.atomicx.R import io.trtc.tuikit.atomicx.callview.core.common.Constants.BLUR_LEVEL_CLOSE import io.trtc.tuikit.atomicx.callview.core.common.Constants.BLUR_LEVEL_HIGH import io.trtc.tuikit.atomicx.callview.core.common.utils.Logger import io.trtc.tuikit.atomicx.callview.core.common.utils.PermissionRequest import io.trtc.tuikit.atomicx.callview.core.common.widget.ControlButton +import io.trtc.tuikit.atomicx.common.imageloader.ImageLoader +import io.trtc.tuikit.atomicx.common.util.ScreenUtil import io.trtc.tuikit.atomicxcore.api.call.CallStore import io.trtc.tuikit.atomicxcore.api.call.CallParticipantStatus import io.trtc.tuikit.atomicxcore.api.device.AudioRoute diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/VideoCallerWaitingView.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/VideoCallerWaitingView.kt index 51698e41..7d1e536f 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/VideoCallerWaitingView.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/controls/VideoCallerWaitingView.kt @@ -8,13 +8,13 @@ import androidx.core.content.ContextCompat import com.tencent.cloud.tuikit.engine.call.TUICallEngine import com.tencent.cloud.tuikit.engine.common.TUICommonDefine import com.tencent.qcloud.tuicore.permission.PermissionCallback -import com.trtc.tuikit.common.imageloader.ImageLoader import io.trtc.tuikit.atomicx.R import io.trtc.tuikit.atomicx.callview.core.common.Constants.BLUR_LEVEL_CLOSE import io.trtc.tuikit.atomicx.callview.core.common.Constants.BLUR_LEVEL_HIGH import io.trtc.tuikit.atomicx.callview.core.common.utils.Logger import io.trtc.tuikit.atomicx.callview.core.common.utils.PermissionRequest import io.trtc.tuikit.atomicx.callview.core.common.widget.ControlButton +import io.trtc.tuikit.atomicx.common.imageloader.ImageLoader import io.trtc.tuikit.atomicxcore.api.call.CallStore import io.trtc.tuikit.atomicxcore.api.device.DeviceStatus import io.trtc.tuikit.atomicxcore.api.device.DeviceStore diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/multi/MultiCallWaitingView.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/multi/MultiCallWaitingView.kt index 96a1c178..636953e4 100644 --- a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/multi/MultiCallWaitingView.kt +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/multi/MultiCallWaitingView.kt @@ -8,10 +8,10 @@ import android.widget.LinearLayout import android.widget.TextView import androidx.constraintlayout.utils.widget.ImageFilterView import androidx.core.content.ContextCompat -import com.trtc.tuikit.common.imageloader.ImageLoader -import com.trtc.tuikit.common.util.ScreenUtil import io.trtc.tuikit.atomicx.R import io.trtc.tuikit.atomicx.callview.core.common.utils.CallUtils +import io.trtc.tuikit.atomicx.common.imageloader.ImageLoader +import io.trtc.tuikit.atomicx.common.util.ScreenUtil import io.trtc.tuikit.atomicxcore.api.call.CallStore import io.trtc.tuikit.atomicxcore.api.call.CallParticipantInfo import kotlinx.coroutines.MainScope @@ -56,7 +56,7 @@ class MultiCallWaitingView(context: Context) : LinearLayout(context) { CallStore.shared.observerState.allParticipants.collect { participants -> for (participant in participants) { if (CallUtils.isCaller(participant.id)) { - ImageLoader.load(context, imageCallerAvatar, participant.avatarUrl, R.drawable.callview_ic_avatar) + ImageLoader.load(context, imageCallerAvatar, participant.avatarURL, R.drawable.callview_ic_avatar) textWaitingUserName.text = participant.name } } @@ -101,7 +101,7 @@ class MultiCallWaitingView(context: Context) : LinearLayout(context) { imageView.round = 12f imageView.scaleType = ImageView.ScaleType.CENTER_CROP imageView.layoutParams = layoutParams - ImageLoader.load(context, imageView, user.avatarUrl, R.drawable.callview_ic_avatar) + ImageLoader.load(context, imageView, user.avatarURL, R.drawable.callview_ic_avatar) return imageView } diff --git a/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/smartcellularswitchrecommendation/SmartCellularRecommendationDialog.kt b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/smartcellularswitchrecommendation/SmartCellularRecommendationDialog.kt new file mode 100644 index 00000000..feeffe80 --- /dev/null +++ b/atomic_x/src/main/java/io/trtc/tuikit/atomicx/callview/public/smartcellularswitchrecommendation/SmartCellularRecommendationDialog.kt @@ -0,0 +1,176 @@ +package io.trtc.tuikit.atomicx.callview.public.smartcellularswitchrecommendation + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.os.Bundle +import android.widget.Button +import android.widget.ImageView +import com.google.android.material.bottomsheet.BottomSheetDialog +import io.trtc.tuikit.atomicx.R + +class SmartCellularRecommendationDialog(context: Context?) : + BottomSheetDialog(context!!, R.style.dialogStyleFromBottom) { + + var onEnableSmartCellular: (() -> Unit)? = null + var onKeepWiFi: (() -> Unit)? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.dialog_smart_cellular_recommendation) + + initViews() + setupClickListeners() + } + + private fun initViews() { + findViewById(R.id.iv_wifi_icon)?.setImageDrawable(createWiFiPoorIcon()) + findViewById(R.id.iv_cellular_icon)?.setImageDrawable(createCellularGoodIcon()) + findViewById(R.id.iv_arrow)?.setImageDrawable(createArrowIcon()) + } + + private fun setupClickListeners() { + findViewById