Compare commits
185 Commits
v5.39.4-11
...
v5.41.1-11
| Author | SHA1 | Date | |
|---|---|---|---|
| b3ee742faf | |||
| ead61c1916 | |||
| 9bb20ca41f | |||
| 74942be890 | |||
| 391eb64df1 | |||
| 03ba6f5614 | |||
| 1552a3e95d | |||
| 9b7526773c | |||
| 764402b701 | |||
| dc7ebbc308 | |||
| 065ebe32ed | |||
| c284fcd531 | |||
| 101aa11855 | |||
| 21a4ff5560 | |||
| 034b7f07ee | |||
| d3c9cb7776 | |||
| 8593f5cd0d | |||
| 26e272edd0 | |||
| cc0683c3c7 | |||
| 7d9f36d587 | |||
| eac6bc2c7f | |||
| 1fd0d7f215 | |||
| cd5748fa1c | |||
| 3cc4a2b9bc | |||
| 55056b772e | |||
| a11acbb8c4 | |||
| 24d59aaa85 | |||
| f57a95b82c | |||
| 3a78b307d3 | |||
| c4dccb7aa7 | |||
| 7612c6afd7 | |||
| 2c781bcbf1 | |||
| 7ab09e42ca | |||
| 292c96586a | |||
| 7681b63e27 | |||
| 95966be1a1 | |||
| 9eab3361a0 | |||
| d0d5ccdc45 | |||
| c61d0bc9cc | |||
| 2da07354e7 | |||
| d874b91b7c | |||
| 62e62d3a93 | |||
| 2e806d77e1 | |||
| 30da988ebc | |||
| fd61e83f8e | |||
| 0712960a30 | |||
| 5dfdaa0353 | |||
| fa4dce66a6 | |||
| 8a017df220 | |||
| 3a0be0a6ee | |||
| d50eeddde2 | |||
| 89aa6e7abc | |||
| ab795ab538 | |||
| ba0854ad9a | |||
| fc2051387a | |||
| ab2973c7be | |||
| 2a08ea681d | |||
| e23d510fb0 | |||
| 3c6ee0c782 | |||
| 07840822a8 | |||
| 12e547d333 | |||
| 8bb3736ad1 | |||
| aa9ba5163f | |||
| 23033edc42 | |||
| 308e134aff | |||
| ac78ea0498 | |||
| 38bab9cf4f | |||
| e3f883b784 | |||
| fbb81d7e45 | |||
| 750ec04c9d | |||
| e23a3d3938 | |||
| d75020cdb5 | |||
| c56c71d1f1 | |||
| ccfa50d748 | |||
| 7176a5a4c4 | |||
| d007092193 | |||
| 2552743ff2 | |||
| 4faf15ffe7 | |||
| 33d6ed75ad | |||
| 2eb4878b12 | |||
| 2bea3c72d7 | |||
| fa3db9d521 | |||
| 8084cda37d | |||
| e624f34de1 | |||
| b832c0c14f | |||
| 6610c43937 | |||
| ec29d94fb7 | |||
| efee9409bf | |||
| 38a7eaf780 | |||
| a1b4233fdb | |||
| 60c24e7457 | |||
| b6ec74d789 | |||
| 2d7224cf16 | |||
| 3f45344b54 | |||
| 1c3dbce08d | |||
| 7844800b0e | |||
| ebcfd9c85d | |||
| 3825315f65 | |||
| 3ffe4f9bc6 | |||
| 729685e764 | |||
| b2fc01ae48 | |||
| 06f932af14 | |||
| c2fe3bb64a | |||
| b1b231a309 | |||
| e5161ae350 | |||
| 4dfa7733ad | |||
| 3906d9b84b | |||
| 775e6cc689 | |||
| 019b9f3f82 | |||
| 49f752dab5 | |||
| 0cbda119d4 | |||
| aed8e50db3 | |||
| da5bb9eaf3 | |||
| d7593de98b | |||
| 69d2d699fe | |||
| a438ef16c0 | |||
| d5a2cecd29 | |||
| 65a4e675fa | |||
| ec3e6d5f7b | |||
| 07b0afce03 | |||
| 852a6d32d6 | |||
| 55022d8b1c | |||
| eb7d407e92 | |||
| 733cd1e198 | |||
| 1d767018f6 | |||
| 0a3616a1c0 | |||
| 05108ab478 | |||
| 508c90cc63 | |||
| 6242f79f80 | |||
| 71dd964440 | |||
| 63fc720c40 | |||
| 5da02c4b64 | |||
| f94b28a085 | |||
| e8a199b5c0 | |||
| 2ba39188f7 | |||
| 963074d5d8 | |||
| cc629819d9 | |||
| d82505ab5d | |||
| a917214b36 | |||
| bdf9094799 | |||
| df0d0604b9 | |||
| f100d906ab | |||
| cc05dabb93 | |||
| bd39ac2eaf | |||
| 31903d21c0 | |||
| 266fcc4c38 | |||
| 075ed04191 | |||
| c804c2f7fd | |||
| 882f0a7b3e | |||
| 3cf86a500b | |||
| 3cd70b5b8f | |||
| 60f35a89b4 | |||
| 1503c23246 | |||
| ea9e91618f | |||
| d52fcc2185 | |||
| db047c36d7 | |||
| 1e58bec4a0 | |||
| 87ff1a64b3 | |||
| b3678d7a54 | |||
| c7fa04792b | |||
| 76ea531419 | |||
| d821da0b2c | |||
| d9b137504a | |||
| 93369f5676 | |||
| b109c3bf6f | |||
| bb80560a49 | |||
| c43a9e3b6e | |||
| 34d255d258 | |||
| 3ca17cea07 | |||
| d3e23bfbb5 | |||
| 273a9f010d | |||
| e8cbaf89ff | |||
| 0e3586a556 | |||
| d546651c06 | |||
| 815f567f44 | |||
| ba3e9357a1 | |||
| 312448daae | |||
| a00a1ced7e | |||
| 1587ca8e6a | |||
| 86b4761a1c | |||
| 0446d87b24 | |||
| 8a6d476636 | |||
| 17b34c9e6f | |||
| 69241c489b | |||
| 5d4648b3d2 |
@ -113,6 +113,7 @@ android {
|
||||
buildConfigField "String", "WECHAT_SECRET", "\"${WECHAT_SECRET}\""
|
||||
buildConfigField "String", "TENCENT_APPID", "\"${TENCENT_APPID}\""
|
||||
buildConfigField "String", "WEIBO_APPKEY", "\"${WEIBO_APPKEY}\""
|
||||
buildConfigField "String", "DSP_API_HOST","\"${DSP_API_HOST}\""
|
||||
// 一体包的32位畅玩游戏助手包名
|
||||
buildConfigField "String", "EXT_PACKAGE_NAME", "\"${rootProject.ext.EXT_PACKAGE_NAME}\""
|
||||
}
|
||||
@ -346,7 +347,7 @@ repositories {
|
||||
android.applicationVariants.configureEach { variant ->
|
||||
variant.mergeAssets.doLast {
|
||||
def assetDir = variant.mergeAssetsProvider.get().outputDir.get()
|
||||
def unwantedAssets = ['2011394667', 'gdt_plugin/gdtadv2.jar']
|
||||
def unwantedAssets = ['1832823466', 'gdt_plugin/gdtadv2.jar']
|
||||
|
||||
unwantedAssets.each { assetPath ->
|
||||
def file = new File([assetDir, assetPath].join(File.separator))
|
||||
|
||||
@ -77,6 +77,7 @@
|
||||
|
||||
### TEA
|
||||
-keep class com.gh.gamecenter.TeaHelper { *; }
|
||||
-keep class com.bytedance.ads.convert.broadcast.common.EncryptionTools {*;}
|
||||
|
||||
### EasyFloat
|
||||
-keep class com.lzf.easyfloat.* {*;}
|
||||
|
||||
Binary file not shown.
BIN
app/src/gdt/libs/GDTActionSDK.min.1.9.1.aar
Normal file
BIN
app/src/gdt/libs/GDTActionSDK.min.1.9.1.aar
Normal file
Binary file not shown.
@ -71,6 +71,10 @@
|
||||
<!-- 适配 双开/分身 游戏授权登录 -->
|
||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
|
||||
|
||||
<!-- 日历 -->
|
||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="
|
||||
com.shuyu.gsyvideoplayer,
|
||||
com.shuyu.gsyvideoplayer.lib,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -19,10 +19,10 @@ import java.net.URLConnection
|
||||
|
||||
object AdPluginDownloadHelper : InnerDownloadListener {
|
||||
|
||||
private const val CSJ_FILE_NAME = "2011394667"
|
||||
private const val CSJ_FILE_NAME = "1832823466"
|
||||
private const val GDT_FILE_NAME = "gdt_plugin/gdtadv2.jar"
|
||||
|
||||
private const val CSJ_PLUGIN_URL = "https://and-static.ghzs66.com/android/static/2011394667"
|
||||
private const val CSJ_PLUGIN_URL = "https://and-static.ghzs66.com/android/static/1832823466"
|
||||
private const val GDT_PLUGIN_URL = "https://and-static.ghzs66.com/android/static/gdtadv2.jar"
|
||||
|
||||
private var csjDownloadedCallback: (() -> Unit)? = null
|
||||
|
||||
@ -3,6 +3,8 @@ package com.gh.common
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Base64
|
||||
import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
@ -11,6 +13,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.LogUtils
|
||||
@ -18,6 +21,7 @@ import com.gh.download.DownloadManager
|
||||
import com.gh.download.PackageObserver
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.common.callback.BiCallback
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
@ -35,6 +39,7 @@ import com.gh.gamecenter.common.utils.SensorsBridge.EVENT_NAME
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge.KEY_IS_FIRST_TIME
|
||||
import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IAcceleratorProvider
|
||||
import com.gh.gamecenter.core.provider.IPushProvider
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
@ -77,7 +82,7 @@ import java.util.*
|
||||
class DefaultJsApi(
|
||||
var context: Context,
|
||||
val entrance: String = "",
|
||||
private var mFragment: Fragment? = null,
|
||||
private val mFragment: Fragment? = null,
|
||||
private var mBbsId: String? = "",
|
||||
private var mOriginUrl: String? = "",
|
||||
private val mForumName: String? = "",
|
||||
@ -94,6 +99,8 @@ class DefaultJsApi(
|
||||
private var mDownloadHandler: CompletionHandler<Any>? = null // 下载信息回调
|
||||
private var mExposureEvent: ExposureEvent? = null // 活动曝光实体
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
init {
|
||||
if (mFragment != null) {
|
||||
EventBus.getDefault().register(this)
|
||||
@ -240,6 +247,12 @@ class DefaultJsApi(
|
||||
VHelper.launch(context, packageName)
|
||||
}
|
||||
} else {
|
||||
val wechatPkgName = "com.tencent.mm"
|
||||
if (packageName == wechatPkgName && !PackageUtils.isInstalled(context, wechatPkgName)) {
|
||||
// 如果是微信客户端,需要检查是否安装微信
|
||||
ToastUtils.showToast(R.string.wechat_app_not_install_tips.toResString())
|
||||
return@runOnUiThread
|
||||
}
|
||||
PackageLauncher.launchApp(context, packageName = packageName)
|
||||
}
|
||||
}
|
||||
@ -502,6 +515,44 @@ class DefaultJsApi(
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun saveWechatQRCode(msg: Any) {
|
||||
val base64StringData = msg.toString()
|
||||
runOnUiThread {
|
||||
(context as? FragmentActivity)?.checkStoragePermissionBeforeAction {
|
||||
runOnIoThread {
|
||||
val base64String = base64StringData.replace("data:image/png;base64", "")
|
||||
tryWithDefaultCatch {
|
||||
val imageFile =
|
||||
File(HaloApp.getInstance().cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".png")
|
||||
val decodedString = Base64.decode(base64String, Base64.DEFAULT)
|
||||
val bos = BufferedOutputStream(FileOutputStream(imageFile))
|
||||
bos.write(decodedString)
|
||||
bos.flush()
|
||||
bos.close()
|
||||
|
||||
ImageUtils.saveImageToFile(imageFile, "", true) {
|
||||
// 这里是 ui 线程
|
||||
// 保存微信二维码成功,1s 以后跳转微信
|
||||
if (mFragment != null && mFragment.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
handler.postDelayed({
|
||||
val wechatPkgName = "com.tencent.mm"
|
||||
if (!PackageUtils.isInstalled(context, wechatPkgName)) {
|
||||
ToastUtils.showToast(R.string.wechat_app_not_install_tips.toResString())
|
||||
return@postDelayed
|
||||
}
|
||||
PackageLauncher.launchApp(context, packageName = wechatPkgName)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun loginWithCallback(msg: Any, handler: CompletionHandler<Any>) {
|
||||
mLoginHandler = handler
|
||||
@ -750,6 +801,14 @@ class DefaultJsApi(
|
||||
listener?.onStopGameAccelerate()
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getDurationRemainingTime(msg: Any, handler: CompletionHandler<Any>) {
|
||||
TheRouter.get(IAcceleratorProvider::class.java)?.loadQyUserPermissionData {
|
||||
val durationExpiredMinute = AcceleratorDataHolder.instance.vipEntity?.durationExpiredTime ?: 0L
|
||||
handler.complete(durationExpiredMinute)
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun refreshToken(token: Any, handler: CompletionHandler<Any>) {
|
||||
val accessToken = token.toString()
|
||||
@ -798,6 +857,8 @@ class DefaultJsApi(
|
||||
}
|
||||
|
||||
EventBus.getDefault().unregister(this@DefaultJsApi)
|
||||
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -66,6 +66,8 @@ public class Config {
|
||||
public static final String WGAME_CPM_BUSIAPPID = BuildConfig.WGAME_CPM_BUSIAPPID;
|
||||
public static final String WGAME_CPM_API_HOST = EnvHelper.getWGameCPMHost();
|
||||
|
||||
public static final String DSP_API_HOST = EnvHelper.getDspHost();
|
||||
|
||||
// Third-Party confs
|
||||
public static final String WECHAT_APPID = BuildConfig.WECHAT_APPID;
|
||||
public static final String WECHAT_SECRET = BuildConfig.WECHAT_SECRET;
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
package com.gh.common.databind;
|
||||
|
||||
import static com.gh.gamecenter.entity.SubjectEntity.SUBJECT_TAG_SELLING_POINT;
|
||||
import static com.gh.gamecenter.entity.SubjectEntity.SUBJECT_TAG_TEST;
|
||||
import static com.gh.gamecenter.entity.SubjectEntity.SUBJECT_TAG_TYPE;
|
||||
import static com.gh.gamecenter.entity.SubjectEntity.SUBJECT_TAG_UPDATE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
@ -8,11 +13,14 @@ import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.constraintlayout.widget.ConstraintSet;
|
||||
|
||||
import com.gh.common.chain.BrowserInstallHandler;
|
||||
import com.gh.common.chain.CheckDownloadHandler;
|
||||
@ -48,6 +56,7 @@ import com.gh.download.server.BrowserInstallHelper;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.common.databinding.LayoutGameItemSellingPointBinding;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.utils.DarkModeUtils;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
@ -55,6 +64,7 @@ import com.gh.gamecenter.common.utils.FileUtils;
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.core.utils.TimeUtils;
|
||||
import com.gh.gamecenter.core.utils.ToastUtils;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
@ -264,7 +274,9 @@ public class BindingAdapters {
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
gameEntity.getId(),
|
||||
gameEntity.getName() != null ? gameEntity.getName() : "",
|
||||
"主动安装"
|
||||
"主动安装",
|
||||
gameEntity.isDspGame(),
|
||||
gameEntity.getDspAdId()
|
||||
);
|
||||
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
|
||||
@ -289,7 +301,7 @@ public class BindingAdapters {
|
||||
});
|
||||
break;
|
||||
case RESERVED:
|
||||
ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> {
|
||||
ReservationHelper.showCancelReservationDialog(progressBar.getContext(), gameEntity, () -> {
|
||||
ReservationHelper.cancelReservation(gameEntity, () -> {
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
@ -472,39 +484,37 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
// 包含测试开服标签
|
||||
public static void setGameTags(LinearLayout layout, GameEntity gameEntity) {
|
||||
/**
|
||||
* 包含测试开服标签
|
||||
*
|
||||
* @param layout
|
||||
* @param gameEntity
|
||||
* @param subjectTag 默认为 “”,只有游戏专题可以配置subjectTag
|
||||
*/
|
||||
public static void setGameTags(LinearLayout layout, GameEntity gameEntity, String subjectTag) {
|
||||
try {
|
||||
if (layout.getVisibility() == View.GONE) return;
|
||||
ArrayList<TagStyleEntity> tagStyle = new ArrayList<>();
|
||||
TestEntity test = gameEntity.getTest();
|
||||
if (test != null
|
||||
// 这个判断用于开测表列表
|
||||
&& !"type_tag".equals(test.getGameTag())) {
|
||||
if ("custom".equals(test.getGameTag())) {
|
||||
TagStyleEntity typeTag = new TagStyleEntity();
|
||||
if (!TextUtils.isEmpty(test.getText())) {
|
||||
typeTag.setName(test.getText() != null ? test.getText() : "");
|
||||
} else {
|
||||
typeTag.setName(test.getType() != null ? test.getType() : "");
|
||||
}
|
||||
typeTag.setBackground("E8F3FF");
|
||||
typeTag.setColor("1383EB");
|
||||
tagStyle.add(typeTag);
|
||||
} else {
|
||||
TagStyleEntity typeTag = new TagStyleEntity();
|
||||
boolean isDarkModeOn = DarkModeUtils.INSTANCE.isDarkModeOn(layout.getContext());
|
||||
typeTag.setName(test.getType() != null ? test.getType() : "");
|
||||
typeTag.setBackground("1AFFA142");
|
||||
typeTag.setColor(isDarkModeOn ? "EB9238" : "FFA142");
|
||||
tagStyle.add(typeTag);
|
||||
if (test != null && subjectTag.equals(SUBJECT_TAG_TEST)) {
|
||||
// 显示开测表标签
|
||||
TagStyleEntity typeTag = new TagStyleEntity();
|
||||
boolean isDarkModeOn = DarkModeUtils.INSTANCE.isDarkModeOn(layout.getContext());
|
||||
typeTag.setName(test.getType() != null ? test.getType() : "");
|
||||
typeTag.setBackground("1AFFA142");
|
||||
typeTag.setColor(isDarkModeOn ? "EB9238" : "FFA142");
|
||||
tagStyle.add(typeTag);
|
||||
|
||||
TagStyleEntity timeTag = new TagStyleEntity();
|
||||
TagStyleEntity timeTag = new TagStyleEntity();
|
||||
if (test.getStartPending()) {
|
||||
timeTag.setName(test.getStartText());
|
||||
} else {
|
||||
timeTag.setName(GameViewUtils.getGameTestDate(test.getStart()));
|
||||
timeTag.setBackground("1A06CEA8");
|
||||
timeTag.setColor(isDarkModeOn ? "07A385" : "06CEA8");
|
||||
tagStyle.add(timeTag);
|
||||
}
|
||||
timeTag.setBackground("1A06CEA8");
|
||||
timeTag.setColor(isDarkModeOn ? "07A385" : "06CEA8");
|
||||
tagStyle.add(timeTag);
|
||||
|
||||
} else {
|
||||
tagStyle = gameEntity.getTagStyle();
|
||||
}
|
||||
@ -514,6 +524,68 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setGameTagsWithSellingPoint(LinearLayout layout, LayoutGameItemSellingPointBinding binding, GameEntity gameEntity, String subjectTag) {
|
||||
if (subjectTag.equals(SUBJECT_TAG_SELLING_POINT)) {
|
||||
layout.setVisibility(View.GONE);
|
||||
binding.getRoot().setVisibility(View.VISIBLE);
|
||||
GameEntity.SellingPoints sellingPoints = gameEntity.getSellingPoints();
|
||||
if (sellingPoints != null) {
|
||||
binding.tvSellingPoints.setVisibility(View.VISIBLE);
|
||||
binding.tvSellingPoints.setText(sellingPoints.getText());
|
||||
} else {
|
||||
binding.tvSellingPoints.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
ArrayList<TagStyleEntity> tagStyle = gameEntity.getTagStyle();
|
||||
StringBuilder tagText = new StringBuilder();
|
||||
for (int i = 0; i < tagStyle.size(); i++) {
|
||||
if (i < 3) {
|
||||
tagText.append(i == 0 ? "" : "·").append(tagStyle.get(i).getName());
|
||||
}
|
||||
}
|
||||
binding.gtcvTags.setText(tagText);
|
||||
} else {
|
||||
layout.setVisibility(View.VISIBLE);
|
||||
binding.getRoot().setVisibility(View.GONE);
|
||||
switch (subjectTag) {
|
||||
case SUBJECT_TAG_UPDATE:
|
||||
List<TagStyleEntity> updateTags = new ArrayList<>();
|
||||
TagStyleEntity updateTag = new TagStyleEntity(
|
||||
"local_generated",
|
||||
TimeUtils.getFormatTime(gameEntity.getUpdateTime(), "MM-dd") + " 更新",
|
||||
"",
|
||||
"1383EB",
|
||||
"E8F3FF",
|
||||
"1383EB",
|
||||
false
|
||||
);
|
||||
updateTags.add(updateTag);
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, updateTags);
|
||||
break;
|
||||
case SUBJECT_TAG_TYPE:
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, gameEntity.getTagStyle());
|
||||
break;
|
||||
default:
|
||||
setGameTags(layout, gameEntity, subjectTag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ViewParent parent = binding.getRoot().getParent();
|
||||
if (parent instanceof ConstraintLayout) {
|
||||
ConstraintLayout constraintLayout = (ConstraintLayout) parent;
|
||||
ConstraintSet constraintSet = new ConstraintSet();
|
||||
constraintSet.clone(constraintLayout);
|
||||
constraintSet.clear(R.id.gameDesSpace, ConstraintSet.BOTTOM);
|
||||
if (subjectTag.equals(SUBJECT_TAG_SELLING_POINT)) {
|
||||
constraintSet.connect(R.id.gameDesSpace, ConstraintSet.BOTTOM, R.id.layout_selling_points, ConstraintSet.TOP);
|
||||
} else {
|
||||
constraintSet.connect(R.id.gameDesSpace, ConstraintSet.BOTTOM, R.id.label_list, ConstraintSet.TOP);
|
||||
}
|
||||
constraintSet.applyTo(constraintLayout);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoDetailGameTags(LinearLayout layout, GameEntity gameEntity) {
|
||||
try {
|
||||
ArrayList<TagStyleEntity> tagStyle = new ArrayList<>();
|
||||
|
||||
@ -0,0 +1,294 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.HaloApp
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.DialogFragmentAccelerateExporationBinding
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
public class AccelerateExpirationDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private lateinit var binding: DialogFragmentAccelerateExporationBinding
|
||||
|
||||
private var _reminder: ExpirationReminder? = null
|
||||
|
||||
override fun onBack(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
_reminder = arguments?.getParcelable(KEY_EXPIRATION_REMINDER)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return DialogFragmentAccelerateExporationBinding.inflate(inflater, container, false)
|
||||
.also {
|
||||
binding = it
|
||||
}.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val reminder = _reminder ?: return
|
||||
val (title, content) = when (reminder) {
|
||||
is ExpirationReminder.UserExpired -> {
|
||||
SensorsBridge.trackMonthlyPackageExpiresDialogShow(
|
||||
reminder.gameId, reminder.gameName, reminder.pkgName, reminder.sourceEntrance
|
||||
)
|
||||
getString(
|
||||
R.string.membership_expiration_reminder_title,
|
||||
"${reminder.days}"
|
||||
) to getString(R.string.membership_expiration_reminder_content)
|
||||
}
|
||||
|
||||
is ExpirationReminder.InsufficientDuration -> {
|
||||
SensorsBridge.trackInsufficientDurationDialogShow(
|
||||
reminder.gameId,
|
||||
reminder.gameName,
|
||||
reminder.pkgName,
|
||||
reminder.sourceEntrance
|
||||
)
|
||||
getString(
|
||||
R.string.duration_time_out_reminder_title,
|
||||
"${reminder.hours}"
|
||||
) to getString(R.string.duration_time_out_reminder_content)
|
||||
}
|
||||
|
||||
is ExpirationReminder.DurationExpired -> {
|
||||
SensorsBridge.trackTimedPackageExpiresDialogShow(
|
||||
reminder.gameId,
|
||||
reminder.gameName,
|
||||
reminder.pkgName,
|
||||
reminder.sourceEntrance
|
||||
)
|
||||
getString(
|
||||
R.string.duration_expiration_reminder_title,
|
||||
"${reminder.days}"
|
||||
) to getString(R.string.duration_expiration_reminder_content)
|
||||
}
|
||||
|
||||
is ExpirationReminder.TimeRunsOut -> {
|
||||
SensorsBridge.trackDurationExhaustedDialogShow()
|
||||
getString(R.string.accelerator_member_expired_title) to getString(R.string.accelerator_member_expired_content)
|
||||
}
|
||||
}
|
||||
|
||||
binding.tvTitle.text = title
|
||||
binding.tvContent.text = content
|
||||
binding.tvCancel.setOnClickListener {
|
||||
when (reminder) {
|
||||
is ExpirationReminder.UserExpired -> {
|
||||
SensorsBridge.trackMonthlyPackageExpiresDialogClick(
|
||||
reminder.gameId, reminder.gameName, reminder.pkgName, reminder.sourceEntrance, BUTTON_NAME_KNOW
|
||||
)
|
||||
}
|
||||
|
||||
is ExpirationReminder.InsufficientDuration -> {
|
||||
SensorsBridge.trackInsufficientDurationDialogClick(
|
||||
reminder.gameId, reminder.gameName, reminder.pkgName, reminder.sourceEntrance, BUTTON_NAME_KNOW
|
||||
)
|
||||
}
|
||||
|
||||
is ExpirationReminder.DurationExpired -> {
|
||||
SensorsBridge.trackTimedPackageExpiresDialogClick(
|
||||
reminder.gameId, reminder.gameName, reminder.pkgName, reminder.sourceEntrance, BUTTON_NAME_KNOW
|
||||
)
|
||||
}
|
||||
|
||||
is ExpirationReminder.TimeRunsOut -> {
|
||||
SensorsBridge.trackDurationExhaustedDialogClick(BUTTON_NAME_KNOW)
|
||||
}
|
||||
}
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
binding.tvSubmit.setOnClickListener {
|
||||
when (reminder) {
|
||||
is ExpirationReminder.UserExpired -> {
|
||||
SensorsBridge.trackMonthlyPackageExpiresDialogClick(
|
||||
reminder.gameId, reminder.gameName, reminder.pkgName, reminder.sourceEntrance, BUTTON_NAME_BUY
|
||||
)
|
||||
}
|
||||
|
||||
is ExpirationReminder.InsufficientDuration -> {
|
||||
SensorsBridge.trackInsufficientDurationDialogClick(
|
||||
reminder.gameId, reminder.gameName, reminder.pkgName, reminder.sourceEntrance, BUTTON_NAME_BUY
|
||||
)
|
||||
}
|
||||
|
||||
is ExpirationReminder.DurationExpired -> {
|
||||
SensorsBridge.trackTimedPackageExpiresDialogClick(
|
||||
reminder.gameId, reminder.gameName, reminder.pkgName, reminder.sourceEntrance, BUTTON_NAME_BUY
|
||||
)
|
||||
}
|
||||
|
||||
is ExpirationReminder.TimeRunsOut -> {
|
||||
SensorsBridge.trackDurationExhaustedDialogClick(BUTTON_NAME_BUY)
|
||||
}
|
||||
}
|
||||
SensorsBridge.trackMyAssetsPageShow(
|
||||
reminder.pkgName,
|
||||
reminder.gameId,
|
||||
reminder.gameName,
|
||||
reminder.dialogName
|
||||
)
|
||||
dismissAllowingStateLoss()
|
||||
|
||||
DirectUtils.navigateToMyAssetsPage(requireContext(), reminder.sourceEntrance)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = HaloApp.getInstance().resources.displayMetrics.widthPixels - 60F.dip2px()
|
||||
val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_EXPIRATION_REMINDER = "key_expiration_reminder"
|
||||
|
||||
private const val BUTTON_NAME_KNOW = "知道了"
|
||||
private const val BUTTON_NAME_BUY = "前往购买"
|
||||
|
||||
fun checkDialogShown(context: Context, reminder: ExpirationReminder, callback: ((Boolean) -> Unit)? = null) {
|
||||
|
||||
when (reminder) {
|
||||
is ExpirationReminder.UserExpired -> {
|
||||
val days = SPUtils.getLong(Constants.SP_ACCELERATOR_USER_REMAINING_REMIND)
|
||||
if (reminder.days != days) {
|
||||
SPUtils.setLong(Constants.SP_ACCELERATOR_USER_REMAINING_REMIND, reminder.days)
|
||||
show(context, reminder)
|
||||
callback?.invoke(true)
|
||||
} else {
|
||||
callback?.invoke(false)
|
||||
}
|
||||
}
|
||||
|
||||
is ExpirationReminder.InsufficientDuration -> {
|
||||
val hours = SPUtils.getLong(Constants.SP_ACCELERATOR_DURATION_REMAINING_HOURS)
|
||||
if (reminder.hours != hours) {
|
||||
SPUtils.setLong(Constants.SP_ACCELERATOR_DURATION_REMAINING_HOURS, reminder.hours)
|
||||
show(context, reminder)
|
||||
callback?.invoke(true)
|
||||
} else {
|
||||
callback?.invoke(false)
|
||||
}
|
||||
}
|
||||
|
||||
is ExpirationReminder.DurationExpired -> {
|
||||
val days = SPUtils.getLong(Constants.SP_ACCELERATOR_DURATION_REMAINING_DAYS)
|
||||
if (reminder.days != days) {
|
||||
SPUtils.setLong(Constants.SP_ACCELERATOR_DURATION_REMAINING_DAYS, reminder.days)
|
||||
show(context, reminder)
|
||||
callback?.invoke(true)
|
||||
} else {
|
||||
callback?.invoke(false)
|
||||
}
|
||||
}
|
||||
|
||||
is ExpirationReminder.TimeRunsOut -> {
|
||||
val hasShow = SPUtils.getBoolean(Constants.SP_ACCELERATOR_MEMBERSHIP_EXPIRED)
|
||||
if (!hasShow) {
|
||||
SPUtils.setBoolean(Constants.SP_ACCELERATOR_MEMBERSHIP_EXPIRED, true)
|
||||
show(context, reminder)
|
||||
callback?.invoke(true)
|
||||
} else {
|
||||
callback?.invoke(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun show(context: Context, reminder: ExpirationReminder) {
|
||||
if (context is AppCompatActivity) {
|
||||
context.supportFragmentManager
|
||||
} else {
|
||||
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
|
||||
}?.let {
|
||||
val fragment = AccelerateExpirationDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(KEY_EXPIRATION_REMINDER, reminder)
|
||||
}
|
||||
}
|
||||
fragment.show(it, AcceleratorPermissionGuideDialogFragment::class.java.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ExpirationReminder(
|
||||
val gameId: String,
|
||||
val gameName: String,
|
||||
val pkgName: String,
|
||||
val sourceEntrance: String
|
||||
) :
|
||||
Parcelable {
|
||||
|
||||
abstract val dialogName: String
|
||||
|
||||
@Parcelize
|
||||
data class InsufficientDuration(
|
||||
val hours: Long,
|
||||
private val _gameId: String,
|
||||
private val _gameName: String,
|
||||
private val _pkgName: String,
|
||||
private val _sourceEntrance: String,
|
||||
) :
|
||||
ExpirationReminder(_gameId, _gameName, _pkgName, _sourceEntrance) {
|
||||
|
||||
override val dialogName: String
|
||||
get() = "时长不足提示弹窗"
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class DurationExpired(
|
||||
val days: Long,
|
||||
private val _gameId: String,
|
||||
private val _gameName: String,
|
||||
private val _pkgName: String,
|
||||
private val _sourceEntrance: String,
|
||||
) :
|
||||
ExpirationReminder(_gameId, _gameName, _pkgName, _sourceEntrance) {
|
||||
|
||||
override val dialogName: String
|
||||
get() = "计时套餐临期提示弹窗"
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class UserExpired(
|
||||
val days: Long,
|
||||
private val _gameId: String,
|
||||
private val _gameName: String,
|
||||
private val _pkgName: String,
|
||||
private val _sourceEntrance: String,
|
||||
) :
|
||||
ExpirationReminder(_gameId, _gameName, _pkgName, _sourceEntrance) {
|
||||
|
||||
override val dialogName: String
|
||||
get() = "包月套餐临期提示弹窗"
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class TimeRunsOut(
|
||||
private val _sourceEntrance: String,
|
||||
) : ExpirationReminder("", "", "", _sourceEntrance) {
|
||||
|
||||
override val dialogName: String
|
||||
get() = "时长耗尽提示弹窗"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.gamecenter.common.HaloApp
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.DialogFragmentAcceleratorPermissionGuideBinding
|
||||
|
||||
class AcceleratorPermissionGuideDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private lateinit var binding: DialogFragmentAcceleratorPermissionGuideBinding
|
||||
|
||||
private var callback: (() -> Unit)? = null
|
||||
|
||||
override fun onBack(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return DialogFragmentAcceleratorPermissionGuideBinding.inflate(inflater, container, false)
|
||||
.also {
|
||||
binding = it
|
||||
}.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
SPUtils.setBoolean(Constants.SP_ACCELERATOR_PERMISSION_GUIDE_SHOW, true)
|
||||
binding.tvSubmit.setOnClickListener {
|
||||
dismiss()
|
||||
callback?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun setOnCallback(block: () -> Unit) {
|
||||
this.callback = block
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = HaloApp.getInstance().resources.displayMetrics.widthPixels - 60F.dip2px()
|
||||
val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun show(context: Context, callback: () -> Unit) {
|
||||
if (context is AppCompatActivity) {
|
||||
context.supportFragmentManager
|
||||
} else {
|
||||
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
|
||||
}?.let {
|
||||
val fragment = AcceleratorPermissionGuideDialogFragment()
|
||||
fragment.setOnCallback(callback)
|
||||
fragment.show(it, AcceleratorPermissionGuideDialogFragment::class.java.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,7 @@ import com.gh.common.pop.EditBindWechatPop
|
||||
import com.gh.common.pop.RealNameTipsPop
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.WechatConfigEntity
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
@ -83,79 +84,90 @@ class ReserveSuccessReminderDialog(
|
||||
handlers.clear()
|
||||
binding.flContentContainer.removeAllViews()
|
||||
|
||||
val smsConfig = reserveReminder.smsConfig
|
||||
val wechatConfig = reserveReminder.wechatConfig
|
||||
when {
|
||||
reserveReminder.onlyShowWechatReminder && !wechatConfig.isReminderEnable -> { // 只显示微信:未开启
|
||||
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
|
||||
arrayListOf(OnlyWechatReminderUnableHandler(16.dp, binding.flContentContainer, this))
|
||||
val configTypes = mutableListOf<Int>()
|
||||
// 短信
|
||||
if (reserveReminder.hasSmsConfig) {
|
||||
if (reserveReminder.smsConfig.notice) {
|
||||
configTypes.add(SMS_REMINDER_ENABLE_TYPE)
|
||||
} else {
|
||||
configTypes.add(SMS_REMINDER_UNABLE_TYPE)
|
||||
}
|
||||
|
||||
|
||||
reserveReminder.onlyShowWechatReminder && wechatConfig.isReminderEnable -> { // 只显示微信:已开
|
||||
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
|
||||
arrayListOf(
|
||||
WechatReminderEnableHandler(
|
||||
reserveReminder.wechatConfig.nickName,
|
||||
8.dp,
|
||||
binding.flContentContainer,
|
||||
this
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
!smsConfig.notice && !wechatConfig.isReminderEnable -> { // 短信,微信未开启
|
||||
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
|
||||
arrayListOf(
|
||||
SmsReminderUnableHandler(16.dp, binding.flContentContainer, this),
|
||||
WechatReminderUnableHandler(8.dp, binding.flContentContainer, this)
|
||||
)
|
||||
}
|
||||
|
||||
smsConfig.notice && wechatConfig.isReminderEnable -> {// 短信,微信已开启
|
||||
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
|
||||
arrayListOf(
|
||||
SmsReminderEnableHandler(reserveReminder.smsConfig, 8.dp, binding.flContentContainer, this),
|
||||
WechatReminderEnableHandler(
|
||||
reserveReminder.wechatConfig.nickName,
|
||||
8.dp,
|
||||
binding.flContentContainer,
|
||||
this
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
smsConfig.notice && !wechatConfig.isReminderEnable -> { // 短信开启,微信未开启
|
||||
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
|
||||
arrayListOf(
|
||||
SmsReminderEnableHandler(smsConfig, 8.dp, binding.flContentContainer, this),
|
||||
WechatReminderUnableHandler(16.dp, binding.flContentContainer, this)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
!smsConfig.notice && wechatConfig.isReminderEnable -> { // 微信开启,短信未开启
|
||||
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
|
||||
arrayListOf(
|
||||
WechatReminderEnableHandler(
|
||||
wechatConfig.nickName,
|
||||
8.dp,
|
||||
binding.flContentContainer,
|
||||
this
|
||||
),
|
||||
SmsReminderUnableHandler(16.dp, binding.flContentContainer, this)
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
|
||||
arrayListOf()
|
||||
}
|
||||
}.let {
|
||||
handlers.clear()
|
||||
handlers.addAll(it)
|
||||
}
|
||||
|
||||
// 微信
|
||||
if (reserveReminder.wechatConfig.isReminderEnable) {
|
||||
configTypes.add(WECHAT_REMINDER_ENABLE_TYPE)
|
||||
} else {
|
||||
configTypes.add(WECHAT_REMINDER_UNABLE_TYPE)
|
||||
}
|
||||
|
||||
// 日历
|
||||
if (reserveReminder.hasCalendarConfig) {
|
||||
if (reserveReminder.calendarConfig.notice) {
|
||||
configTypes.add(CALENDAR_REMINDER_ENABLE_TYPE)
|
||||
} else {
|
||||
configTypes.add(CALENDAR_REMINDER_UNABLE_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
if (configTypes.size == 1) {
|
||||
// 只有微信提醒
|
||||
if (configTypes.first() == WECHAT_REMINDER_ENABLE_TYPE) {
|
||||
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
|
||||
handlers.add(
|
||||
WechatReminderEnableHandler(reserveReminder.wechatConfig, 8.dp, binding.flContentContainer, this)
|
||||
)
|
||||
} else {
|
||||
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
|
||||
handlers.add(OnlyWechatReminderUnableHandler(16.dp, binding.flContentContainer, this))
|
||||
}
|
||||
} else {
|
||||
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
|
||||
var isLargerSpacing = true
|
||||
fun getPaddingTop(): Int {
|
||||
val paddingTop = if (isLargerSpacing) 16.dp else 8.dp
|
||||
isLargerSpacing = false
|
||||
return paddingTop
|
||||
}
|
||||
configTypes.sorted().forEach {
|
||||
when (it) {
|
||||
SMS_REMINDER_ENABLE_TYPE -> {
|
||||
isLargerSpacing = true
|
||||
SmsReminderEnableHandler(reserveReminder.smsConfig, 8.dp, binding.flContentContainer, this)
|
||||
}
|
||||
|
||||
SMS_REMINDER_UNABLE_TYPE -> {
|
||||
SmsReminderUnableHandler(getPaddingTop(), binding.flContentContainer, this)
|
||||
}
|
||||
|
||||
|
||||
WECHAT_REMINDER_ENABLE_TYPE -> {
|
||||
isLargerSpacing = true
|
||||
WechatReminderEnableHandler(
|
||||
reserveReminder.wechatConfig,
|
||||
8.dp,
|
||||
binding.flContentContainer,
|
||||
this
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
WECHAT_REMINDER_UNABLE_TYPE ->
|
||||
WechatReminderUnableHandler(getPaddingTop(), binding.flContentContainer, this)
|
||||
|
||||
CALENDAR_REMINDER_ENABLE_TYPE -> {
|
||||
isLargerSpacing = true
|
||||
CalendarReminderEnableHandler(8.dp, binding.flContentContainer, this)
|
||||
}
|
||||
|
||||
CALENDAR_REMINDER_UNABLE_TYPE ->
|
||||
CalendarReminderUnableHandler(getPaddingTop(), binding.flContentContainer, this)
|
||||
|
||||
else -> null
|
||||
}?.let(handlers::add)
|
||||
}
|
||||
}
|
||||
|
||||
handlers.forEach {
|
||||
binding.flContentContainer.addView(it.init())
|
||||
}
|
||||
@ -220,9 +232,14 @@ class ReserveSuccessReminderDialog(
|
||||
listener.changeWechatBinding()
|
||||
}
|
||||
|
||||
override fun updateCalendarReminder() {
|
||||
listener.updateCalendarReminder()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
window?.let {
|
||||
it.setDimAmount(0.4F)
|
||||
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
val params = it.attributes
|
||||
params.width = DisplayUtils.dip2px(300F)
|
||||
@ -244,6 +261,13 @@ class ReserveSuccessReminderDialog(
|
||||
private val Int.dp: Int
|
||||
get() = DisplayUtils.dip2px(this.toFloat())
|
||||
|
||||
private const val SMS_REMINDER_ENABLE_TYPE = 1
|
||||
private const val WECHAT_REMINDER_ENABLE_TYPE = 2
|
||||
private const val CALENDAR_REMINDER_ENABLE_TYPE = 3
|
||||
private const val SMS_REMINDER_UNABLE_TYPE = 4
|
||||
private const val WECHAT_REMINDER_UNABLE_TYPE = 5
|
||||
private const val CALENDAR_REMINDER_UNABLE_TYPE = 6
|
||||
|
||||
fun create(context: Context, listener: OnReserveReminderListener) =
|
||||
ReserveSuccessReminderDialog(
|
||||
context,
|
||||
@ -360,7 +384,7 @@ class ReserveSuccessReminderDialog(
|
||||
}
|
||||
|
||||
class WechatReminderEnableHandler(
|
||||
private val nickName: String,
|
||||
private val wechatConfig: WechatConfigEntity,
|
||||
topMargin: Int,
|
||||
parent: ViewGroup,
|
||||
listener: OnReserveSuccessListener
|
||||
@ -380,7 +404,7 @@ class ReserveSuccessReminderDialog(
|
||||
}.root
|
||||
|
||||
override fun initView() {
|
||||
binding.tvWechat.text = nickName
|
||||
binding.tvWechat.text = wechatConfig.nickName
|
||||
binding.vModifyWechat.setOnClickListener {
|
||||
editWechatPop.showAsDropDown(
|
||||
binding.ivModifyWechat,
|
||||
@ -411,6 +435,51 @@ class ReserveSuccessReminderDialog(
|
||||
|
||||
}
|
||||
|
||||
class CalendarReminderUnableHandler(
|
||||
topMargin: Int,
|
||||
parent: ViewGroup,
|
||||
listener: OnReserveSuccessListener
|
||||
) : ReminderContentHandler(topMargin, parent, listener) {
|
||||
|
||||
private lateinit var binding: LayoutReserveWechatReminderUnableBinding
|
||||
|
||||
// 复用微信提醒未开启状态布局
|
||||
override fun createView(inflater: LayoutInflater) =
|
||||
LayoutReserveWechatReminderUnableBinding.inflate(inflater, parent, false)
|
||||
.also {
|
||||
binding = it
|
||||
}.root
|
||||
|
||||
override fun initView() {
|
||||
binding.tvWechatReminderTitle.setText(R.string.calendar_reminders)
|
||||
binding.tvWechatReminderDescription.setText(R.string.calendar_reminders_description)
|
||||
binding.vWechatAdd.setOnClickListener {
|
||||
listener.updateCalendarReminder()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CalendarReminderEnableHandler(
|
||||
topMargin: Int,
|
||||
parent: ViewGroup,
|
||||
listener: OnReserveSuccessListener
|
||||
) : ReminderContentHandler(topMargin, parent, listener) {
|
||||
|
||||
private lateinit var binding: LayoutReserveCalendarReminderUnableBinding
|
||||
|
||||
override fun createView(inflater: LayoutInflater) =
|
||||
LayoutReserveCalendarReminderUnableBinding.inflate(inflater, parent, false)
|
||||
.also {
|
||||
binding = it
|
||||
}.root
|
||||
|
||||
override fun initView() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -425,4 +494,6 @@ interface OnReserveSuccessListener {
|
||||
fun verifyPhoneNumber()
|
||||
|
||||
fun changeWechatBinding()
|
||||
|
||||
fun updateCalendarReminder()
|
||||
}
|
||||
@ -19,7 +19,7 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
ExposureThrottleBus(
|
||||
{ commitExposure(it) },
|
||||
Consumer(Throwable::printStackTrace),
|
||||
{ commitWXCPMExposure(it) }
|
||||
{ commitExternalExposure(it) }
|
||||
)
|
||||
}
|
||||
var layoutManager: LayoutManager? = null
|
||||
@ -31,7 +31,7 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
|
||||
if (fragment == f) {
|
||||
visibleState?.let { commitExposure(it) }
|
||||
visibleState?.let { commitWXCPMExposure(it) }
|
||||
visibleState?.let { commitExternalExposure(it) }
|
||||
throttleBus.clear()
|
||||
}
|
||||
}
|
||||
@ -97,23 +97,33 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小游戏CPM曝光事件接口上报,由于普通曝光事件的上报通道存在节流特性,不符合CPM接口对于数据上报的实时性和准确性的要求,所以使用额外的通道进行上报
|
||||
* 提交第三方的曝光事件 (微信小游戏CPM 和 DSP 游戏)
|
||||
* 由于普通曝光事件的上报通道存在节流特性,不符合CPM接口对于数据上报的实时性和准确性的要求,所以使用额外的通道进行上报
|
||||
*/
|
||||
private fun commitWXCPMExposure(visibleState: ExposureThrottleBus.VisibleState) {
|
||||
private fun commitExternalExposure(visibleState: ExposureThrottleBus.VisibleState) {
|
||||
|
||||
val eventList = arrayListOf<ExposureEvent>()
|
||||
val cpmEventList = arrayListOf<ExposureEvent>()
|
||||
val dspEventList = arrayListOf<ExposureEvent>()
|
||||
|
||||
for (pos in visibleState.firstVisiblePosition..visibleState.lastVisiblePosition) {
|
||||
try {
|
||||
exposable.getEventByPosition(pos)?.let {
|
||||
if (it.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
|
||||
eventList.add(it)
|
||||
when (it.payload.miniGameType) {
|
||||
Constants.WECHAT_MINI_GAME_CPM -> cpmEventList.add(it)
|
||||
Constants.DSP_GAME -> dspEventList.add(it)
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
exposable.getEventListByPosition(pos)?.let { list ->
|
||||
list.forEach {
|
||||
if (it.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
|
||||
eventList.add(it)
|
||||
when (it.payload.miniGameType) {
|
||||
Constants.WECHAT_MINI_GAME_CPM -> cpmEventList.add(it)
|
||||
Constants.DSP_GAME -> dspEventList.add(it)
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,7 +131,8 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
// Just ignore the error.
|
||||
}
|
||||
}
|
||||
ExposureManager.logCPM(eventList)
|
||||
ExposureManager.logExternal(cpmEventList, dspEventList)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -6,7 +6,9 @@ import com.gh.gamecenter.common.loghub.TLogHubHelper
|
||||
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.dsp.DspReportHelper
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.minigame.wechat.WGameSubjectCPMListReportHelper
|
||||
import com.lightgame.utils.Utils
|
||||
import com.volcengine.model.tls.LogItem
|
||||
@ -36,6 +38,10 @@ object ExposureManager {
|
||||
AppExecutor.logExecutor.execute {
|
||||
if (event.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
|
||||
WGameSubjectCPMListReportHelper.reportExposure(event)
|
||||
} else if (event.payload.miniGameType == Constants.DSP_GAME) {
|
||||
if (event.event == ExposureType.DOWNLOAD_COMPLETE) {
|
||||
DspReportHelper.report(event.payload.downloadUrl)
|
||||
}
|
||||
}
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
exposureSet.add(event)
|
||||
@ -64,12 +70,18 @@ object ExposureManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a wechat mini game cpm collection of exposure event.
|
||||
* Log a collection of exposure event for external use.
|
||||
*/
|
||||
fun logCPM(eventList: List<ExposureEvent>) {
|
||||
fun logExternal(cpmEventList: List<ExposureEvent>, dspEventList: ArrayList<ExposureEvent>) {
|
||||
AppExecutor.logExecutor.execute {
|
||||
if (eventList.isNotEmpty()) {
|
||||
WGameSubjectCPMListReportHelper.reportExposure(eventList.toSet())
|
||||
if (cpmEventList.isNotEmpty()) {
|
||||
WGameSubjectCPMListReportHelper.reportExposure(cpmEventList.toSet())
|
||||
}
|
||||
|
||||
if (dspEventList.isNotEmpty()) {
|
||||
for (event in dspEventList) {
|
||||
DspReportHelper.report(event.payload.showUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +89,7 @@ object ExposureUtils {
|
||||
exposureEvent.payload.path = path
|
||||
exposureEvent.payload.speed = speed
|
||||
exposureEvent.payload.redirectedUrlList = redirectedUrlList
|
||||
exposureEvent.payload.downloadUrl = gameEntity.downloadUrl
|
||||
|
||||
ExposureManager.log(exposureEvent)
|
||||
ExposureManager.commitSavedExposureEvents(forcedUpload = true)
|
||||
|
||||
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.PackageFlavorHelper
|
||||
import com.gh.gamecenter.common.utils.debounceActionWithInterval
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
@ -123,10 +124,16 @@ object RegionSettingHelper {
|
||||
mIsInit = false
|
||||
}
|
||||
|
||||
val fakeIp = if (PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
SPUtils.getString(Constants.SP_TEST_FLAVOR_IP)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
// 使用默认的 Schdulers.io() 可能会触发 OOM
|
||||
RetrofitManager.getInstance()
|
||||
.api
|
||||
.getRegionSetting(HaloApp.getInstance().channel)
|
||||
.getRegionSetting(HaloApp.getInstance().channel, fakeIp)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<RegionSetting>() {
|
||||
override fun onSuccess(data: RegionSetting) {
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package com.gh.common.interceptor
|
||||
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.therouter.router.RouteItem
|
||||
import com.therouter.router.interceptor.RouterReplaceInterceptor
|
||||
import com.therouter.router.matchRouteMap
|
||||
|
||||
/**
|
||||
* 主拦截器
|
||||
*/
|
||||
class MainInterceptor: RouterReplaceInterceptor() {
|
||||
|
||||
override fun replace(routeItem: RouteItem?): RouteItem? {
|
||||
if (routeItem == null) return null
|
||||
|
||||
// 用户是否已经同意隐私政策
|
||||
val isUserAcceptPrivacyPolicy = HaloApp.isUserAcceptPrivacyPolicy(HaloApp.getInstance())
|
||||
|
||||
// 如果用户已经同意隐私政策并且应用已经启动,直接返回 routeItem ,运行跳转
|
||||
if (isUserAcceptPrivacyPolicy && HaloApp.getInstance().isAlreadyUpAndRunning) {
|
||||
return routeItem
|
||||
}
|
||||
|
||||
// 指向调整为 SplashScreenActivity
|
||||
return matchRouteMap(RouteConsts.activity.splashActivity)
|
||||
}
|
||||
|
||||
}
|
||||
@ -59,7 +59,7 @@ class CustomFloatingWindowHandler(priority: Int) : PriorityChainHandler(priority
|
||||
override fun onProcess(): Boolean {
|
||||
when (getStatus()) {
|
||||
STATUS_VALID -> {
|
||||
_showFloatingAction.value = Event(data)
|
||||
_showFloatingAction.postValue(Event(data))
|
||||
return true
|
||||
// floatingWindowProvider.showFloatingWindowOnly(
|
||||
// mFragment!!,
|
||||
|
||||
@ -64,7 +64,8 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
* 预启动所有的优先级弹窗管理链
|
||||
*/
|
||||
fun preStart(withSpecialDelay: Boolean) {
|
||||
val launchRedirectHandler = LaunchRedirectHandler(-101)
|
||||
val launchRedirectHandler = LaunchRedirectHandler(-102)
|
||||
val membershipExpiredHandler = MembershipExpiredHandler(-101)
|
||||
val updateDialogHandler = UpdateDialogHandler(-100)
|
||||
val privacyPolicyDialogHandler = PrivacyPolicyDialogHandler(-99)
|
||||
val notificationPermissionDialogHandler = NotificationPermissionDialogHandler(0)
|
||||
@ -74,6 +75,7 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
val resumeDownloadHandler = ResumeDownloadHudHandler(4)
|
||||
|
||||
mainChain.addHandler(launchRedirectHandler)
|
||||
mainChain.addHandler(membershipExpiredHandler)
|
||||
mainChain.addHandler(updateDialogHandler)
|
||||
mainChain.addHandler(privacyPolicyDialogHandler)
|
||||
mainChain.addHandler(welcomeDialogHandler)
|
||||
@ -83,6 +85,7 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
mainChain.addHandler(resumeDownloadHandler)
|
||||
|
||||
launchRedirectHandler.doPreProcess()
|
||||
membershipExpiredHandler.doPreProcess()
|
||||
updateDialogHandler.doPreProcess()
|
||||
|
||||
// 首次启动延迟 300ms,保证请求首次启动时已经获取到了 GID 、 OAID 等标记
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.common.dialog.AccelerateExpirationDialogFragment
|
||||
import com.gh.gamecenter.common.constant.Constants.SP_ACCELERATOR_MEMBERSHIP_EXPIRED
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.login.user.UserRepository
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
|
||||
class MembershipExpiredHandler(priority: Int) : PriorityChainHandler(priority) {
|
||||
|
||||
fun doPreProcess() {
|
||||
UserRepository.getInstance().setAutoLoginListener {
|
||||
val hasShow = SPUtils.getBoolean(SP_ACCELERATOR_MEMBERSHIP_EXPIRED)
|
||||
val vipEntity = AcceleratorDataHolder.instance.vipEntity
|
||||
if (getStatus() == STATUS_PENDING) {
|
||||
if (vipEntity == null ||
|
||||
vipEntity.vipStatus ||
|
||||
vipEntity.isNewUser ||
|
||||
vipEntity.isVipRefundUser ||
|
||||
vipEntity.isDurationRefundUser ||
|
||||
hasShow
|
||||
) {
|
||||
processNext()
|
||||
} else {
|
||||
updateStatus(STATUS_VALID)
|
||||
process()
|
||||
}
|
||||
} else {
|
||||
if (vipEntity == null ||
|
||||
vipEntity.vipStatus ||
|
||||
vipEntity.isNewUser ||
|
||||
vipEntity.isVipRefundUser ||
|
||||
vipEntity.isDurationRefundUser ||
|
||||
hasShow
|
||||
) {
|
||||
updateStatus(STATUS_INVALID)
|
||||
} else {
|
||||
updateStatus(STATUS_VALID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProcess(): Boolean {
|
||||
val currentActivity = CurrentActivityHolder.getCurrentActivity()
|
||||
if (GlobalPriorityChainHelper.isThisActivityValid(currentActivity)) {
|
||||
when (getStatus()) {
|
||||
STATUS_VALID -> {
|
||||
val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.TimeRunsOut("")
|
||||
SPUtils.setBoolean(SP_ACCELERATOR_MEMBERSHIP_EXPIRED, true)
|
||||
val dialogFragment = AccelerateExpirationDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(
|
||||
AccelerateExpirationDialogFragment.KEY_EXPIRATION_REMINDER, reminder
|
||||
)
|
||||
}
|
||||
}
|
||||
dialogFragment.dialog?.setOnDismissListener {
|
||||
processNext()
|
||||
}
|
||||
dialogFragment.show(
|
||||
(currentActivity as FragmentActivity).supportFragmentManager,
|
||||
AccelerateExpirationDialogFragment::class.java.name
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
STATUS_INVALID -> {
|
||||
processNext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -4,8 +4,10 @@ import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.gamecenter.common.databinding.LayoutGameItemSellingPointBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.provider.IBindingAdaptersProvider
|
||||
import com.gh.gamecenter.home.custom.adapter.CustomViewExt
|
||||
|
||||
@com.therouter.inject.ServiceProvider
|
||||
class BindingAdaptersProviderImpl : IBindingAdaptersProvider {
|
||||
@ -18,7 +20,7 @@ class BindingAdaptersProviderImpl : IBindingAdaptersProvider {
|
||||
}
|
||||
|
||||
override fun setGameTags(layout: LinearLayout, gameEntity: GameEntity) {
|
||||
BindingAdapters.setGameTags(layout, gameEntity)
|
||||
BindingAdapters.setGameTags(layout, gameEntity, "")
|
||||
}
|
||||
|
||||
override fun setMessageUnread(view: TextView, unreadCount: Int) {
|
||||
@ -28,4 +30,17 @@ class BindingAdaptersProviderImpl : IBindingAdaptersProvider {
|
||||
override fun setGame(view: View, gameEntity: GameEntity) {
|
||||
BindingAdapters.setGame(view, gameEntity)
|
||||
}
|
||||
|
||||
override fun setGameTagsWithSellingPoints(
|
||||
layout: LinearLayout,
|
||||
sellingPointsBinding: LayoutGameItemSellingPointBinding,
|
||||
gameEntity: GameEntity,
|
||||
subjectTag: String
|
||||
) {
|
||||
BindingAdapters.setGameTagsWithSellingPoint(layout, sellingPointsBinding, gameEntity, subjectTag)
|
||||
}
|
||||
|
||||
override fun setGameDescription(tvDesc: TextView, briefStyle: String, game: GameEntity) {
|
||||
CustomViewExt.setDescription(tvDesc, briefStyle, game)
|
||||
}
|
||||
}
|
||||
@ -31,4 +31,6 @@ class BuildConfigImpl : IBuildConfigProvider {
|
||||
override fun getWGameCPMBusiAppId(): String = BuildConfig.WGAME_CPM_BUSIAPPID
|
||||
|
||||
override fun getLogProducerProject(): String = BuildConfig.LOG_HUB_PROJECT
|
||||
|
||||
override fun getDspApiHost(): String = BuildConfig.DSP_API_HOST
|
||||
}
|
||||
@ -2,6 +2,8 @@ package com.gh.common.provider
|
||||
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity
|
||||
@ -11,6 +13,7 @@ import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.provider.IDownloadButtonClickedProvider
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
@ -27,6 +30,9 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
|
||||
var packageName = ""
|
||||
var exposureSourceList: List<ExposureSource>? = null
|
||||
var customPageTrackData: CustomPageTrackData? = null
|
||||
val pushMessageId = (HaloApp.get(Constants.PUSH_MESSAGE_ID, false) as? String) ?: ""
|
||||
val pushLinkId = (HaloApp.get(Constants.PUSH_LINK_ENTITY, false) as? LinkEntity)?.link ?: ""
|
||||
val isFromPush = pushMessageId.isNotEmpty()
|
||||
|
||||
val boundedObject = downloadButton.getObject()
|
||||
|
||||
@ -113,8 +119,10 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
|
||||
}
|
||||
|
||||
// 小游戏的启动不需要上报下载点击事件
|
||||
// @see https://jira.shanqu.cc/browse/GHZSCY-7013
|
||||
if (boundedObject is GameEntity && boundedObject.isMiniGame()) {
|
||||
// @see https://jira.shanqu.cc/browse/GHZSCY-7013 & https://jira.shanqu.cc/browse/GHZSCY-7918
|
||||
if (boundedObject is GameEntity
|
||||
&& (boundedObject.isMiniGame() || boundedObject.isDspGame)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -136,6 +144,9 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
|
||||
"last_page_name", GlobalActivityManager.getLastPageEntity().pageName,
|
||||
"last_page_id", GlobalActivityManager.getLastPageEntity().pageId,
|
||||
"last_page_business_id", GlobalActivityManager.getLastPageEntity().pageBusinessId,
|
||||
"is_from_push_notifications", isFromPush,
|
||||
"message_id", pushMessageId,
|
||||
"link_id", pushLinkId,
|
||||
*customPageKV
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,24 +1,57 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import com.gh.common.util.PackageUtils
|
||||
import android.annotation.SuppressLint
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.core.provider.IAcceleratorDataHolderProvider
|
||||
import com.gh.gamecenter.feature.entity.BaseEntity
|
||||
import com.gh.gamecenter.feature.entity.VipEntity
|
||||
import com.gh.gamecenter.login.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
|
||||
@com.therouter.inject.ServiceProvider
|
||||
class IAcceleratorDataHolderProviderImpl : IAcceleratorDataHolderProvider {
|
||||
override fun setVipEntity(vip: Any) {
|
||||
if (vip is VipEntity) {
|
||||
AcceleratorDataHolder.instance.setVipEntity(vip)
|
||||
|
||||
override fun isPaidVip(): Boolean =
|
||||
AcceleratorDataHolder.instance.isPaidVip
|
||||
|
||||
override fun getGhVersionName(): String {
|
||||
return PackageUtils.getGhVersionName()
|
||||
}
|
||||
|
||||
/**
|
||||
* 请注意,由于光环后端无法获取 奇游时长套餐 加速时长,这里的 vipStatus不准,
|
||||
* 这里只做参考,具体的状态需要奇游sdk提供,如果奇游sdk返回失败,则以这条接口结果为准
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
override fun loadVipEntityFromGh(userId: String, callBack: (Any?) -> Unit) {
|
||||
RetrofitManager.getInstance().newApi.getVipStatus(
|
||||
userId.ifBlank { UserManager.getInstance().userId },
|
||||
"gjonline_vip",
|
||||
true
|
||||
)
|
||||
.compose(singleToMain())
|
||||
.subscribe(object : BiResponse<BaseEntity<VipEntity>>() {
|
||||
override fun onSuccess(data: BaseEntity<VipEntity>) {
|
||||
callBack(data.data)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
callBack(null)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
override fun updateVipEntity(data: Any) {
|
||||
if (data is VipEntity) {
|
||||
AcceleratorDataHolder.instance.setVipEntity(data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addInitFunResult(result: String) {
|
||||
AcceleratorDataHolder.instance.addInitFunResult(result)
|
||||
}
|
||||
|
||||
override fun getInitFunResults(): List<String> {
|
||||
return AcceleratorDataHolder.instance.initResults
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
AcceleratorDataHolder.instance.clear()
|
||||
|
||||
@ -5,7 +5,6 @@ import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.core.provider.IWechatPayResultProvider
|
||||
import com.gh.gamecenter.feature.entity.OrderEntity
|
||||
import com.gh.gamecenter.feature.entity.VipEntity
|
||||
import com.gh.gamecenter.feature.eventbus.EBPayState
|
||||
import com.halo.assistant.accelerator.repository.AccelerationRepository
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
@ -25,14 +24,8 @@ class WechatPayResultProviderImpl : IWechatPayResultProvider {
|
||||
// 支付成功
|
||||
EventBus.getDefault().post(EBPayState.PaySuccess)
|
||||
|
||||
// 先刷新本地状态,支付成功,肯定是付费会员
|
||||
AcceleratorDataHolder.instance.setVipEntity(
|
||||
VipEntity(
|
||||
_vipStatus = true,
|
||||
_isNewUser = false,
|
||||
_isTryVip = false
|
||||
)
|
||||
)
|
||||
// 先刷新本地状态,支付成功
|
||||
AcceleratorDataHolder.instance.handleUserRechargeSuccess(orderEntity)
|
||||
|
||||
SensorsBridge.trackMemberRechargeResult(
|
||||
AccelerationRepository.PAYMENT_TYPE_WECHAT,
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
@ -12,15 +13,18 @@ import okhttp3.ResponseBody
|
||||
object ActivationHelper {
|
||||
|
||||
private const val HAS_SENT_ACTIVATED_INFO = "has_sent_activated_info"
|
||||
private const val SENT_ACTIVATED_INFO_TIME = "sent_activated_info_time"
|
||||
private const val HAS_SENT_RETENTION_INFO = "has_sent_retention_info"
|
||||
|
||||
var mHasSentActivatedInfo = SPUtils.getBoolean(HAS_SENT_ACTIVATED_INFO, false)
|
||||
private var hasSentActivatedInfo = SPUtils.getBoolean(HAS_SENT_ACTIVATED_INFO, false)
|
||||
private var hasSentRetentionInfo = SPUtils.getBoolean(HAS_SENT_RETENTION_INFO, false)
|
||||
|
||||
/**
|
||||
* 发送激活信息 (用于推广)
|
||||
*/
|
||||
@JvmStatic
|
||||
fun sendActivationInfo() {
|
||||
if (!mHasSentActivatedInfo) {
|
||||
if (!hasSentActivatedInfo) {
|
||||
RetrofitManager.getInstance()
|
||||
.api.postActivationInfo()
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -28,8 +32,36 @@ object ActivationHelper {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
super.onResponse(response)
|
||||
|
||||
mHasSentActivatedInfo = true
|
||||
hasSentActivatedInfo = true
|
||||
SPUtils.setBoolean(HAS_SENT_ACTIVATED_INFO, true)
|
||||
SPUtils.setLong(SENT_ACTIVATED_INFO_TIME, System.currentTimeMillis())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送次日留存信息 (用于推广)
|
||||
*/
|
||||
@JvmStatic
|
||||
fun sendRetentionInfo() {
|
||||
if (hasSentActivatedInfo && !hasSentRetentionInfo) {
|
||||
val activateTimeMillis = SPUtils.getLong(SENT_ACTIVATED_INFO_TIME, 0)
|
||||
val currentTimeMillis = System.currentTimeMillis()
|
||||
|
||||
if (!TimeUtils.isNextDay(activateTimeMillis, currentTimeMillis)) {
|
||||
return
|
||||
}
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.api.postRetentionInfo()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
super.onResponse(response)
|
||||
|
||||
hasSentRetentionInfo = true
|
||||
SPUtils.setBoolean(HAS_SENT_RETENTION_INFO, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -55,6 +55,8 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
|
||||
viewHolder.setSpeedViewsVisible(false);
|
||||
// 默认为显示状态
|
||||
viewHolder.getDownloadPb().setVisibility(View.VISIBLE);
|
||||
|
||||
// 根据预置的配置更新 ViewHolder 的状态 (譬如青少年模式、下载内容为空等)
|
||||
if (updateViewHolderWithPredefinedConfig(viewHolder, gameEntity)) {
|
||||
@ -100,9 +102,9 @@ public class DetailDownloadUtils {
|
||||
viewHolder.getLocalDownloadContainer().setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
// 畅玩未安装,且当前下载的默认类型为"普通下载",且用户未安装时,禁用双按钮,禁用畅玩
|
||||
if (!VHelper.isInstalled(gameEntity.getUniquePackageName())
|
||||
&& !PackagesManager.isInstalled(gameEntity.getUniquePackageName())
|
||||
// 1.畅玩未安装/当前游戏配置了加速,且当前下载的默认类型为"普通下载",且用户未安装时,禁用双按钮,禁用畅玩
|
||||
if ((!VHelper.isInstalled(gameEntity.getUniquePackageName())
|
||||
&& !PackagesManager.isInstalled(gameEntity.getUniquePackageName()) || gameEntity.getCanSpeed())
|
||||
&& downloadEntity != null
|
||||
&& ExtensionsKt.isLocalDownloadInDualDownloadMode(downloadEntity)
|
||||
) {
|
||||
@ -110,8 +112,22 @@ public class DetailDownloadUtils {
|
||||
if (viewHolder.getOverlayTv() != null) {
|
||||
viewHolder.getOverlayTv().setVisibility(View.GONE);
|
||||
}
|
||||
// 此时需要将 本地占位按钮样式改成单条样式
|
||||
if (viewHolder.getLocalDownloadContainer() != null) {
|
||||
viewHolder.getLocalDownloadContainer().setBackgroundResource(com.gh.gamecenter.common.R.drawable.bg_common_button_fill_gradient_blue);
|
||||
}
|
||||
if (viewHolder.getLocalDownloadTitleTv() != null) {
|
||||
viewHolder.getLocalDownloadTitleTv().setTextColor(ExtensionsKt.toColor(com.gh.gamecenter.common.R.color.text_aw_primary, viewHolder.getContext()));
|
||||
}
|
||||
} else {
|
||||
viewHolder.getDownloadPb().setVisibility(View.VISIBLE);
|
||||
// 将占位按钮样式恢复成左半边样式
|
||||
if (viewHolder.getLocalDownloadContainer() != null) {
|
||||
viewHolder.getLocalDownloadContainer().setBackgroundResource(com.gh.gamecenter.common.R.drawable.bg_common_button_light_fill_blue);
|
||||
}
|
||||
if (viewHolder.getLocalDownloadTitleTv() != null) {
|
||||
viewHolder.getLocalDownloadTitleTv().setTextColor(ExtensionsKt.toColor(com.gh.gamecenter.common.R.color.text_theme, viewHolder.getContext()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,12 +154,11 @@ public class DetailDownloadUtils {
|
||||
showDualDownloadButton,
|
||||
downloadEntity
|
||||
);
|
||||
|
||||
if(!showVGame){
|
||||
String rawBtnText = GameUtils.getDownloadBtnText(viewHolder.getContext(), gameEntity, false, showVGame, PluginLocation.only_game);
|
||||
viewHolder.checkIfShowSpeedUi(rawBtnText);
|
||||
if (downloadEntity != null && downloadEntity.getStatus() != DownloadStatus.done) {
|
||||
// 如果存在未完成的任务,则不显示加速按钮
|
||||
} else {
|
||||
viewHolder.checkIfShowSpeedUi(showVGame, showDualDownloadButton);
|
||||
}
|
||||
|
||||
} else {
|
||||
// 游戏包含多 APK 的情况
|
||||
viewHolder.getMultiVersionDownloadTv().setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord));
|
||||
@ -610,7 +625,7 @@ public class DetailDownloadUtils {
|
||||
return (int) Math.ceil(downloadEntity.getPercent());
|
||||
}
|
||||
|
||||
private static String convertSizeString(String sizeString) {
|
||||
public static String convertSizeString(String sizeString) {
|
||||
String numberPart;
|
||||
String indicator;
|
||||
|
||||
|
||||
@ -854,7 +854,8 @@ object DirectUtils {
|
||||
entrance: String? = null,
|
||||
autoDownload: Boolean? = null,
|
||||
tab: String? = "",
|
||||
traceEvent: ExposureEvent? = null
|
||||
traceEvent: ExposureEvent? = null,
|
||||
from: String? = null
|
||||
) {
|
||||
if (id.isEmpty()) return
|
||||
|
||||
@ -862,6 +863,7 @@ object DirectUtils {
|
||||
.path(RouteConsts.activity.gameDetailActivity)
|
||||
.appendQueryParameter(KEY_ENTRANCE, entrance)
|
||||
.appendQueryParameter(KEY_GAME_ID, id)
|
||||
.appendQueryParameter(KEY_FROM, from)
|
||||
.build()
|
||||
|
||||
TheRouter
|
||||
@ -1128,9 +1130,15 @@ object DirectUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun directToWebView(context: Context, url: String, entrance: String? = null) {
|
||||
directToWebView(context, url, entrance, null)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToWebView(context: Context, url: String, entrance: String? = null, title: String? = null) {
|
||||
if (url.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(EntranceConsts.KEY_GAMENAME, title)
|
||||
if (url.contains("android_page_type=singleton")) {
|
||||
bundle.putString(KEY_TO, SingletonWebActivity::class.java.simpleName)
|
||||
} else {
|
||||
|
||||
@ -61,7 +61,7 @@ object DownloadItemUtils {
|
||||
gameEntity: GameEntity,
|
||||
downloadEntity: DownloadEntity,
|
||||
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
|
||||
index: Int
|
||||
index: Int,
|
||||
) {
|
||||
if (gameEntity.id != downloadEntity.gameId) {
|
||||
adapter?.notifyItemChanged(index)
|
||||
@ -139,7 +139,7 @@ object DownloadItemUtils {
|
||||
context: Context,
|
||||
gameEntity: GameEntity,
|
||||
holder: GameViewHolder,
|
||||
hideDownloadBtnIfNoAvailableContent: Boolean
|
||||
hideDownloadBtnIfNoAvailableContent: Boolean,
|
||||
) {
|
||||
updateItem(
|
||||
context = context,
|
||||
@ -155,7 +155,7 @@ object DownloadItemUtils {
|
||||
context: Context,
|
||||
gameEntity: GameEntity,
|
||||
holder: GameViewHolder,
|
||||
briefStyle: String?
|
||||
briefStyle: String?,
|
||||
) {
|
||||
updateItem(
|
||||
context = context,
|
||||
@ -177,7 +177,7 @@ object DownloadItemUtils {
|
||||
hideDownloadBtnIfNoAvailableContent: Boolean = false,
|
||||
briefStyle: String? = null,
|
||||
isShowRecommendStar: Boolean = false,
|
||||
listener: DownloadButton.OnUpdateListener? = null
|
||||
listener: DownloadButton.OnUpdateListener? = null,
|
||||
) {
|
||||
holder.gameDownloadBtn.putObject(gameEntity)
|
||||
|
||||
@ -223,7 +223,7 @@ object DownloadItemUtils {
|
||||
gameEntity: GameEntity,
|
||||
hideDownloadBtnIfNoAvailableContent: Boolean = false,
|
||||
pluginLocation: PluginLocation? = PluginLocation.only_game,
|
||||
listener: DownloadButton.OnUpdateListener?
|
||||
listener: DownloadButton.OnUpdateListener?,
|
||||
) {
|
||||
// 控制是否显示下载按钮
|
||||
downloadBtn.goneIf(context.getString(R.string.app_name) == gameEntity.name)
|
||||
@ -452,7 +452,8 @@ object DownloadItemUtils {
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.diskioerror,
|
||||
DownloadStatus.overflow -> {
|
||||
DownloadStatus.overflow,
|
||||
-> {
|
||||
buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
setText(com.gh.gamecenter.feature.R.string.resume)
|
||||
listener?.completion(downloadBtn.text)
|
||||
@ -482,7 +483,7 @@ object DownloadItemUtils {
|
||||
holder: GameViewHolder,
|
||||
gameEntity: GameEntity,
|
||||
briefStyle: String?,
|
||||
isShowRecommendStar: Boolean = false
|
||||
isShowRecommendStar: Boolean = false,
|
||||
) {
|
||||
updateItemViewStatus(holder, briefStyle, gameEntity.columnRecommend, isShowRecommendStar)
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
|
||||
@ -507,7 +508,7 @@ object DownloadItemUtils {
|
||||
holder: GameViewHolder,
|
||||
gameEntity: GameEntity,
|
||||
briefStyle: String?,
|
||||
isShowRecommendStar: Boolean = false
|
||||
isShowRecommendStar: Boolean = false,
|
||||
) {
|
||||
val entryMap = gameEntity.getEntryMap()
|
||||
var downloadEntity: DownloadEntity? = null
|
||||
@ -535,11 +536,12 @@ object DownloadItemUtils {
|
||||
context: Context,
|
||||
holder: GameViewHolder,
|
||||
downloadEntity: DownloadEntity,
|
||||
isMultiVersion: Boolean = false
|
||||
isMultiVersion: Boolean = false,
|
||||
) {
|
||||
when (downloadEntity.status) {
|
||||
DownloadStatus.redirected,
|
||||
DownloadStatus.downloading -> {
|
||||
DownloadStatus.downloading,
|
||||
-> {
|
||||
if (isMultiVersion) {
|
||||
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
val darkMode =
|
||||
@ -556,7 +558,8 @@ object DownloadItemUtils {
|
||||
)
|
||||
} else {
|
||||
holder.gameDownloadTips?.visibility = View.GONE
|
||||
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
holder.gameDownloadBtn.buttonStyle =
|
||||
DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
holder.gameDownloadBtn.progress = (downloadEntity.percent * 10).toInt()
|
||||
holder.gameDownloadBtn.text = downloadEntity.percent.toString() + "%"
|
||||
}
|
||||
@ -577,13 +580,15 @@ object DownloadItemUtils {
|
||||
DownloadStatus.diskioerror,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.overflow -> {
|
||||
DownloadStatus.overflow,
|
||||
-> {
|
||||
if (isMultiVersion) {
|
||||
holder.gameDownloadTips?.visibility = View.VISIBLE
|
||||
holder.gameDownloadTips?.setDownloadTipsAnimation(false)
|
||||
}
|
||||
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
holder.gameDownloadBtn.text = context.getString(com.gh.gamecenter.feature.R.string.resume)
|
||||
holder.gameDownloadBtn.text =
|
||||
context.getString(com.gh.gamecenter.feature.R.string.resume)
|
||||
}
|
||||
|
||||
DownloadStatus.done -> {
|
||||
@ -616,7 +621,7 @@ object DownloadItemUtils {
|
||||
holder: GameViewHolder,
|
||||
briefStyle: String?,
|
||||
recommendStyle: LinkEntity?,
|
||||
isShowRecommendStar: Boolean = false
|
||||
isShowRecommendStar: Boolean = false,
|
||||
) {
|
||||
holder.gameDownloadTips?.visibility = View.GONE
|
||||
// 推荐指数优先,现暂时为游戏单详情列表游戏使用
|
||||
@ -655,7 +660,11 @@ object DownloadItemUtils {
|
||||
}
|
||||
|
||||
// 缺省情况下回落到游戏简介
|
||||
if (TextUtils.isEmpty(briefStyle) || briefStyle!!.contains("brief") || briefStyle.contains("recommend")) {
|
||||
if (TextUtils.isEmpty(briefStyle)
|
||||
|| briefStyle!!.contains("brief")
|
||||
|| briefStyle.contains("recommend")
|
||||
|| briefStyle.contains("test&appointment")
|
||||
) {
|
||||
holder.gameDes?.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.gameDes?.visibility = View.GONE
|
||||
@ -671,7 +680,7 @@ object DownloadItemUtils {
|
||||
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
|
||||
entrance: String,
|
||||
location: String,
|
||||
sourceEntrance: String = "其他"
|
||||
sourceEntrance: String = "其他",
|
||||
) {
|
||||
setOnClickListener(
|
||||
context,
|
||||
@ -760,7 +769,7 @@ object DownloadItemUtils {
|
||||
traceEvent: ExposureEvent?,
|
||||
clickCallback: EmptyCallback?,
|
||||
refreshCallback: EmptyCallback?,
|
||||
allStateClickCallback: EmptyCallback?
|
||||
allStateClickCallback: EmptyCallback?,
|
||||
) {
|
||||
// 为 downloadButton 添加游戏实体,供点击的时候上报用
|
||||
downloadBtn.putObject(gameEntity)
|
||||
@ -996,7 +1005,7 @@ object DownloadItemUtils {
|
||||
entrance: String,
|
||||
location: String,
|
||||
traceEvent: ExposureEvent? = null,
|
||||
refreshCallback: EmptyCallback? = null
|
||||
refreshCallback: EmptyCallback? = null,
|
||||
) {
|
||||
val str =
|
||||
if (downloadBtn is DownloadButton) downloadBtn.text else context.getString(com.gh.gamecenter.feature.R.string.download)
|
||||
@ -1105,15 +1114,17 @@ object DownloadItemUtils {
|
||||
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apk.url)
|
||||
|
||||
com.gh.gamecenter.common.utils.NewFlatLogUtils.logGameInstall(
|
||||
gameId = downloadEntity?.gameId ?: "",
|
||||
gameName = downloadEntity?.name ?: "",
|
||||
gameId = gameEntity.id,
|
||||
gameName = gameEntity.name ?: "",
|
||||
trigger = "主动安装"
|
||||
)
|
||||
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
gameId = downloadEntity?.gameId ?: "",
|
||||
gameName = downloadEntity?.name ?: "",
|
||||
action = "主动安装"
|
||||
gameId = gameEntity.id,
|
||||
gameName = gameEntity.name ?: "",
|
||||
action = "主动安装",
|
||||
isDspGame = gameEntity.isDspGame,
|
||||
dspAdId = gameEntity.dspAdId
|
||||
)
|
||||
|
||||
if (gameEntity.simulator != null) {
|
||||
@ -1239,7 +1250,7 @@ object DownloadItemUtils {
|
||||
location: String,
|
||||
asVGame: Boolean,
|
||||
isSubscribe: Boolean,
|
||||
traceEvent: ExposureEvent?
|
||||
traceEvent: ExposureEvent?,
|
||||
) {
|
||||
if (gameEntity.getApk().isEmpty()) return
|
||||
|
||||
@ -1283,7 +1294,7 @@ object DownloadItemUtils {
|
||||
entrance: String,
|
||||
location: String,
|
||||
isSubscribe: Boolean,
|
||||
traceEvent: ExposureEvent?
|
||||
traceEvent: ExposureEvent?,
|
||||
) {
|
||||
val msg = FileUtils.isCanDownload(context, gameEntity.getApk().firstOrNull()?.size ?: "")
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
@ -1310,7 +1321,7 @@ object DownloadItemUtils {
|
||||
gameEntity: GameEntity,
|
||||
position: Int,
|
||||
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
|
||||
refreshCallback: EmptyCallback?
|
||||
refreshCallback: EmptyCallback?,
|
||||
) {
|
||||
val apkEntity = gameEntity.getApk().firstOrNull()
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
|
||||
@ -1353,7 +1364,7 @@ object DownloadItemUtils {
|
||||
location: String,
|
||||
asVGame: Boolean,
|
||||
isSubscribe: Boolean,
|
||||
traceEvent: ExposureEvent?
|
||||
traceEvent: ExposureEvent?,
|
||||
) {
|
||||
|
||||
// 执行更新操作前,先清理历史下载任务,避免冲突
|
||||
|
||||
@ -14,15 +14,16 @@ import com.gh.gamecenter.common.base.GlobalActivityManager.getLastPageEntity
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.common.entity.SuggestType
|
||||
import com.gh.gamecenter.common.eventbus.EBShowDialog
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.dsp.DspReportHelper
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.feature.entity.CustomPageTrackData
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
@ -281,11 +282,10 @@ object DownloadObserver {
|
||||
|
||||
private fun performDownloadCompleteAction(
|
||||
downloadEntity: DownloadEntity,
|
||||
downloadManager: DownloadManager
|
||||
downloadManager: DownloadManager,
|
||||
) {
|
||||
if (downloadEntity.name.contains(mApplication.getString(R.string.app_name))) {
|
||||
statDoneEvent(downloadEntity)
|
||||
MtaHelper.onEvent("软件更新", "下载完成")
|
||||
// 会有 ActivityNotFoundException 异常,catch 掉不管了
|
||||
tryWithDefaultCatch {
|
||||
if (Constants.SILENT_UPDATE != downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)) {
|
||||
@ -298,7 +298,9 @@ object DownloadObserver {
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
gameName = downloadEntity.name,
|
||||
gameId = downloadEntity.gameId,
|
||||
action = "自动安装"
|
||||
action = "自动安装",
|
||||
isDspGame = downloadEntity.getMetaExtra(Constants.DSP_GAME) == "true",
|
||||
dspAdId = downloadEntity.getMetaExtra(Constants.DSP_AD_ID)
|
||||
)
|
||||
|
||||
// TODO 在 Android 11 上没有授权安装未知应用的权限前第一次调用这个方法系统会杀掉我们的进程...
|
||||
@ -395,7 +397,9 @@ object DownloadObserver {
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
gameId = downloadEntity.gameId,
|
||||
gameName = downloadEntity.name,
|
||||
action = "自动安装"
|
||||
action = "自动安装",
|
||||
isDspGame = downloadEntity.getMetaExtra(Constants.DSP_GAME) == "true",
|
||||
dspAdId = downloadEntity.getMetaExtra(Constants.DSP_AD_ID)
|
||||
)
|
||||
PackageInstaller.install(mApplication, downloadEntity, false, ignoreAsVGame = false)
|
||||
}
|
||||
@ -504,7 +508,8 @@ object DownloadObserver {
|
||||
gameVersion = downloadEntity.versionName ?: "",
|
||||
isPlatformRecommend = isPlatformRecommend,
|
||||
adIconActive = downloadEntity.meta[Constants.AD_ICON_ACTIVE].toBoolean(),
|
||||
isAdData = downloadEntity.meta[Constants.IS_AD_DATA].toBoolean()
|
||||
isAdData = downloadEntity.meta[Constants.IS_AD_DATA].toBoolean(),
|
||||
downloadUrl = downloadEntity.meta[Constants.DOWNLOAD_URL]
|
||||
),
|
||||
downloadEntity.platform,
|
||||
downloadEntity.exposureTrace,
|
||||
@ -556,24 +561,81 @@ object DownloadObserver {
|
||||
} else {
|
||||
arrayOf()
|
||||
}
|
||||
SensorsBridge.trackEventWithExposureSource(
|
||||
"DownloadProcessFinish",
|
||||
exposureEvent?.source,
|
||||
"game_id", downloadEntity.gameId,
|
||||
"game_name", downloadEntity.meta[Constants.GAME_NAME] ?: "",
|
||||
"game_type", downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: "",
|
||||
"game_label", downloadEntity.tags.joinToString(","),
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
|
||||
"page_name", getCurrentPageEntity().pageName,
|
||||
"page_id", getCurrentPageEntity().pageId,
|
||||
"page_business_id", getCurrentPageEntity().pageBusinessId,
|
||||
"last_page_name", getLastPageEntity().pageName,
|
||||
"last_page_id", getLastPageEntity().pageId,
|
||||
"last_page_business_id", getLastPageEntity().pageBusinessId,
|
||||
"download_status", downloadEntity.meta[Constants.DOWNLOAD_STATUS_IN_CHINESE] ?: "",
|
||||
"download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
|
||||
*kvs
|
||||
)
|
||||
|
||||
val pushMessageId = (HaloApp.get(Constants.PUSH_MESSAGE_ID, false) as? String) ?: ""
|
||||
val pushLinkId = (HaloApp.get(Constants.PUSH_LINK_ENTITY, false) as? LinkEntity)?.link ?: ""
|
||||
val isFromPush = pushMessageId.isNotEmpty()
|
||||
|
||||
if (downloadEntity.getMetaExtra(Constants.DSP_GAME) != "true") {
|
||||
SensorsBridge.trackEventWithExposureSource(
|
||||
"DownloadProcessFinish",
|
||||
exposureEvent?.source,
|
||||
"game_id",
|
||||
downloadEntity.gameId,
|
||||
"game_name",
|
||||
downloadEntity.meta[Constants.GAME_NAME] ?: "",
|
||||
"game_type",
|
||||
downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: "",
|
||||
"game_label",
|
||||
downloadEntity.tags.joinToString(","),
|
||||
"game_schema_type",
|
||||
if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
|
||||
"page_name",
|
||||
getCurrentPageEntity().pageName,
|
||||
"page_id",
|
||||
getCurrentPageEntity().pageId,
|
||||
"page_business_id",
|
||||
getCurrentPageEntity().pageBusinessId,
|
||||
"last_page_name",
|
||||
getLastPageEntity().pageName,
|
||||
"last_page_id",
|
||||
getLastPageEntity().pageId,
|
||||
"last_page_business_id",
|
||||
getLastPageEntity().pageBusinessId,
|
||||
"download_status",
|
||||
downloadEntity.meta[Constants.DOWNLOAD_STATUS_IN_CHINESE] ?: "",
|
||||
"download_type",
|
||||
if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
|
||||
"is_from_push_notifications",
|
||||
isFromPush,
|
||||
"message_id",
|
||||
pushMessageId,
|
||||
"link_id",
|
||||
pushLinkId,
|
||||
*kvs
|
||||
)
|
||||
} else {
|
||||
val searchContent = downloadEntity.getMetaExtra(Constants.SEARCH_KEY)
|
||||
|
||||
SensorsBridge.trackEventWithExposureSource(
|
||||
"DspAdDownloadFinish",
|
||||
exposureEvent?.source,
|
||||
"ad_id", downloadEntity.getMetaExtra(Constants.DSP_AD_ID),
|
||||
"search_content", searchContent,
|
||||
"game_column_name", downloadEntity.getMetaExtra(Constants.SUBJECT_NAME),
|
||||
"game_column_id", downloadEntity.getMetaExtra(Constants.SUBJECT_ID),
|
||||
"game_id", downloadEntity.gameId,
|
||||
"game_name", downloadEntity.meta[Constants.GAME_NAME] ?: "",
|
||||
"game_type", downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: "",
|
||||
"game_label", downloadEntity.tags.joinToString(","),
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
|
||||
"page_name", getCurrentPageEntity().pageName,
|
||||
"page_id", getCurrentPageEntity().pageId,
|
||||
"page_business_id", getCurrentPageEntity().pageBusinessId,
|
||||
"last_page_name", getLastPageEntity().pageName,
|
||||
"last_page_id", getLastPageEntity().pageId,
|
||||
"last_page_business_id", getLastPageEntity().pageBusinessId,
|
||||
"download_status", downloadEntity.meta[Constants.DOWNLOAD_STATUS_IN_CHINESE] ?: "",
|
||||
"download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
|
||||
"is_from_push_notifications", isFromPush,
|
||||
"message_id", pushMessageId,
|
||||
"link_id", pushLinkId,
|
||||
"location", if (searchContent.isEmpty()) "自定义页面" else "游戏搜索结果列表",
|
||||
*kvs
|
||||
)
|
||||
|
||||
DspReportHelper.report(downloadEntity.getMetaExtra(Constants.DOWNLOAD_URL))
|
||||
}
|
||||
}
|
||||
|
||||
DataCollectionUtils.uploadDownload(mApplication, downloadEntity, "完成")
|
||||
|
||||
@ -111,7 +111,12 @@ object GameUtils {
|
||||
var gh_id: Any?
|
||||
apkFor@ for (apkEntity in gameEntity.getApk()) {
|
||||
|
||||
val isInstalledLocally = PackagesManager.isInstalled(apkEntity.packageName)
|
||||
val isInstalledLocally =
|
||||
if (gameEntity.isDspGame) {
|
||||
PackageHelper.validLocalPackageNameSet.contains(apkEntity.packageName)
|
||||
} else {
|
||||
PackagesManager.isInstalled(apkEntity.packageName)
|
||||
}
|
||||
|
||||
// filter by packageName
|
||||
val settings = Config.getSettings()
|
||||
|
||||
@ -2,21 +2,29 @@ package com.gh.common.util
|
||||
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.common.dialog.AccelerateExpirationDialogFragment
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.PackageObserver
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.core.provider.IAcceleratorProvider
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.hud.HeadUpDisplayHelper
|
||||
import com.gh.gamecenter.hud.HeadUpDisplayLogHelper
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.hud.HeadUpDisplayLogHelper
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.getMetaExtra
|
||||
import com.gh.gamecenter.dsp.DspReportHelper
|
||||
import com.lightgame.utils.Utils
|
||||
import com.therouter.TheRouter
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
@ -27,12 +35,13 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
private const val UNINSTALL_PENDING = 2
|
||||
private const val UPDATE_PENDING = 3
|
||||
|
||||
// <包名,pending 类型,应用版本> Triple
|
||||
private var pendingPackageTriple: Triple<String, Int, String>? = null
|
||||
private var pendingGhId: String? = null
|
||||
// <包名,pending 类型,应用版本,光环ID> 的 pending 集合
|
||||
private var pendingPackageMap: HashMap<String, PackageEntity> = hashMapOf()
|
||||
|
||||
private var pendingHUDShowed: Boolean = false
|
||||
|
||||
private var isLaunching = true
|
||||
|
||||
/**
|
||||
* 添加一个等待中,待确定是否已成功安装的应用
|
||||
*/
|
||||
@ -43,24 +52,21 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待安装成功")
|
||||
|
||||
pendingHUDShowed = false
|
||||
pendingPackageTriple = Triple(packageName, INSTALL_PENDING, "")
|
||||
pendingPackageMap[packageName] = PackageEntity(packageName, INSTALL_PENDING, "")
|
||||
} else {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待安装更新成功")
|
||||
|
||||
val ghId = PackageUtils.getGhId(packageName)
|
||||
|
||||
// 记录光环插件相关信息,用于安装成功后的处理
|
||||
if (ghId != null) {
|
||||
pendingGhId = ghId.toString()
|
||||
}
|
||||
val ghId = PackageUtils.getGhId(packageName)?.toString() ?: ""
|
||||
|
||||
pendingHUDShowed = false
|
||||
pendingPackageTriple = Triple(packageName, UPDATE_PENDING, installData.version)
|
||||
pendingPackageMap[packageName] =
|
||||
PackageEntity(packageName, UPDATE_PENDING, installData.version, ghId)
|
||||
}
|
||||
}
|
||||
|
||||
fun isInstallPendingPackage(packageName: String): Boolean {
|
||||
return pendingPackageTriple?.first == packageName
|
||||
return pendingPackageMap[packageName]?.packageName == packageName
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,87 +74,159 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
*/
|
||||
fun addUninstallPendingPackage(packageName: String) {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待卸载成功")
|
||||
pendingPackageTriple = Triple(packageName, UNINSTALL_PENDING, "")
|
||||
pendingPackageMap[packageName] = PackageEntity(packageName, UNINSTALL_PENDING, "")
|
||||
}
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
super.onCreate(owner)
|
||||
isLaunching = true
|
||||
}
|
||||
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
|
||||
if (pendingPackageTriple != null) {
|
||||
val packageName = pendingPackageTriple?.first ?: return
|
||||
val isInstallPending = pendingPackageTriple?.second == INSTALL_PENDING
|
||||
val isUninstallPending = pendingPackageTriple?.second == UNINSTALL_PENDING
|
||||
val isUpdatePending = pendingPackageTriple?.second == UPDATE_PENDING
|
||||
if (pendingPackageMap.size > 0) {
|
||||
calculateAndDispatchPackageChanges()
|
||||
}
|
||||
|
||||
val pendingVersion = pendingPackageTriple?.third ?: ""
|
||||
refreshVipStatus()
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用从后台切到前台,如果是登录状态,需要刷新用户的vip状态
|
||||
*/
|
||||
private fun refreshVipStatus() {
|
||||
val iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
|
||||
if (iAcceleratorProvider?.hasToken() == true &&
|
||||
AcceleratorDataHolder.instance.enableRefresh &&
|
||||
AcceleratorDataHolder.instance.vipEntity != null &&
|
||||
!isLaunching
|
||||
) {
|
||||
iAcceleratorProvider.loadQyUserPermissionData {
|
||||
val vip = AcceleratorDataHolder.instance.vipEntity
|
||||
if (vip != null && !vip.vipStatus && !vip.isNewUser && !vip.isVipRefundUser && !vip.isDurationRefundUser) {
|
||||
// 获取当前
|
||||
val currentActivity = CurrentActivityHolder.getCurrentActivity()
|
||||
val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.TimeRunsOut("")
|
||||
if (currentActivity != null && HaloApp.getInstance().isRunningForeground) {
|
||||
AccelerateExpirationDialogFragment.checkDialogShown(currentActivity, reminder)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算并分发包名的安装状态
|
||||
*/
|
||||
private fun calculateAndDispatchPackageChanges() {
|
||||
val completeList = arrayListOf<PackageEntity>()
|
||||
val pendingHudPackageList = arrayListOf<String>()
|
||||
|
||||
for (packageEntity in pendingPackageMap.values) {
|
||||
val packageName = packageEntity.packageName
|
||||
val pendingVersion = packageEntity.version
|
||||
val pendingGhId = packageEntity.ghId
|
||||
|
||||
val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName)
|
||||
val isInstalled = installedVersionName != null
|
||||
|
||||
if (isInstallPending) {
|
||||
if (packageEntity.isInstallPending()) {
|
||||
if (isInstalled) {
|
||||
pendingPackageTriple = null
|
||||
pendingGhId = null
|
||||
completeList += packageEntity
|
||||
|
||||
PackageRepository.addInstalledGame(PackageRepository.packageFilterManager, packageName)
|
||||
PackageRepository.addInstalledGame(
|
||||
PackageRepository.packageFilterManager,
|
||||
packageName
|
||||
)
|
||||
|
||||
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(
|
||||
packageName = packageName,
|
||||
isAdd = true
|
||||
)
|
||||
|
||||
performInstallSuccessAction(packageName)
|
||||
} else {
|
||||
// 任务不存在了,将等待更新安装结果的 triple 置为 null
|
||||
if (DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName) == null) {
|
||||
pendingPackageTriple = null
|
||||
// 任务不存在了,将等待更新安装结果的 packageEntity 置为 null
|
||||
if (DownloadManager.getInstance()
|
||||
.getDownloadEntitySnapshotByPackageName(packageName) == null
|
||||
) {
|
||||
completeList += packageEntity
|
||||
} else {
|
||||
showHUDIfNeeded(packageName)
|
||||
pendingHudPackageList.add(packageName)
|
||||
}
|
||||
}
|
||||
} else if (isUninstallPending && !isInstalled) {
|
||||
pendingPackageTriple = null
|
||||
pendingGhId = null
|
||||
} else if (packageEntity.isUninstallPending() && !isInstalled) {
|
||||
completeList += packageEntity
|
||||
|
||||
// 从额外的包名白名单移除,下次启动时不再查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = false)
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(
|
||||
packageName = packageName,
|
||||
isAdd = false
|
||||
)
|
||||
|
||||
performUninstallSuccessAction(packageName)
|
||||
} else if (isUpdatePending) {
|
||||
} else if (packageEntity.isUpdatePending()) {
|
||||
val isUpdateValid = if (installedVersionName != pendingVersion) {
|
||||
true
|
||||
} else {
|
||||
!pendingGhId.isNullOrEmpty() && pendingGhId != PackageUtils.getGhId(packageName).toString()
|
||||
pendingGhId.isNotEmpty()
|
||||
&& pendingGhId != PackageUtils.getGhId(packageName).toString()
|
||||
}
|
||||
|
||||
pendingPackageTriple = null
|
||||
pendingGhId = null
|
||||
|
||||
if (isUpdateValid) {
|
||||
performUninstallSuccessAction(packageName)
|
||||
performInstallSuccessAction(packageName)
|
||||
|
||||
completeList += packageEntity
|
||||
} else {
|
||||
// 任务不存在了,将等待更新安装结果的 triple 置为 null
|
||||
if (DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName) == null) {
|
||||
pendingPackageTriple = null
|
||||
// 任务不存在了,将等待更新安装结果的 packageEntity 置为 null
|
||||
if (DownloadManager.getInstance()
|
||||
.getDownloadEntitySnapshotByPackageName(packageName) == null
|
||||
) {
|
||||
completeList += packageEntity
|
||||
} else {
|
||||
showHUDIfNeeded(packageName)
|
||||
pendingHudPackageList.add(packageName)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(
|
||||
packageName = packageName,
|
||||
isAdd = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for (invalidPackage in completeList) {
|
||||
pendingPackageMap.remove(invalidPackage.packageName)
|
||||
}
|
||||
|
||||
if (pendingHudPackageList.isNotEmpty()) {
|
||||
showHUDIfNeeded(pendingHudPackageList.last())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop(owner: LifecycleOwner) {
|
||||
super.onStop(owner)
|
||||
isLaunching = false
|
||||
}
|
||||
|
||||
private fun showHUDIfNeeded(packageName: String) {
|
||||
if (pendingHUDShowed) return
|
||||
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName) ?: return
|
||||
val downloadEntity =
|
||||
DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName)
|
||||
?: return
|
||||
if (downloadEntity.gameId == Constants.GHZS_GAME_ID) return
|
||||
val activity = CurrentActivityHolder.getCurrentActivity() ?: return
|
||||
if (activity is DownloadManagerActivity) return
|
||||
|
||||
pendingHUDShowed = true
|
||||
HeadUpDisplayHelper.showHUD(activity,
|
||||
HeadUpDisplayHelper.showHUD(
|
||||
activity,
|
||||
downloadEntity.icon ?: "",
|
||||
activity.getString(R.string.hud_has_pending_install_game),
|
||||
activity.getString(R.string.hud_head_to_download_manager),
|
||||
@ -189,16 +267,26 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
private fun performInstallSuccessAction(
|
||||
packageName: String,
|
||||
cachedGameEntity: GameEntity? = null,
|
||||
withLog: Boolean = true
|
||||
withLog: Boolean = true,
|
||||
) {
|
||||
Utils.log(TAG, "安装了: $packageName 包名的程序")
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName)
|
||||
val gameId = if (downloadEntity != null && downloadEntity.gameId != null) downloadEntity.gameId else ""
|
||||
val gameName = if (downloadEntity != null && downloadEntity.name != null) downloadEntity.name else ""
|
||||
val downloadEntity =
|
||||
DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName)
|
||||
val gameId = downloadEntity?.gameId ?: ""
|
||||
val gameName = downloadEntity?.name ?: ""
|
||||
|
||||
if (withLog) {
|
||||
if (withLog && gameId.isNotEmpty()) {
|
||||
NewFlatLogUtils.logGameInstallComplete(gameId, gameName)
|
||||
SensorsBridge.trackInstallGameFinish(gameId, gameName)
|
||||
SensorsBridge.trackInstallGameFinish(
|
||||
gameId,
|
||||
gameName,
|
||||
downloadEntity?.getMetaExtra(Constants.DSP_GAME) == "true",
|
||||
downloadEntity?.getMetaExtra(Constants.DSP_AD_ID) ?: ""
|
||||
)
|
||||
|
||||
if (downloadEntity?.getMetaExtra(Constants.DSP_GAME) == "true") {
|
||||
DspReportHelper.report(downloadEntity.getMetaExtra(Constants.INSTALL_URL))
|
||||
}
|
||||
}
|
||||
|
||||
InstallUtils.getInstance().removeInstall(packageName)
|
||||
@ -237,4 +325,23 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
EventBus.getDefault().post(uninstallEb)
|
||||
}
|
||||
|
||||
private class PackageEntity(
|
||||
val packageName: String,
|
||||
val type: Int,
|
||||
val version: String,
|
||||
val ghId: String = "",
|
||||
) {
|
||||
fun isInstallPending(): Boolean {
|
||||
return type == INSTALL_PENDING
|
||||
}
|
||||
|
||||
fun isUninstallPending(): Boolean {
|
||||
return type == UNINSTALL_PENDING
|
||||
}
|
||||
|
||||
fun isUpdatePending(): Boolean {
|
||||
return type == UPDATE_PENDING
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -95,7 +95,8 @@ object ReservationHelper {
|
||||
it.categoryChinese,
|
||||
data.wechatConfig.isReminderEnable,
|
||||
if (data.hasSmsConfig) data.smsConfig.notice else null,
|
||||
if (data.isEnableAutoDownload) data.wifiAutoDownload else null
|
||||
if (data.isEnableAutoDownload) data.wifiAutoDownload else null,
|
||||
if (data.hasCalendarConfig) false else null
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -2,12 +2,10 @@ package com.gh.common.util
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.therouter.TheRouter
|
||||
import com.gh.common.iinterface.ISuperiorChain
|
||||
import com.gh.gamecenter.amway.AmwayFragment
|
||||
import com.gh.gamecenter.category2.CategoryV2Fragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.provider.IHelpAndFeedbackProvider
|
||||
import com.gh.gamecenter.discovery.DiscoveryFragment
|
||||
@ -38,6 +36,7 @@ import com.gh.gamecenter.toolbox.ToolboxFragment
|
||||
import com.gh.gamecenter.video.detail.HomeVideoFragment
|
||||
import com.gh.gamecenter.wrapper.ToolbarWrapperFragment
|
||||
import com.halo.assistant.fragment.WebFragment
|
||||
import com.therouter.TheRouter
|
||||
|
||||
/**
|
||||
* 通用跳转Fragment方法
|
||||
|
||||
@ -306,21 +306,14 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
// 仅官网渠道上报 XAPK 异常信息
|
||||
if (HaloApp.getInstance().channel == "GH_206") {
|
||||
SentryHelper.onEvent(
|
||||
"XAPK_UNZIP_ERROR",
|
||||
"gameName", downloadEntity.name,
|
||||
"errorDigest", exception.localizedMessage
|
||||
)
|
||||
}
|
||||
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压失败")
|
||||
|
||||
SensorsBridge.trackGameDecompressionFailed(
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name,
|
||||
downloadEntity.categoryChinese
|
||||
downloadEntity.categoryChinese,
|
||||
exception.localizedMessage ?: "unknown error"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ import com.gh.common.util.PackageUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.utils.DeviceUtils;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
@ -360,6 +361,17 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_REQUIRED_G_APPS, gameEntity.getGAppsSwitch());
|
||||
}
|
||||
|
||||
if (gameEntity.isDspGame()) {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.DSP_GAME, "true");
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.SEARCH_KEY, gameEntity.getSearchKey());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.SUBJECT_NAME, gameEntity.getSubjectName());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.SUBJECT_ID, gameEntity.getSubjectId());
|
||||
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.INSTALL_URL, gameEntity.getInstallUrl());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.DOWNLOAD_URL, gameEntity.getDownloadUrl());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.DSP_AD_ID, gameEntity.getDspAdId());
|
||||
}
|
||||
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.KEY_BIT, apkEntity.getBit());
|
||||
|
||||
// 记录是否为双下载按钮模式
|
||||
@ -451,8 +463,15 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
trackDownloadType = "本地下载";
|
||||
}
|
||||
|
||||
String pushMessageId = HaloApp.get(Constants.PUSH_MESSAGE_ID, false) instanceof String
|
||||
? (String) HaloApp.get(Constants.PUSH_MESSAGE_ID, false)
|
||||
: "";
|
||||
String pushLinkId = HaloApp.get(Constants.PUSH_LINK_ENTITY, false) instanceof LinkEntity
|
||||
? ((LinkEntity) HaloApp.get(Constants.PUSH_LINK_ENTITY, false)).getLink()
|
||||
: "";
|
||||
boolean isFromPush = !pushMessageId.isEmpty();
|
||||
|
||||
String[] arrayKv = {
|
||||
Object[] arrayKv = {
|
||||
"game_id", gameEntity.getId(),
|
||||
"game_name", gameEntity.getName(),
|
||||
"game_type", gameEntity.getCategoryChinese(),
|
||||
@ -465,17 +484,49 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
"last_page_id", GlobalActivityManager.getLastPageEntity().getPageId(),
|
||||
"last_page_business_id", GlobalActivityManager.getLastPageEntity().getPageBusinessId(),
|
||||
"download_status", gameEntity.getDownloadStatusChinese(),
|
||||
"download_type", trackDownloadType
|
||||
"download_type", trackDownloadType,
|
||||
"is_from_push_notifications", isFromPush,
|
||||
"message_id", pushMessageId,
|
||||
"link_id", pushLinkId,
|
||||
};
|
||||
|
||||
List<String> kvs = new ArrayList<>(Arrays.asList(arrayKv));
|
||||
List<Object> kvs = new ArrayList<>(Arrays.asList(arrayKv));
|
||||
|
||||
if (customPageTrackData != null) {
|
||||
kvs.addAll(Arrays.asList(customPageTrackData.toKV()));
|
||||
}
|
||||
|
||||
SensorsBridge.trackEventWithExposureSource("DownloadProcessBegin",
|
||||
downloadExposureEvent.getSource(), kvs.toArray(new String[0])
|
||||
);
|
||||
if (!gameEntity.isDspGame()) {
|
||||
SensorsBridge.trackEventWithExposureSource(
|
||||
"DownloadProcessBegin",
|
||||
downloadExposureEvent.getSource(), kvs.toArray(new Object[0])
|
||||
);
|
||||
} else {
|
||||
String searchKey = gameEntity.getSearchKey();
|
||||
String loc;
|
||||
|
||||
if (TextUtils.isEmpty(searchKey)) {
|
||||
loc = "自定义页面";
|
||||
} else {
|
||||
loc = "游戏搜索结果列表";
|
||||
}
|
||||
|
||||
kvs.add("ad_id");
|
||||
kvs.add(gameEntity.getDspAdId());
|
||||
kvs.add("search_content");
|
||||
kvs.add(searchKey);
|
||||
kvs.add("game_column_name");
|
||||
kvs.add(gameEntity.getSubjectName());
|
||||
kvs.add("game_column_id");
|
||||
kvs.add(gameEntity.getSubjectId());
|
||||
kvs.add("location");
|
||||
kvs.add(loc);
|
||||
|
||||
SensorsBridge.trackEventWithExposureSource(
|
||||
"DspAdDownloadBegin",
|
||||
downloadExposureEvent.getSource(), kvs.toArray(new Object[0])
|
||||
);
|
||||
}
|
||||
|
||||
//TODO remove
|
||||
DownloadManager.getInstance().putStatus(downloadEntity.getUrl(), DownloadStatus.downloading);
|
||||
|
||||
@ -175,7 +175,9 @@ object PackageObserver {
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
gameId = mDownloadEntity.gameId,
|
||||
gameName = mDownloadEntity.name,
|
||||
action = "自动安装"
|
||||
action = "自动安装",
|
||||
isDspGame = mDownloadEntity.getMetaExtra(Constants.DSP_GAME) == "true",
|
||||
dspAdId = mDownloadEntity.getMetaExtra(Constants.DSP_AD_ID)
|
||||
)
|
||||
PackageInstaller.install(application, mDownloadEntity)
|
||||
}
|
||||
|
||||
@ -164,7 +164,8 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
true,
|
||||
mTraceEvent,
|
||||
mEntrance,
|
||||
mLocation
|
||||
mLocation,
|
||||
onDownloadClickAction
|
||||
)
|
||||
mBinding.collectionList.layoutManager = createLayoutManager(itemList)
|
||||
mBinding.collectionList.adapter = mCollectionAdapter
|
||||
|
||||
@ -114,7 +114,6 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
view,
|
||||
listOf(
|
||||
R.id.menu_download_iv,
|
||||
R.id.gameBigEvent,
|
||||
R.id.cardContainer,
|
||||
R.id.iv_reserve,
|
||||
R.id.iv_concern,
|
||||
|
||||
@ -119,6 +119,7 @@ import com.sina.weibo.sdk.auth.AuthInfo;
|
||||
import com.sina.weibo.sdk.openapi.IWBAPI;
|
||||
import com.sina.weibo.sdk.openapi.WBAPIFactory;
|
||||
|
||||
import com.therouter.TheRouter;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -222,7 +223,7 @@ public class MainActivity extends BaseActivity {
|
||||
DialogHelper.showCenterWarningDialog(this, "发生闪退", "光环助手发生了闪退,建议安装到最新版本修复异常"
|
||||
, "马上反馈", "马上安装修复",
|
||||
() -> {
|
||||
DirectUtils.directToGameDetail(this, Constants.GHZS_GAME_ID, "", "crash", true, "desc", null);
|
||||
DirectUtils.directToGameDetail(this, Constants.GHZS_GAME_ID, "", "crash", true, "desc", null, "");
|
||||
return null;
|
||||
},
|
||||
() -> {
|
||||
@ -255,9 +256,12 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
// 跳转至其它页面
|
||||
if (getIntent() != null
|
||||
&& getIntent().getExtras() != null
|
||||
&& getIntent().getBooleanExtra(EntranceConsts.KEY_REQUIRE_REDIRECT, false)) {
|
||||
doSkip();
|
||||
&& getIntent().getExtras() != null) {
|
||||
if (getIntent().getBooleanExtra(EntranceConsts.KEY_REQUIRE_REDIRECT, false)) {
|
||||
doSkip();
|
||||
} else if (!TextUtils.isEmpty(getIntent().getStringExtra(EntranceConsts.KEY_THE_ROUTER_PATH))) {
|
||||
doRedirect(getIntent().getStringExtra(EntranceConsts.KEY_THE_ROUTER_PATH));
|
||||
}
|
||||
}
|
||||
|
||||
// debug 模式下的快速跳转页面
|
||||
@ -456,6 +460,10 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
releaseExoSourceCache();
|
||||
|
||||
// 移除推送触发启动记录
|
||||
HaloApp.remove(Constants.PUSH_MESSAGE_ID);
|
||||
HaloApp.remove(Constants.PUSH_LINK_ENTITY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -820,6 +828,19 @@ public class MainActivity extends BaseActivity {
|
||||
}, 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重定向至 TheRouter 配置的页面
|
||||
*/
|
||||
private void doRedirect(String path) {
|
||||
if (getIntent().getExtras() != null) {
|
||||
// 更新 intent 数据,避免页面重建重新跳转
|
||||
getIntent().getExtras().putString(EntranceConsts.KEY_THE_ROUTER_PATH, "");
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
TheRouter.build(path).navigation(this);
|
||||
}, 500L);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Function0<Unit> launchGame(String gamePackageName) {
|
||||
return () -> {
|
||||
@ -923,7 +944,9 @@ public class MainActivity extends BaseActivity {
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
finalDownloadEntity.getGameId(),
|
||||
finalDownloadEntity.getName(),
|
||||
"主动安装"
|
||||
"主动安装",
|
||||
"true".equals(ExtensionsKt.getMetaExtra(finalDownloadEntity, Constants.DSP_GAME)),
|
||||
ExtensionsKt.getMetaExtra(finalDownloadEntity, Constants.DSP_AD_ID)
|
||||
);
|
||||
PackageInstaller.install(MainActivity.this, finalDownloadEntity);
|
||||
}, 200);
|
||||
@ -1044,7 +1067,9 @@ public class MainActivity extends BaseActivity {
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
downloadEntity.getGameId(),
|
||||
downloadEntity.getName(),
|
||||
"自动安装"
|
||||
"自动安装",
|
||||
"true".equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.DSP_GAME)),
|
||||
ExtensionsKt.getMetaExtra(downloadEntity, Constants.DSP_AD_ID)
|
||||
);
|
||||
PackageInstaller.install(this, downloadEntity, false, false);
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.gamecenter;
|
||||
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_BROWSER;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_OTHER;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_PUSH;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ANSWER;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ARCHIVE_LOGIN;
|
||||
@ -35,6 +36,7 @@ import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_VIDEO_STREAM
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_VIDEO_STREAMING_HOME;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_WEB;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_DATA;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_FROM;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_GAME_NAME;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_NAME;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_PACKAGENAME;
|
||||
@ -100,7 +102,6 @@ public class SkipActivity extends BaseActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Uri uri = getIntent().getData();
|
||||
Bundle bundle;
|
||||
if (uri != null) {
|
||||
@ -160,7 +161,8 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToArticle(this, path, entrance);
|
||||
break;
|
||||
case HOST_GAME:
|
||||
DirectUtils.directToGameDetail(this, path, "", entrance, "true".equals(uri.getQueryParameter("auto_download")), to, null);
|
||||
String from = uri.getQueryParameter(KEY_FROM);
|
||||
DirectUtils.directToGameDetail(this, path, "", entrance, "true".equals(uri.getQueryParameter("auto_download")), to, null, from);
|
||||
break;
|
||||
case HOST_COLUMN:
|
||||
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), entrance, null, SubjectData.SubjectType.NORMAL);
|
||||
@ -180,7 +182,7 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToAnswerDetail(this, path, entrance, pathName);
|
||||
break;
|
||||
case HOST_QUESTION:
|
||||
DirectUtils.directToQuestionDetail(this, path, entrance, pathName, "");
|
||||
DirectUtils.directToQuestionDetail(this, path, entrance, pathName, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
|
||||
break;
|
||||
case HOST_TOOLBOX:
|
||||
DirectUtils.directToToolbox(this, uri.getQueryParameter("gameId"), uri.getQueryParameter("toolboxUrl"), entrance);
|
||||
@ -190,7 +192,7 @@ public class SkipActivity extends BaseActivity {
|
||||
break;
|
||||
// 社区文章格式一
|
||||
case "community.article":
|
||||
DirectUtils.directToCommunityArticle(this, uri.getQueryParameter("articleId"), uri.getQueryParameter("communityId"), entrance, pathName, "");
|
||||
DirectUtils.directToCommunityArticle(this, uri.getQueryParameter("articleId"), uri.getQueryParameter("communityId"), entrance, pathName, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
|
||||
break;
|
||||
// 社区文章格式二
|
||||
case "communities":
|
||||
@ -211,13 +213,13 @@ public class SkipActivity extends BaseActivity {
|
||||
}
|
||||
}
|
||||
if ("articles".equals(type)) {
|
||||
DirectUtils.directToCommunityArticle(this, typeId, communityId, entrance, pathName, "");
|
||||
DirectUtils.directToCommunityArticle(this, typeId, communityId, entrance, pathName, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HOST_VIDEO:
|
||||
DirectUtils.directToVideoDetail(this, path, VideoDetailContainerViewModel.Location.HOTTEST_GAME_VIDEO.getValue(),
|
||||
false, id, entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, "");
|
||||
false, id, entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
|
||||
break;
|
||||
case HOST_UPLOAD_VIDEO://跳转上传视频
|
||||
String titleParameter = uri.getQueryParameter("title");
|
||||
@ -237,7 +239,7 @@ public class SkipActivity extends BaseActivity {
|
||||
break;
|
||||
case HOST_VIDEO_SINGLE:
|
||||
DirectUtils.directToVideoDetail(this, path, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.getValue(),
|
||||
false, "", entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, "");
|
||||
false, "", entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
|
||||
break;
|
||||
case HOST_VIDEO_MORE:
|
||||
gameId = uri.getQueryParameter("gameId");
|
||||
@ -294,7 +296,7 @@ public class SkipActivity extends BaseActivity {
|
||||
EntranceUtils.jumpActivityCompat(this, bundle);
|
||||
break;
|
||||
case EntranceConsts.HOST_VIDEO_DETAIL:
|
||||
DirectUtils.directToVideoDetail(this, path, entrance, "", "");
|
||||
DirectUtils.directToVideoDetail(this, path, entrance, "", isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
|
||||
break;
|
||||
case HOST_LIBAO:
|
||||
DirectUtils.directToGiftDetail(this, path, entrance);
|
||||
@ -315,7 +317,7 @@ public class SkipActivity extends BaseActivity {
|
||||
break;
|
||||
|
||||
case HOST_COLUMN_COLLECTION:
|
||||
DirectUtils.directToColumnCollection(this, path, -1, entrance, "", "", "", "", null,false);
|
||||
DirectUtils.directToColumnCollection(this, path, -1, entrance, "", "", "", "", null, false);
|
||||
break;
|
||||
case EntranceConsts.HOST_BLOCK:
|
||||
name = uri.getQueryParameter("name");
|
||||
@ -357,7 +359,7 @@ public class SkipActivity extends BaseActivity {
|
||||
byte[] linkData = Base64.decode(dataString, Base64.DEFAULT);
|
||||
String linkDataString = new String(linkData, "UTF-8");
|
||||
LaunchRedirect launchRedirect = GsonUtils.fromJson(linkDataString, LaunchRedirect.class);
|
||||
DirectUtils.directToLinkPage(this, launchRedirect, entrance, "", "");
|
||||
DirectUtils.directToLinkPage(this, launchRedirect, entrance, "", isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -414,13 +416,13 @@ public class SkipActivity extends BaseActivity {
|
||||
break;
|
||||
case HOST_ARCHIVE_LOGIN:
|
||||
String gamePkg = uri.getQueryParameter(EntranceConsts.KEY_GAME_PKG);
|
||||
if(CheckLoginUtils.isLogin()) {
|
||||
if (CheckLoginUtils.isLogin()) {
|
||||
VHelper.INSTANCE.updateAuthorizeInfo(true);
|
||||
} else {
|
||||
Bundle newBundle = new Bundle();
|
||||
newBundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivityCompat(this, newBundle, null, (resultCode, data) -> {
|
||||
if(CheckLoginUtils.isLogin()) {
|
||||
if (CheckLoginUtils.isLogin()) {
|
||||
VHelper.INSTANCE.updateAuthorizeInfo(true);
|
||||
}
|
||||
VHelper.launch(this, gamePkg, false, false);
|
||||
|
||||
@ -5,6 +5,7 @@ import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
@ -26,6 +27,9 @@ import com.gh.common.util.UsageStatsHelper.checkAndPostUsageStats
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts.KEY_FROM
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts.KEY_GAMEID
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.tracker.TrackerLogger
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
@ -90,8 +94,9 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
|
||||
showPrivacyDialog()
|
||||
} else {
|
||||
val spanBuilder = buildSpannedString {
|
||||
append("这个弹窗只会在右上角有环境标签的测试包出现" +
|
||||
"\n进入应用以后还可以到关于我们页面长按应用图标重新选择"
|
||||
append(
|
||||
"这个弹窗只会在右上角有环境标签的测试包出现" +
|
||||
"\n进入应用以后还可以到关于我们页面长按应用图标重新选择"
|
||||
)
|
||||
bold {
|
||||
color(com.gh.gamecenter.common.R.color.text_theme.toColor(this@SplashScreenActivity)) {
|
||||
@ -104,7 +109,7 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
|
||||
executeDex2OatInAdvance()
|
||||
DialogHelper.showDialog(
|
||||
context = this,
|
||||
title ="选择环境",
|
||||
title = "选择环境",
|
||||
content = spanBuilder,
|
||||
confirmText = "正式环境",
|
||||
cancelText = "测试环境",
|
||||
@ -145,6 +150,10 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
|
||||
val trackEvent = JSONObject()
|
||||
// 是否首次使用神策
|
||||
val isFirstTime = SPUtils.getBoolean(Constants.SP_SENSORS_IS_FIRST_TIME, true)
|
||||
val therouterPath = intent.extras?.getString(EntranceConsts.KEY_THE_ROUTER_PATH) ?: ""
|
||||
val uri = Uri.parse(therouterPath)
|
||||
val isFromWechat = WECHAT_APPOINTMENT == if (!uri.isOpaque) uri.getQueryParameter(KEY_FROM) else false
|
||||
val gameId = if (!uri.isOpaque) uri.getQueryParameter(KEY_GAMEID) else ""
|
||||
tryCatchInRelease {
|
||||
trackEvent.run {
|
||||
put("\$is_first_time", isFirstTime)
|
||||
@ -154,6 +163,10 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
|
||||
put("signature", signatureHash)
|
||||
put("app_name", appProvider?.getAppName())
|
||||
put("install_first_time", if (HaloApp.getInstance().isBrandNewInstall) "是" else "否")
|
||||
if (isFromWechat) {
|
||||
put("source_entrance", WECHAT_NOTIFICATION)
|
||||
put("page_business_id", gameId)
|
||||
}
|
||||
}
|
||||
}
|
||||
SensorsBridge.trackEvent("AppLaunch", trackEvent)
|
||||
@ -324,6 +337,9 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
|
||||
const val HONOR_CULPRIT_ID = 12324
|
||||
const val HONOR_CULPRIT_CHANNEL = "荣耀通道"
|
||||
|
||||
private const val WECHAT_APPOINTMENT = "wechat_appointment"
|
||||
private const val WECHAT_NOTIFICATION = "微信通知"
|
||||
|
||||
@JvmStatic
|
||||
fun getSplashScreenIntent(context: Context?, bundle: Bundle?): Intent {
|
||||
val intent = Intent(context, SplashScreenActivity::class.java)
|
||||
|
||||
@ -23,6 +23,7 @@ import com.gh.common.simulator.NewSimulatorGameManager
|
||||
import com.gh.common.simulator.SimulatorDownloadManager
|
||||
import com.gh.common.simulator.SimulatorGameManager
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.GameUtils.getDownloadBtnText
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
@ -44,6 +45,7 @@ import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.eventbus.EBScroll
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.feature.view.DownloadButton.ButtonStyle
|
||||
@ -102,17 +104,23 @@ class DetailViewHolder(
|
||||
val speedContainer: ConstraintLayout?
|
||||
private val ivFreeVipTag: ImageView?
|
||||
private val gMoreZone: Group?
|
||||
private val gUpdate: Group?
|
||||
private val ivUpdate: ImageView?
|
||||
private val tvSize: TextView?
|
||||
private val vUpdate: View?
|
||||
private val tvUpdate: TextView?
|
||||
|
||||
private var isShowVaUpdate = true
|
||||
|
||||
// 注意 View 的命名
|
||||
init {
|
||||
downloadBottom = view.findViewById(R.id.detail_ll_bottom)
|
||||
downloadPb = view.findViewById(R.id.detail_progressbar)
|
||||
downloadTips = view.findViewById(R.id.downloadTipsLottie)
|
||||
downloadPb = downloadBottom.findViewById(R.id.detail_progressbar)
|
||||
downloadTips = downloadBottom.findViewById(R.id.downloadTipsLottie)
|
||||
overlayTv = view.findViewById(R.id.overlayTv)
|
||||
overlayContainer = view.findViewById(R.id.overlayContainer)
|
||||
extraOverlayTv = view.findViewById(R.id.extraOverlayTv)
|
||||
multiVersionDownloadTv = view.findViewById(R.id.multiVersionDownloadTv)
|
||||
multiVersionDownloadTv = downloadBottom.findViewById(R.id.multiVersionDownloadTv)
|
||||
localDownloadContainer = view.findViewById(R.id.localDownloadContainer)
|
||||
localDownloadSizeTv = view.findViewById(R.id.localDownloadSizeTv)
|
||||
localDownloadTitleTv = view.findViewById(R.id.localDownloadTitleTv)
|
||||
@ -121,8 +129,14 @@ class DetailViewHolder(
|
||||
speedContainer = view.findViewById(R.id.cl_speed_container)
|
||||
ivFreeVipTag = view.findViewById(R.id.iv_free_vip_tag)
|
||||
gMoreZone = view.findViewById(R.id.g_more_zone)
|
||||
gUpdate = view.findViewById(R.id.g_update)
|
||||
ivUpdate = view.findViewById(R.id.iv_update)
|
||||
tvSize = view.findViewById(R.id.tv_size)
|
||||
vUpdate = view.findViewById(R.id.v_update)
|
||||
tvUpdate = view.findViewById(R.id.tv_update)
|
||||
|
||||
context = view.context
|
||||
com.gh.gamecenter.common.R.color.text_aw_primary.toColor()
|
||||
|
||||
var gameDownloadMode = gameEntity.getGameDownloadButtonMode()
|
||||
|
||||
@ -181,8 +195,19 @@ class DetailViewHolder(
|
||||
com.gh.gamecenter.feature.R.string.download_local
|
||||
)
|
||||
)
|
||||
|
||||
vUpdate?.setOnClickListener {
|
||||
if (isShowVaUpdate) {
|
||||
vGameDownloadListener.onClick(vUpdate)
|
||||
} else {
|
||||
localDownloadListener.onClick(vUpdate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
downloadPb.putWidgetBusinessName("游戏详情页")
|
||||
// "DownLoadbuttonClick" 埋点需要上报traceEvent信息
|
||||
|
||||
@ -199,25 +224,83 @@ class DetailViewHolder(
|
||||
}
|
||||
|
||||
|
||||
fun checkIfShowSpeedUi(rawBtnText: String) {
|
||||
fun checkIfShowSpeedUi(showVGame: Boolean, showDualDownloadButton: Boolean) {
|
||||
acceleratorUiHelper?.let {
|
||||
when {
|
||||
rawBtnText == "启动" && gameEntity.canSpeed -> {
|
||||
downloadPb.goneIf(true)
|
||||
localDownloadButton?.goneIf(true)
|
||||
it.checkIfShowSpeedUi(true)
|
||||
val showSpeedUi = when {
|
||||
gameEntity.canSpeed && showDualDownloadButton -> { // 双按钮
|
||||
val localText = getDownloadBtnText(context, gameEntity, false, false, PluginLocation.only_game);
|
||||
val downloadText =
|
||||
getDownloadBtnText(context, gameEntity, false, true, PluginLocation.only_game)
|
||||
when {
|
||||
localText.contains(com.gh.gamecenter.feature.R.string.update.toResString()) -> { // 本地游戏需要更新
|
||||
localDownloadContainer?.goneIf(true)
|
||||
downloadPb.goneIf(true)
|
||||
overlayTv?.goneIf(true)
|
||||
|
||||
gUpdate?.visibility = View.VISIBLE
|
||||
ivUpdate?.goneIf(true)
|
||||
tvSize?.goneIf(false)
|
||||
tvSize?.text =
|
||||
DetailDownloadUtils.convertSizeString(gameEntity.getApk().firstOrNull()?.size ?: "")
|
||||
tvUpdate?.setText(R.string.update)
|
||||
isShowVaUpdate = false
|
||||
true
|
||||
}
|
||||
|
||||
localText.contains(com.gh.gamecenter.feature.R.string.launch.toResString()) && downloadText == "更新" -> { // 畅玩游戏需要更新:显示 加速/更新
|
||||
localDownloadContainer?.goneIf(true)
|
||||
downloadPb.goneIf(true)
|
||||
overlayTv?.goneIf(true)
|
||||
|
||||
gUpdate?.visibility = View.VISIBLE
|
||||
ivUpdate?.goneIf(false)
|
||||
tvSize?.goneIf(true)
|
||||
tvUpdate?.setText(R.string.update)
|
||||
isShowVaUpdate = true
|
||||
true
|
||||
}
|
||||
|
||||
localText.contains(com.gh.gamecenter.feature.R.string.launch.toResString()) -> { // 本地游戏为启动状态:显示 加速/畅玩
|
||||
localDownloadContainer?.goneIf(true)
|
||||
downloadPb.goneIf(true)
|
||||
overlayTv?.goneIf(true)
|
||||
|
||||
gUpdate?.visibility = View.VISIBLE
|
||||
tvUpdate?.setText(R.string.v_play)
|
||||
tvSize?.goneIf(true)
|
||||
isShowVaUpdate = true
|
||||
true
|
||||
}
|
||||
|
||||
else -> {
|
||||
gUpdate?.visibility = View.GONE
|
||||
tvSize?.goneIf(true)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rawBtnText == "更新" && gameEntity.canSpeed -> {
|
||||
it.checkIfShowSpeedUi(true)
|
||||
gameEntity.canSpeed && !showVGame -> {
|
||||
gUpdate?.visibility = View.GONE
|
||||
val downloadText = getDownloadBtnText(context, gameEntity, false, false, PluginLocation.only_game)
|
||||
when {
|
||||
downloadText.contains(com.gh.gamecenter.feature.R.string.launch.toResString()) -> {
|
||||
localDownloadContainer?.goneIf(true)
|
||||
downloadPb.goneIf(true)
|
||||
true
|
||||
}
|
||||
|
||||
downloadText.contains(R.string.update.toResString()) -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
it.checkIfShowSpeedUi(false)
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
it.checkIfShowSpeedUi(showSpeedUi, showDualDownloadButton)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun setSpeedViewsVisible(isVisible: Boolean) {
|
||||
@ -311,7 +394,9 @@ class DetailViewHolder(
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
mGameEntity.id,
|
||||
mGameEntity.name ?: "",
|
||||
"主动安装"
|
||||
"主动安装",
|
||||
mGameEntity.isDspGame,
|
||||
mGameEntity.dspAdId
|
||||
)
|
||||
PackageInstaller.install(mViewHolder.context, mDownloadEntity)
|
||||
}
|
||||
@ -436,7 +521,9 @@ class DetailViewHolder(
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
gameId = mGameEntity.id,
|
||||
gameName = mGameEntity.name ?: "",
|
||||
action = "主动安装"
|
||||
action = "主动安装",
|
||||
isDspGame = mGameEntity.isDspGame,
|
||||
dspAdId = mGameEntity.dspAdId
|
||||
)
|
||||
val url = mGameEntity.getApk().firstOrNull()?.url
|
||||
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(url)
|
||||
|
||||
@ -242,7 +242,7 @@ class CategoryV2ListAdapter(
|
||||
gameIconView.displayGameIcon(gameEntity)
|
||||
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
|
||||
BindingAdapters.setGameName(gameName, gameEntity, false)
|
||||
BindingAdapters.setGameTags(labelList, gameEntity)
|
||||
BindingAdapters.setGameTags(labelList, gameEntity, "")
|
||||
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null)
|
||||
gameRating.text = if (gameEntity.commentCount > 3) {
|
||||
if (gameEntity.star == 10.0F) "10" else gameEntity.star.toString()
|
||||
|
||||
@ -318,7 +318,9 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
downloadEntity.getGameId(),
|
||||
downloadEntity.getName(),
|
||||
"主动安装"
|
||||
"主动安装",
|
||||
false,
|
||||
""
|
||||
);
|
||||
PackageInstaller.install(mContext, downloadEntity);
|
||||
}
|
||||
@ -397,7 +399,9 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
SensorsBridge.trackInstallGameClick(
|
||||
downloadEntity.getGameId(),
|
||||
downloadEntity.getName(),
|
||||
"主动安装"
|
||||
"主动安装",
|
||||
"true".equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.DSP_GAME)),
|
||||
ExtensionsKt.getMetaExtra(downloadEntity, Constants.DSP_AD_ID)
|
||||
);
|
||||
PackageInstaller.install(mContext, downloadEntity);
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import com.gh.gamecenter.common.base.BaseSimpleDao
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager.getCurrentPageEntity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager.getLastPageEntity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.GsonUtils.toJson
|
||||
@ -142,6 +143,8 @@ class UpdatableGameViewModel(
|
||||
|
||||
// 按包名分
|
||||
for (update in updatableList) {
|
||||
if (update.id == Constants.GHZS_GAME_ID) continue
|
||||
|
||||
var list = packageNameAndUpdateListMap[update.packageName]
|
||||
if (list == null) {
|
||||
list = arrayListOf()
|
||||
@ -686,6 +689,9 @@ class UpdatableGameViewModel(
|
||||
// 收集下载数据
|
||||
DataCollectionUtils.uploadDownload(getApplication(), downloadEntity, "开始")
|
||||
|
||||
val pushMessageId = (HaloApp.get(Constants.PUSH_MESSAGE_ID, false) as? String) ?: ""
|
||||
val pushLinkId = (HaloApp.get(Constants.PUSH_LINK_ENTITY, false) as? LinkEntity)?.link ?: ""
|
||||
val isFromPush = pushMessageId.isNotEmpty()
|
||||
SensorsBridge.trackEventWithExposureSource(
|
||||
"DownloadProcessBegin",
|
||||
event.source,
|
||||
@ -701,6 +707,9 @@ class UpdatableGameViewModel(
|
||||
"last_page_business_id", getLastPageEntity().pageBusinessId,
|
||||
"download_status", update.downloadStatusChinese,
|
||||
"download_type", "本地下载",
|
||||
"is_from_push_notifications", isFromPush,
|
||||
"message_id", pushMessageId,
|
||||
"link_id", pushLinkId,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
46
app/src/main/java/com/gh/gamecenter/dsp/DspReportHelper.kt
Normal file
46
app/src/main/java/com/gh/gamecenter/dsp/DspReportHelper.kt
Normal file
@ -0,0 +1,46 @@
|
||||
package com.gh.gamecenter.dsp
|
||||
|
||||
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.lightgame.utils.Utils
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
||||
object DspReportHelper {
|
||||
|
||||
private const val TAG = "DspReportHelper"
|
||||
private val reportCache by lazy { FixedSizeLinkedHashSet<String>(100) }
|
||||
|
||||
fun report(url: String?) {
|
||||
url ?: return
|
||||
|
||||
AppExecutor.logExecutor.execute {
|
||||
if (reportCache.contains(url)) {
|
||||
Utils.log(TAG, "遇到重复上报,自动过滤 ($url)")
|
||||
return@execute
|
||||
}
|
||||
|
||||
try {
|
||||
val client = OkHttpClient()
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.build()
|
||||
|
||||
Utils.log(TAG, "Report is executing: $url")
|
||||
|
||||
val response = client.newCall(request).execute()
|
||||
if (response.isSuccessful) {
|
||||
// Add the URL to the cache to prevent duplicate reports
|
||||
reportCache.add(url)
|
||||
|
||||
Utils.log(TAG, "Report successful: ${response.body?.string()}")
|
||||
} else {
|
||||
Utils.log(TAG, "Request failed with code: ${response.code}")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Utils.log(TAG, "Request failed: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.gh.gamecenter.dsp.data
|
||||
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.utils.toRequestBody
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.DspApiService
|
||||
import io.reactivex.Single
|
||||
|
||||
class GameSubjectDSPRemoteDataSource(private val api: DspApiService = RetrofitManager.getInstance().dspApiService) {
|
||||
|
||||
fun getDspGames(type: String, count: Int): Single<List<GameEntity>> {
|
||||
val meta = MetaUtil.getMeta()
|
||||
val request = mapOf(
|
||||
"device" to mapOf(
|
||||
"oaid" to (meta.oaid ?: ""),
|
||||
"brand" to (meta.manufacturer ?: ""),
|
||||
"model" to (meta.model ?: ""),
|
||||
"osv" to (MetaUtil.getAndroidVersion()),
|
||||
),
|
||||
"count" to count,
|
||||
"scene" to 3,
|
||||
"busid" to "guanghuan1205"
|
||||
)
|
||||
return api.fetch(request.toRequestBody())
|
||||
.map {
|
||||
val gameEntityList = mutableListOf<GameEntity>()
|
||||
for (bidEntity in it.bidList) {
|
||||
val gameEntity = bidEntity.toGameEntity()
|
||||
gameEntityList.add(gameEntity)
|
||||
}
|
||||
gameEntityList
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,6 +11,8 @@ class ReserveReminderEntity(
|
||||
private var _smsConfig: SmsConfig? = null,
|
||||
@SerializedName("wechat_config")
|
||||
private var _wechatConfig: WechatConfigEntity? = null,
|
||||
@SerializedName("calendar_config")
|
||||
private var _calendarConfig: CalendarConfig? = null,
|
||||
@SerializedName("mirror_type")
|
||||
private val _mirrorType: String? = null,
|
||||
@SerializedName("wifi_auto_download")
|
||||
@ -34,8 +36,14 @@ class ReserveReminderEntity(
|
||||
_wechatConfig = value
|
||||
}
|
||||
|
||||
val onlyShowWechatReminder: Boolean
|
||||
get() = _smsConfig == null
|
||||
val hasCalendarConfig: Boolean
|
||||
get() = _calendarConfig != null
|
||||
|
||||
var calendarConfig: CalendarConfig
|
||||
get() = _calendarConfig ?: CalendarConfig()
|
||||
set(value) {
|
||||
_calendarConfig = value
|
||||
}
|
||||
|
||||
val mirrorType: String
|
||||
get() = _mirrorType ?: ""
|
||||
@ -81,4 +89,39 @@ class ReserveReminderEntity(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class CalendarConfig(
|
||||
@SerializedName("notice")
|
||||
private val _notice: Boolean? = null,
|
||||
@SerializedName("title")
|
||||
private val _title: String? = null,
|
||||
@SerializedName("time_start")
|
||||
private val _timeStart: Long? = null,
|
||||
@SerializedName("time_end")
|
||||
private val _timeEnd: Long? = null,
|
||||
@SerializedName("advance_seconds")
|
||||
private val _advanceSeconds: Long? = null,
|
||||
@SerializedName("remark")
|
||||
private val _remark: String? = null
|
||||
) : Parcelable {
|
||||
|
||||
val notice: Boolean
|
||||
get() = _notice ?: false
|
||||
|
||||
val title: String
|
||||
get() = _title ?: ""
|
||||
|
||||
val timeStart: Long
|
||||
get() = _timeStart ?: 0L
|
||||
|
||||
val timeEnd: Long
|
||||
get() = _timeEnd ?: 0L
|
||||
|
||||
val advanceSeconds: Long
|
||||
get() = _advanceSeconds ?: 0L
|
||||
|
||||
val remark: String
|
||||
get() = _remark ?: ""
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.gh.gamecenter.entity
|
||||
import android.os.Parcelable
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.personalhome.home.UserHistoryViewModel
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@ -19,11 +20,20 @@ data class SearchSubjectEntity(
|
||||
val adIconActive: Boolean = false,
|
||||
// 本地字段,标记是否为微信小游戏CPM专题
|
||||
var isWGameSubjectCPM: Boolean = false,
|
||||
val type: String = ""
|
||||
// 本地字段,标记是否为DSP专题
|
||||
var isDspSubject: Boolean = false,
|
||||
val type: String = "",
|
||||
|
||||
@SerializedName("column_type")
|
||||
val columnType: String = "", // DSP 专题类型 (DSP专题类型(apk:下载应用、mini_game:微信小程序/小游戏)
|
||||
@SerializedName("show_download") // 下载/秒玩按钮(true:显示、false:不显示)(专题类型为apk,则为下载按钮;专题类型为mini_game,则为秒完按钮)
|
||||
val showDownload: Boolean = false,
|
||||
val size: Int = -1, // 专题游戏数量
|
||||
) : Parcelable {
|
||||
|
||||
companion object {
|
||||
const val TYPE_WECHAT_GAME_CPM_COLUMN = "wechat_game_cpm_column"
|
||||
const val TYPE_DSP_GAME_COLUMN = "dsp_game_column"
|
||||
}
|
||||
|
||||
fun getFilterGame() = RegionSettingHelper.filterGame(games)
|
||||
|
||||
@ -117,7 +117,12 @@ data class SubjectEntity(
|
||||
@SerializedName("show_index_icon_subscript")
|
||||
val showIndexIconSubscript: Boolean = false,
|
||||
@SerializedName("welfare_info")
|
||||
val welfareInfo: WelfareInfo? = null
|
||||
val welfareInfo: WelfareInfo? = null,
|
||||
|
||||
@SerializedName("column_type")
|
||||
private val _columnType: String? = null,
|
||||
@SerializedName("size")
|
||||
private val _size: Size? = null
|
||||
) : Parcelable {
|
||||
|
||||
@IgnoredOnParcel
|
||||
@ -130,12 +135,13 @@ data class SubjectEntity(
|
||||
@IgnoredOnParcel
|
||||
private var filteredData: MutableList<GameEntity>? = null
|
||||
|
||||
val subjectType: SubjectData.SubjectType get() = when {
|
||||
isQQColumn -> SubjectData.SubjectType.QQ_GAME
|
||||
isWechatColumnCPM -> SubjectData.SubjectType.WECHAT_GAME_CPM
|
||||
isWechatColumn -> SubjectData.SubjectType.WECHAT_GAME
|
||||
else -> SubjectData.SubjectType.NORMAL
|
||||
}
|
||||
val subjectType: SubjectData.SubjectType
|
||||
get() = when {
|
||||
isQQColumn -> SubjectData.SubjectType.QQ_GAME
|
||||
isWechatColumnCPM -> SubjectData.SubjectType.WECHAT_GAME_CPM
|
||||
isWechatColumn -> SubjectData.SubjectType.WECHAT_GAME
|
||||
else -> SubjectData.SubjectType.NORMAL
|
||||
}
|
||||
|
||||
val isMiniGame: Boolean get() = isQQColumn || isWechatColumn
|
||||
|
||||
@ -148,4 +154,28 @@ data class SubjectEntity(
|
||||
|
||||
val list: Int
|
||||
get() = max(min(_list ?: 0, data?.size ?: 0), 1)
|
||||
|
||||
val columnType: String
|
||||
get() = _columnType ?: ""
|
||||
|
||||
val size: Size
|
||||
get() = _size ?: Size()
|
||||
|
||||
var isDspSubject: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val SUBJECT_TAG_UPDATE = "update" // 更新时间
|
||||
const val SUBJECT_TAG_TYPE = "type" // 游戏标签
|
||||
const val SUBJECT_TAG_TEST = "test" // 开测时间
|
||||
const val SUBJECT_TAG_SELLING_POINT = "selling_points&type" // 卖点文案+游戏标签
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class Size(
|
||||
@SerializedName("index")
|
||||
private val _index: Int? = null
|
||||
) : Parcelable {
|
||||
val index: Int
|
||||
get() = _index ?: 0
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,6 @@ import com.gh.gamecenter.eventbus.EBUserFollow
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.forum.home.ForumScrollCalculatorHelper
|
||||
import com.gh.gamecenter.video.detail.CustomManager
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
@ -125,10 +124,6 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
override fun onFragmentPause() {
|
||||
super.onFragmentPause()
|
||||
pauseVideo()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mScrollCalculatorHelper?.currentPlayer?.release()
|
||||
}
|
||||
|
||||
@ -263,9 +258,7 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
mBaseHandler.postDelayed({
|
||||
tryCatchInRelease {
|
||||
if (position != 0L) {
|
||||
if (currentPlayer?.currentState == GSYVideoView.CURRENT_STATE_PAUSE) {
|
||||
currentPlayer?.startPlayLogic(true)
|
||||
}
|
||||
currentPlayer?.startPlayLogic(true)
|
||||
} else {
|
||||
currentPlayer?.release()
|
||||
}
|
||||
|
||||
@ -160,12 +160,15 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
}
|
||||
|
||||
//监控播放错误
|
||||
// override fun onError(what: Int, extra: Int) {
|
||||
// super.onError(what, extra)
|
||||
override fun onError(what: Int, extra: Int) {
|
||||
super.onError(what, extra)
|
||||
// Utils.toast(context, "网络错误,视频播放失败")
|
||||
// setViewShowState(mStartButton, View.INVISIBLE)
|
||||
//// errorContainer.visibility = View.VISIBLE
|
||||
// }
|
||||
// errorContainer.visibility = View.VISIBLE
|
||||
|
||||
// 部分设备由于MediaCodec实例达到上限导致 CodecException: Error 0xfffffff4,在此处尝试释放所有视频
|
||||
CustomManager.clearAllVideo()
|
||||
}
|
||||
|
||||
override fun releaseVideos() {
|
||||
CustomManager.releaseAllVideos(getKey())
|
||||
|
||||
@ -37,9 +37,9 @@ class UserSearchListFragment : LazyListFragment<FollowersOrFansEntity, UserSearc
|
||||
SensorsBridge.trackUserSearchResultClick(
|
||||
GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
mListViewModel.sourceEntrance,
|
||||
mSearchKey,
|
||||
SearchActivity.toTrackSearchType(mSearchType),
|
||||
mListViewModel.sourceEntrance,
|
||||
userId,
|
||||
position
|
||||
)
|
||||
|
||||
@ -15,10 +15,10 @@ class GameHorizontalSimpleItemViewHolder(val binding: GameHorizontalSimpleItemBi
|
||||
view.text = name
|
||||
view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
view.viewTreeObserver.removeOnGlobalLayoutListener(this);
|
||||
val newText = autoSplitText(view);
|
||||
view.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
val newText = autoSplitText(view)
|
||||
if (!TextUtils.isEmpty(newText)) {
|
||||
view.text = newText;
|
||||
view.text = newText
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -137,7 +137,6 @@ class GameHorizontalSlideAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// notifyDataSetChanged 会出现页面抖动情况
|
||||
fun checkResetData(subjectEntity: SubjectEntity) {
|
||||
var dataIds = ""
|
||||
|
||||
@ -3,10 +3,10 @@ package com.gh.gamecenter.game.vertical
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Space
|
||||
@ -17,11 +17,12 @@ import androidx.core.content.ContextCompat
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.airbnb.lottie.LottieDrawable
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.feature.view.GameIconView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.databinding.LayoutGameItemSellingPointBinding
|
||||
import com.gh.gamecenter.common.utils.setDrawableEnd
|
||||
import com.gh.gamecenter.common.view.GameTagContainerView
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.feature.view.GameIconView
|
||||
import splitties.dimensions.dip
|
||||
import splitties.views.backgroundColor
|
||||
import splitties.views.dsl.constraintlayout.*
|
||||
@ -63,6 +64,7 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
var gamePlayCountTv: TextView
|
||||
|
||||
var mGameDesSpace: Space
|
||||
var sellingPointsBinding: LayoutGameItemSellingPointBinding
|
||||
|
||||
override val root: ConstraintLayout = constraintLayout {
|
||||
padding = dip(16)
|
||||
@ -84,6 +86,7 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
gameTagContainer = GameTagContainerView(ctx).apply { id = R.id.label_list }
|
||||
mGameDesSpace = space { }.apply { id = R.id.gameDesSpace }
|
||||
recommendConstraintLayout = initRecommendConstraintLayout()
|
||||
sellingPointsBinding = LayoutGameItemSellingPointBinding.inflate(LayoutInflater.from(context))
|
||||
|
||||
add(iconIv, lParams(dip(64), dip(64)) {
|
||||
topOfParent()
|
||||
@ -142,6 +145,12 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
endToEndOf(mGameDesSpace)
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
})
|
||||
add(sellingPointsBinding.root, lParams(0, wrapContent) {
|
||||
topToBottomOf(mGameDesSpace)
|
||||
bottomToBottomOf(iconIv)
|
||||
startToEndOf(gamePlayCountTv)
|
||||
endToEndOf(mGameDesSpace)
|
||||
})
|
||||
add(gamePlayCountTv, lParams(wrapContent, wrapContent) {
|
||||
topToBottomOf(mGameDesSpace)
|
||||
bottomToBottomOf(iconIv)
|
||||
@ -197,7 +206,8 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
startPadding = dip(2)
|
||||
endPadding = dip(2)
|
||||
ellipsize = TextUtils.TruncateAt.END
|
||||
background = ContextCompat.getDrawable(context, com.gh.gamecenter.feature.R.drawable.bg_advance_download_game_subtitle)
|
||||
background =
|
||||
ContextCompat.getDrawable(context, com.gh.gamecenter.feature.R.drawable.bg_advance_download_game_subtitle)
|
||||
setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_secondary))
|
||||
visibility = View.GONE
|
||||
}
|
||||
@ -305,7 +315,12 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
gravity = Gravity.CENTER
|
||||
text = "展开"
|
||||
setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.white))
|
||||
setDrawableEnd(AppCompatResources.getDrawable(context, com.gh.gamecenter.feature.R.drawable.ic_jump_universal))
|
||||
setDrawableEnd(
|
||||
AppCompatResources.getDrawable(
|
||||
context,
|
||||
com.gh.gamecenter.feature.R.drawable.ic_jump_universal
|
||||
)
|
||||
)
|
||||
compoundDrawablePadding = dip(2)
|
||||
visibility = View.GONE
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ class GameVerticalAdapter(
|
||||
false
|
||||
)
|
||||
BindingAdapters.setGame(iconIv, gameEntity)
|
||||
BindingAdapters.setGameTags(gameTagContainer, gameEntity)
|
||||
BindingAdapters.setGameTags(gameTagContainer, gameEntity, subjectData?.tag ?: "")
|
||||
GameItemViewHolder.initServerType(gameNameTv, serverTypeTv, gameEntity)
|
||||
gameDesTv.text = gameEntity.decoratedDes
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(
|
||||
@ -225,10 +225,10 @@ class GameVerticalAdapter(
|
||||
subjectData?.briefStyle
|
||||
)
|
||||
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
context, downloadTv, gameEntity, position,
|
||||
adapter, entrance, location = location, traceEvent = gameEntity.exposureEvent
|
||||
)
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
context, downloadTv, gameEntity, position,
|
||||
adapter, entrance, location = location, traceEvent = gameEntity.exposureEvent
|
||||
)
|
||||
|
||||
root.setPadding(paddingStart, 8F.dip2px(), paddingEnd, 8F.dip2px())
|
||||
}
|
||||
|
||||
@ -610,7 +610,7 @@ open class GameCollectionDetailAdapter(
|
||||
gameIconView.displayGameIcon(gameEntity)
|
||||
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
|
||||
BindingAdapters.setGameName(gameName, gameEntity, false)
|
||||
BindingAdapters.setGameTags(labelList, gameEntity)
|
||||
BindingAdapters.setGameTags(labelList, gameEntity, "")
|
||||
gameRating.setDrawableStart(
|
||||
if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable(mContext) else null
|
||||
)
|
||||
|
||||
@ -45,7 +45,6 @@ import com.google.gson.JsonArray
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.halo.assistant.accelerator.repository.AccelerationRepository
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
@ -128,12 +127,16 @@ class GameDetailViewModel(
|
||||
var isSkipOnPageSelected = false // 是否触发论坛/专区Tab跳转
|
||||
|
||||
var defaultCoverEntity: CoverEntity? = null
|
||||
var coverTabSequence = 1 // 用于埋点,详情视频/图集tab 当前选中tab的序号,从1开始
|
||||
var coverTabName = "" // 用于埋点,详情视频/图集tab 详情视频/图集tab 当前选中tab的tab名称
|
||||
|
||||
var isGameInstalled = false
|
||||
private var isGameUpdatable = false
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
|
||||
private var userRelatedInfoReceivedCallback: (() -> Unit)? = null
|
||||
|
||||
init {
|
||||
loadData()
|
||||
}
|
||||
@ -190,13 +193,6 @@ class GameDetailViewModel(
|
||||
game = response
|
||||
gameLiveData.postValue(Resource.success(game))
|
||||
loadGameDetailData()
|
||||
if (game?.canSpeed == true) {
|
||||
// 如果当前游戏支持加速,则刷新vip状态
|
||||
val userId = UserManager.getInstance().userId
|
||||
if (userId.isNotBlank()) {
|
||||
UserRepository.getInstance().refreshVipStatus(userId, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -769,8 +765,14 @@ class GameDetailViewModel(
|
||||
.subscribe({
|
||||
unifiedUserTrendEntity = it
|
||||
emitter.onSuccess(Result.success(it))
|
||||
|
||||
userRelatedInfoReceivedCallback?.invoke()
|
||||
userRelatedInfoReceivedCallback = null
|
||||
}, {
|
||||
emitter.onSuccess(Result.failure(it))
|
||||
|
||||
userRelatedInfoReceivedCallback?.invoke()
|
||||
userRelatedInfoReceivedCallback = null
|
||||
})
|
||||
}
|
||||
|
||||
@ -800,9 +802,21 @@ class GameDetailViewModel(
|
||||
tabSelectedLiveData.postValue(Event(LinkEntity(type = type)))
|
||||
}
|
||||
|
||||
fun performContentCardClicked(contentCardType: String): Boolean {
|
||||
/**
|
||||
* 发送内容卡片点击事件
|
||||
* @param contentCardType 内容卡片类型
|
||||
* @param waitForUserRelatedResult 是否等待用户相关信息请求结果
|
||||
* @return 是否成功触发点击事件
|
||||
*/
|
||||
fun performContentCardClicked(contentCardType: String, waitForUserRelatedResult: Boolean = false): Boolean {
|
||||
return if (contentCardList?.any { it.link.type == contentCardType } == true) {
|
||||
contentCardClickedLiveData.postValue(Event(contentCardType))
|
||||
if (waitForUserRelatedResult && CheckLoginUtils.isLogin()) {
|
||||
userRelatedInfoReceivedCallback = {
|
||||
contentCardClickedLiveData.postValue(Event(contentCardType))
|
||||
}
|
||||
} else {
|
||||
contentCardClickedLiveData.postValue(Event(contentCardType))
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -812,7 +826,7 @@ class GameDetailViewModel(
|
||||
fun performScrollToServer(): Boolean {
|
||||
// 如果该游戏的【内容卡片】在详情中显示类型为【游戏开服】的卡片时,触发点击类型为【游戏开服】的内容卡片进入开服日历表页面
|
||||
// 如果该游戏的【内容卡片】在详情中没有【游戏开服】的卡片时,定位到游戏详情页-详情tab-【游戏开服】组件
|
||||
return if (performContentCardClicked(ContentCardEntity.TYPE_SERVER)) {
|
||||
return if (performContentCardClicked(ContentCardEntity.TYPE_SERVER, true)) {
|
||||
true
|
||||
} else if (detailDataListLiveData.value?.any { it.linkServer != null } == true) {
|
||||
scrollToListPositionLiveData.postValue(Event(LinkEntity(type = GameDetailData.TYPE_SERVER)))
|
||||
@ -962,7 +976,7 @@ class GameDetailViewModel(
|
||||
unifiedUserTrendEntity.game?.let {
|
||||
if (it.isEmpty()) return@let
|
||||
for (game in it) {
|
||||
meLiveData.postValue(game.me)
|
||||
meLiveData.value = game.me
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@ import com.gh.gamecenter.common.base.fragment.BaseLazyFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.json.json
|
||||
import com.gh.gamecenter.common.mvvm.Status
|
||||
@ -757,6 +758,7 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
|
||||
bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_ID, tabEntity.link?.link)
|
||||
bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_NAME, tabEntity.link?.text)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SHOW_FLOATING_WINDOW, false)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SHOW_PULL_DOWN_PUSH, false)
|
||||
}
|
||||
}
|
||||
fragment?.let {
|
||||
@ -765,7 +767,7 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
viewPager.setRestoredCurItem(destinationTab)
|
||||
currentVpPosition = destinationTab
|
||||
onPageSelected(destinationTab)
|
||||
viewPager.offscreenPageLimit = fragmentsList.size
|
||||
viewPager.adapter =
|
||||
FragmentAdapter(childFragmentManager, fragmentsList, tabEntityList.map { it.name })
|
||||
@ -1110,6 +1112,13 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
|
||||
return true
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(reuse: EBReuse) {
|
||||
if ("download" == reuse.type) {
|
||||
downloadBinding.detailProgressbar.performClick()
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus) {
|
||||
updateDownloadCountHint(packageViewModel.filterSameUpdateLiveData.value)
|
||||
@ -1440,6 +1449,7 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
|
||||
* 3. 当前游戏 APK 不为 1 个
|
||||
* 4. 当前游戏类型不为畅玩
|
||||
* 5. 当前游戏不是双下载时使用本地下载进行下载
|
||||
* 6. 当前游戏支持加速
|
||||
*/
|
||||
private fun isSpecialDownloadDialogAvailable(downloadEntity: DownloadEntity? = null): Boolean {
|
||||
if (Config.getNewApiSettingsEntity()?.install?.questionTip?.linkEntity == null) return false
|
||||
@ -1448,7 +1458,7 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
|
||||
if (downloadEntity?.asVGame() == true) return false
|
||||
if (downloadEntity?.isSimulatorGame() == true) return false
|
||||
if (downloadEntity?.isLocalDownloadInDualDownloadMode() == true) return false
|
||||
|
||||
if (gameEntity?.canSpeed == true) return false
|
||||
return true
|
||||
}
|
||||
|
||||
@ -1549,9 +1559,12 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
|
||||
downloadMenuIcon?.setImageResource(R.drawable.toolbar_download)
|
||||
if (::viewModel.isInitialized) {
|
||||
updateConcernMenuIcon(viewModel.meLiveData.value?.isGameConcerned ?: false)
|
||||
detailViewHolder.downloadPb.buttonStyle = detailViewHolder.downloadPb.buttonStyle
|
||||
if (detailViewHolder.downloadTips.visibility == View.VISIBLE) {
|
||||
detailViewHolder.downloadTips.setDownloadTipsAnimation(detailViewHolder.downloadTips.isAnimating)
|
||||
if (gameEntity != null) {
|
||||
val viewHolder = detailViewHolder
|
||||
viewHolder.downloadPb.buttonStyle = detailViewHolder.downloadPb.buttonStyle
|
||||
if (viewHolder.downloadTips.isVisible) {
|
||||
viewHolder.downloadTips.setDownloadTipsAnimation(detailViewHolder.downloadTips.isAnimating)
|
||||
}
|
||||
}
|
||||
}
|
||||
controlReserveBtn()
|
||||
|
||||
@ -3,8 +3,11 @@ package com.gh.gamecenter.gamedetail
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.gh.gamecenter.common.constant.Constants.SP_ACCELERATOR_MEMBERSHIP_EXPIRED
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.core.provider.IAcceleratorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.feature.entity.BaseEntity
|
||||
import com.gh.gamecenter.feature.entity.TrialEntity
|
||||
import com.gh.gamecenter.feature.entity.VipEntity
|
||||
@ -13,6 +16,7 @@ import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.login.user.UserRepository
|
||||
import com.halo.assistant.accelerator.AccelerationUseCase
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
import com.therouter.TheRouter
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
|
||||
class StartingAcceleratorViewModel : ViewModel() {
|
||||
@ -21,13 +25,14 @@ class StartingAcceleratorViewModel : ViewModel() {
|
||||
|
||||
val useCase = AccelerationUseCase()
|
||||
|
||||
private val _restartingAcceleratorAction = MutableLiveData<Event<Boolean>>()
|
||||
val restartingAcceleratorAction: LiveData<Event<Boolean>> = _restartingAcceleratorAction
|
||||
private val _restartingAcceleratorAction = MutableLiveData<Event<Unit>>()
|
||||
val restartingAcceleratorAction: LiveData<Event<Unit>> = _restartingAcceleratorAction
|
||||
fun loadAcceleratorToken() {
|
||||
val userId = UserManager.getInstance().userId
|
||||
if (userId.isNotBlank()) {
|
||||
UserRepository.getInstance().setAcceleratorToken(userId) {
|
||||
_restartingAcceleratorAction.value = Event(it)
|
||||
// 这里就算setToken失败,也要调用启动加速,失败会走正常的日志上报
|
||||
_restartingAcceleratorAction.value = Event(Unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,16 +46,15 @@ class StartingAcceleratorViewModel : ViewModel() {
|
||||
.subscribe(object : BiResponse<BaseEntity<TrialEntity>>() {
|
||||
override fun onSuccess(data: BaseEntity<TrialEntity>) {
|
||||
if (data.data?.result == true) {
|
||||
// 刷新vip状态
|
||||
// 这里先刷新内存数据
|
||||
AcceleratorDataHolder.instance.setVipEntity(
|
||||
VipEntity(
|
||||
_vipStatus = true,
|
||||
_isNewUser = false,
|
||||
_isTryVip = true
|
||||
)
|
||||
// 试用三小时下单成功
|
||||
val permissionEntity = VipEntity(
|
||||
_vipStatus = true,
|
||||
_isNewUser = false,
|
||||
_isTryVip = true,
|
||||
)
|
||||
|
||||
AcceleratorDataHolder.instance.setVipEntity(permissionEntity)
|
||||
TheRouter.get(IAcceleratorProvider::class.java)?.loadQyUserPermissionData()
|
||||
SPUtils.setBoolean(SP_ACCELERATOR_MEMBERSHIP_EXPIRED, false)
|
||||
_rechargeTrailResult.value = Event(true)
|
||||
} else {
|
||||
_rechargeTrailResult.value = Event(false)
|
||||
@ -64,6 +68,33 @@ class StartingAcceleratorViewModel : ViewModel() {
|
||||
}).let(compositeDisposable::add)
|
||||
}
|
||||
|
||||
private val _vipEntity = MutableLiveData<Event<VipEntity?>>()
|
||||
val vipEntity: LiveData<Event<VipEntity?>> = _vipEntity
|
||||
fun loadVipStatus() {
|
||||
val enableRefreshVipStatus = AcceleratorDataHolder.instance.enableRefresh
|
||||
if (enableRefreshVipStatus) {
|
||||
useCase.loadVipStatus()
|
||||
.compose(singleToMain())
|
||||
.subscribe(object : BiResponse<BaseEntity<VipEntity>>() {
|
||||
override fun onSuccess(data: BaseEntity<VipEntity>) {
|
||||
val vip = data.data
|
||||
if (vip != null) {
|
||||
AcceleratorDataHolder.instance.setVipEntity(vip)
|
||||
}
|
||||
_vipEntity.value = Event(vip)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
_vipEntity.value = Event(null)
|
||||
}
|
||||
}).let(compositeDisposable::add)
|
||||
} else {
|
||||
_vipEntity.value = Event(AcceleratorDataHolder.instance.vipEntity)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
compositeDisposable.clear()
|
||||
|
||||
@ -15,7 +15,6 @@ import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.DetailDownloadItemBinding
|
||||
import com.gh.gamecenter.feature.entity.AcctGameInfo
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.VipEntity
|
||||
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorClient
|
||||
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorValidator
|
||||
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment
|
||||
@ -56,6 +55,8 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
|
||||
private var hasAnyAcctRecord = false
|
||||
|
||||
private var showDualDownloadButton: Boolean = false
|
||||
|
||||
private val accelerationListener = object : OnAccelerateListener {
|
||||
override fun onStateChanged(state: AccelerateState) {
|
||||
when (state) {
|
||||
@ -77,7 +78,7 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
}
|
||||
|
||||
private val onDataHolderListener = object : AcceleratorDataHolder.OnDataHolderListener {
|
||||
override fun onVipStateChanged(vip: VipEntity) {
|
||||
override fun onVipStateChanged() {
|
||||
showFreeTag()
|
||||
}
|
||||
}
|
||||
@ -132,13 +133,17 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
|
||||
val isCurrentGameAccelerating = AcceleratorDataHolder.instance.isCurrentGameAccelerating(game.id)
|
||||
|
||||
when {
|
||||
isCurrentGameAccelerating -> {// 如果当前游戏正处于加速状态,则需要隐藏当前下载按钮
|
||||
binding.detailProgressbar.goneIf(true)
|
||||
}
|
||||
if (!showDualDownloadButton) {
|
||||
when {
|
||||
isCurrentGameAccelerating -> {// 如果当前游戏正处于加速状态,则需要隐藏当前下载按钮
|
||||
binding.detailProgressbar.goneIf(true)
|
||||
}
|
||||
|
||||
binding.detailProgressbar.text == "更新" -> { // 游戏没有处于加速状态,如果 下载按钮为 “更新” 状态,则需要显示出来
|
||||
binding.detailProgressbar.goneIf(false)
|
||||
binding.detailProgressbar.text == "更新" -> { // 游戏没有处于加速状态,如果 下载按钮为 “更新” 状态,则需要显示出来
|
||||
binding.detailProgressbar.setBackgroundResource(com.gh.gamecenter.common.R.drawable.bg_common_button_light_fill_blue)
|
||||
binding.detailProgressbar.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
|
||||
binding.detailProgressbar.goneIf(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,14 +158,13 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
} ?: R.string.network_acceleration.toResString()
|
||||
}
|
||||
|
||||
fun checkIfShowSpeedUi(show: Boolean) {
|
||||
fun checkIfShowSpeedUi(show: Boolean, showDualDownloadButton: Boolean) {
|
||||
this.showDualDownloadButton = showDualDownloadButton
|
||||
if (!isInit) {
|
||||
return
|
||||
}
|
||||
showSpeedUi = show
|
||||
binding.clSpeedContainer.goneIf(!showSpeedUi) {
|
||||
binding.detailProgressbar.setBackgroundResource(com.gh.gamecenter.common.R.drawable.bg_common_button_light_fill_blue)
|
||||
binding.detailProgressbar.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
|
||||
// 是否需要展示弹窗
|
||||
showGuideLayerIfNeed()
|
||||
updateSpeedUi()
|
||||
@ -224,7 +228,7 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
game.id,
|
||||
game.name ?: ""
|
||||
)
|
||||
guideView?.show(binding.clSpeedContainer, context, uiListener::onStartAccelerator)
|
||||
guideView?.show(binding.clSpeed, context, uiListener::onStartAccelerator)
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,6 +248,7 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
if (isInvalidClick()) {
|
||||
return
|
||||
}
|
||||
|
||||
val lastAcctGameInfo = last
|
||||
|
||||
val memberType = AcceleratorDataHolder.instance.memberType
|
||||
@ -278,6 +283,7 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
doStartAccelerating(context, game, gameInfo)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun showZoneList(context: Context, game: GameEntity) {
|
||||
@ -290,13 +296,14 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
SOURCE_ENTRANCE_GAME_DETAIL
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private var clickTime = 0L
|
||||
|
||||
private fun doStartAccelerating(context: Context, game: GameEntity, zoneInfo: AcctGameInfo.ZoneInfo) {
|
||||
|
||||
val request = AcceleratorValidator.Request(isVip, isNewUser, game, SOURCE_ENTRANCE_GAME_DETAIL)
|
||||
val request = AcceleratorValidator.Request(game, SOURCE_ENTRANCE_GAME_DETAIL)
|
||||
AcceleratorClient.newInstance()
|
||||
.execute(context, request, object : AcceleratorValidator.ValidateListener {
|
||||
override fun finished(context: Context) {
|
||||
|
||||
@ -22,7 +22,7 @@ class AcceleratorClient(
|
||||
AcceleratorLoginInterceptor(),
|
||||
AcceleratorPackageCheckInterceptor(),
|
||||
AcceleratorRealNameInterceptor(),
|
||||
AcceleratorVipInterceptor(),
|
||||
AcceleratorPermissionGuideInterceptor(),
|
||||
AcceleratorStateInterceptor()
|
||||
)
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.gh.gamecenter.gamedetail.accelerator.chain
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.common.dialog.AcceleratorPermissionGuideDialogFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
|
||||
class AcceleratorPermissionGuideInterceptor : AcceleratorValidator.Interceptor {
|
||||
override fun intercept(
|
||||
context: Context,
|
||||
chain: AcceleratorValidator.Chain,
|
||||
listener: AcceleratorValidator.ValidateListener?
|
||||
) {
|
||||
val hasShow = SPUtils.getBoolean(Constants.SP_ACCELERATOR_PERMISSION_GUIDE_SHOW)
|
||||
val request = chain.request
|
||||
if (hasShow) {
|
||||
chain.proceed(context, request, listener)
|
||||
} else {
|
||||
AcceleratorPermissionGuideDialogFragment.show(context) {
|
||||
if (chain.isValidContext(context)) {
|
||||
chain.proceed(context, request, listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,11 +31,9 @@ class AcceleratorValidator {
|
||||
|
||||
@Parcelize
|
||||
data class Request(
|
||||
val isVip: Boolean,
|
||||
val isNewUser: Boolean,
|
||||
val game: GameEntity,
|
||||
val sourceEntrance: String
|
||||
):Parcelable
|
||||
) : Parcelable
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,14 @@
|
||||
package com.gh.gamecenter.gamedetail.accelerator.chain
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.common.dialog.AccelerateExpirationDialogFragment
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.toResString
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment
|
||||
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_ENABLE_VIP
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
|
||||
class AcceleratorVipInterceptor : AcceleratorValidator.Interceptor {
|
||||
|
||||
@ -12,20 +18,24 @@ class AcceleratorVipInterceptor : AcceleratorValidator.Interceptor {
|
||||
listener: AcceleratorValidator.ValidateListener?
|
||||
) {
|
||||
val request = chain.request
|
||||
val isVip = request.isVip
|
||||
val isNewUser = request.isNewUser
|
||||
if (isVip || isNewUser) {
|
||||
val vip = AcceleratorDataHolder.instance.vipEntity
|
||||
if (vip?.vipStatus == true || vip?.isNewUser == true) {
|
||||
chain.proceed(context, request, listener)
|
||||
} else {
|
||||
val game = request.game
|
||||
AcceleratorDialogFragment.show(
|
||||
SPEED_ENABLE_VIP,
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
request.sourceEntrance,
|
||||
context
|
||||
)
|
||||
val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.TimeRunsOut(request.sourceEntrance)
|
||||
AccelerateExpirationDialogFragment.checkDialogShown(context, reminder) {
|
||||
if (!it) {
|
||||
val game = request.game
|
||||
AcceleratorDialogFragment.show(
|
||||
SPEED_ENABLE_VIP,
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
request.sourceEntrance,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,9 +86,7 @@ class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcc
|
||||
sourceEntrance
|
||||
)
|
||||
|
||||
val isVip = acceleratorDataHolder.isVip
|
||||
val isNewUser = acceleratorDataHolder.isNewUser
|
||||
val request = AcceleratorValidator.Request(isVip, isNewUser, game, sourceEntrance)
|
||||
val request = AcceleratorValidator.Request(game, sourceEntrance)
|
||||
AcceleratorClient.newInstance()
|
||||
.execute(it, request, object : AcceleratorValidator.ValidateListener {
|
||||
override fun finished(context: Context) {
|
||||
|
||||
@ -10,30 +10,35 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.gh.common.dialog.AccelerateExpirationDialogFragment
|
||||
import com.gh.common.util.PackageLauncher
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.core.callback.AccelerateState
|
||||
import com.gh.gamecenter.core.callback.OnAccelerateListener
|
||||
import com.gh.gamecenter.core.provider.IAcceleratorProvider
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.databinding.DialogFragmentStartingAcceleratorBinding
|
||||
import com.gh.gamecenter.feature.entity.AcctGameInfo
|
||||
import com.gh.gamecenter.feature.entity.AcctRecord
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.VipEntity
|
||||
import com.gh.gamecenter.gamedetail.StartingAcceleratorViewModel
|
||||
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.DISTRICT_SERVER_HAVA
|
||||
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.SOURCE_ENTRANCE_GAME_DETAIL
|
||||
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_ENABLE_VIP
|
||||
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_START_FAILURE
|
||||
import com.gh.gamecenter.livedata.EventObserver
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.login.user.UserRepository
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
import com.therouter.TheRouter
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import java.util.*
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
|
||||
class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
@ -91,14 +96,30 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
// 加速失败,上传奇游加速器log
|
||||
unloadAcceleratorErrorLog(game)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 由于每次加速前,都会检测加速会员权限,所以一般不会出现这种场景,这里只是为了兼容特殊情况,弹出相应提示
|
||||
if (state.isPermissionExpired) {
|
||||
// 加速会员过期 ,如果之前没有弹出过耗尽提醒,则弹出提示
|
||||
val reminder =
|
||||
AccelerateExpirationDialogFragment.ExpirationReminder.TimeRunsOut(sourceEntrance)
|
||||
AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
|
||||
if (!it) {
|
||||
// 之前弹出过耗尽提醒弹窗,这里直接展示加速失败
|
||||
AcceleratorDialogFragment.show(
|
||||
SPEED_START_FAILURE,
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
sourceEntrance,
|
||||
requireContext()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (state.isPermissionExpired) {
|
||||
// 加速会员过期,刷新本地vip状态
|
||||
val userId = UserManager.getInstance().userId
|
||||
UserRepository.getInstance().refreshVipStatus(userId, true)
|
||||
// 加速失败,上传奇游加速器log
|
||||
unloadAcceleratorErrorLog(game)
|
||||
iAcceleratorProvider?.loadQyUserPermissionData()
|
||||
// 加速失败,上传奇游加速器log
|
||||
unloadAcceleratorErrorLog(game)
|
||||
}
|
||||
}
|
||||
|
||||
dismissAllowingStateLoss()
|
||||
@ -178,14 +199,6 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
|
||||
binding.tvProgress.text = getString(R.string.accelerating_with_progress, "0")
|
||||
iAcceleratorProvider?.bindAccRelatedListener("", accelerationListener)
|
||||
val isVip = acceleratorDataHolder.isVip
|
||||
val isNewUser = acceleratorDataHolder.isNewUser
|
||||
if (isNewUser && !isVip) {
|
||||
// 新用户,并且还不是vip
|
||||
viewModel.rechargeTrial()
|
||||
} else {
|
||||
startGameAccelerate()
|
||||
}
|
||||
|
||||
viewModel.restartingAcceleratorAction.observe(viewLifecycleOwner, EventObserver {
|
||||
startGameAccelerate()
|
||||
@ -208,6 +221,162 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
viewModel.vipEntity.observe(viewLifecycleOwner, EventObserver {
|
||||
if (it == null) {
|
||||
// 获取用户vip数据失败,直接弹出加速失败
|
||||
AcceleratorDialogFragment.show(
|
||||
SPEED_START_FAILURE,
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
sourceEntrance,
|
||||
requireContext()
|
||||
)
|
||||
dismissAllowingStateLoss()
|
||||
trackNetworkAccelerationStartupResult("失败(获取vip数据失败)")
|
||||
} else {
|
||||
// 获取用户vip数据成功
|
||||
canUserEnableAcceleration(it) {
|
||||
startGameAccelerate()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.loadVipStatus()
|
||||
}
|
||||
|
||||
private fun canUserEnableAcceleration(vipEntity: VipEntity, callback: () -> Unit) {
|
||||
if (vipEntity.isNewUser) {
|
||||
// 如果是新用户,下单试用套餐
|
||||
viewModel.rechargeTrial()
|
||||
return
|
||||
}
|
||||
|
||||
val serviceTime = vipEntity.timestamp
|
||||
val userRemainingDays = calculateCalendarDaysDiff(vipEntity.vipExpireTime, serviceTime)
|
||||
|
||||
//如果是试用会员 或者是 包月会员,并且还没有临期: 直接启动。
|
||||
if (vipEntity.isTryVip || (vipEntity.vipStatus && userRemainingDays > 3)) {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
|
||||
// 包月会员不足三天
|
||||
if (vipEntity.isMonthVip && userRemainingDays in 1..3) {
|
||||
val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.UserExpired(
|
||||
userRemainingDays, game.id, game.name ?: "", game.getUniquePackageName() ?: "", sourceEntrance
|
||||
)
|
||||
AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
|
||||
if (it) {
|
||||
dismissAllowingStateLoss()
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 检查时长套餐是否快要耗尽
|
||||
val durationRemainingMinute = vipEntity.durationExpiredTime
|
||||
if (vipEntity.isDurationVip && durationRemainingMinute < 0) {
|
||||
// 用户是时长会员,但是剩余时长为 -1 ,说明后端拉取奇游剩余时长失败,此时无法判断用户的时长会员是否到期,直接开启加速
|
||||
callback()
|
||||
return
|
||||
}
|
||||
|
||||
// 用户是时长会员,并且将要消耗完毕
|
||||
val durationRemainingHours = ceil(durationRemainingMinute / 60.0).toLong()
|
||||
if (vipEntity.isDurationVip && durationRemainingHours in 1..3) {
|
||||
val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.InsufficientDuration(
|
||||
durationRemainingHours, game.id, game.name ?: "", game.getUniquePackageName() ?: "", sourceEntrance
|
||||
)
|
||||
AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
|
||||
if (it) {
|
||||
dismissAllowingStateLoss()
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 检查时长套餐是否快要过期
|
||||
val durationRemainingDays = calculateCalendarDaysDiff(vipEntity.durationVipExpiredTime, serviceTime)
|
||||
if (vipEntity.isDurationVip && durationRemainingDays in 1..3) {
|
||||
val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.DurationExpired(
|
||||
durationRemainingDays, game.id, game.name ?: "", game.getUniquePackageName() ?: "", sourceEntrance
|
||||
)
|
||||
AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
|
||||
if (it) {
|
||||
dismissAllowingStateLoss()
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 检查会员是否到期
|
||||
val hasShow = SPUtils.getBoolean(Constants.SP_ACCELERATOR_MEMBERSHIP_EXPIRED)
|
||||
val showExpiredDialog = !vipEntity.vipStatus &&
|
||||
!vipEntity.isNewUser &&
|
||||
!vipEntity.isVipRefundUser &&
|
||||
!vipEntity.isDurationRefundUser &&
|
||||
!hasShow
|
||||
if (showExpiredDialog) {
|
||||
val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.TimeRunsOut(sourceEntrance)
|
||||
AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
|
||||
if (it) {
|
||||
dismissAllowingStateLoss()
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否是会员
|
||||
if (vipEntity.vipStatus) {
|
||||
callback()
|
||||
} else {
|
||||
// 弹出去充值弹窗
|
||||
AcceleratorDialogFragment.show(
|
||||
SPEED_ENABLE_VIP,
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
sourceEntrance,
|
||||
requireContext()
|
||||
)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateCalendarDaysDiff(timeSeconds1: Long, timeSeconds2: Long): Long {
|
||||
// 转换秒为毫秒
|
||||
val millis1 = timeSeconds1 * 1000
|
||||
val millis2 = timeSeconds2 * 1000
|
||||
|
||||
val calendar1 = Calendar.getInstance().apply {
|
||||
timeInMillis = millis1
|
||||
set(Calendar.HOUR_OF_DAY, 0)
|
||||
set(Calendar.MINUTE, 0)
|
||||
set(Calendar.SECOND, 0)
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
}
|
||||
val calendar2 = Calendar.getInstance().apply {
|
||||
timeInMillis = millis2
|
||||
set(Calendar.HOUR_OF_DAY, 0)
|
||||
set(Calendar.MINUTE, 0)
|
||||
set(Calendar.SECOND, 0)
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
}
|
||||
|
||||
// 计算两个日期零点之间的差值(毫秒),再转换为天数
|
||||
val diff = (calendar1.timeInMillis - calendar2.timeInMillis) / (1000 * 60 * 60 * 24)
|
||||
// 当diff == 0 时,当天过期,此时剩余天数为 1 天
|
||||
return if (diff >= 0) diff + 1 else -1
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -86,7 +86,8 @@ class GameDetailFragment : LazyFragment(), IScrollable {
|
||||
GameDetailCoverAdapter(
|
||||
requireContext(),
|
||||
this@GameDetailFragment,
|
||||
viewModel
|
||||
viewModel,
|
||||
scrollCalculatorHelper
|
||||
) {
|
||||
binding.coverSfv.isVisible = shouldShowCoverFilter && it
|
||||
}
|
||||
@ -187,15 +188,20 @@ class GameDetailFragment : LazyFragment(), IScrollable {
|
||||
coverSfv.goneIf(!shouldShowCoverFilter) {
|
||||
val defaultTabPosition =
|
||||
tabNameList.indexOfFirst { tabName -> viewModel.defaultCoverEntity?.tabName == tabName }
|
||||
viewModel.coverTabSequence = defaultTabPosition + 1
|
||||
viewModel.coverTabName = viewModel.defaultCoverEntity?.tabName ?: ""
|
||||
coverSfv.setItemList(tabNameList, if (defaultTabPosition != -1) defaultTabPosition else 0)
|
||||
coverSfv.setOnCheckedCallback { position ->
|
||||
val checkedText = tabNameList.getOrNull(position)
|
||||
val currentCoverEntity = it.getOrNull(coverPosition)
|
||||
viewModel.coverTabSequence = position + 1
|
||||
viewModel.coverTabName = checkedText ?: ""
|
||||
SensorsBridge.trackEvent("GameDetailMediaTabClick", json {
|
||||
"game_id" to gameEntity?.id
|
||||
"game_name" to gameEntity?.name
|
||||
"sequence" to position + 1
|
||||
"tab_name" to checkedText
|
||||
"sequence" to viewModel.coverTabSequence
|
||||
"tab_name" to viewModel.coverTabName
|
||||
"game_type" to gameEntity?.categoryChinese
|
||||
})
|
||||
if (currentCoverEntity?.tabName == checkedText) return@setOnCheckedCallback
|
||||
|
||||
@ -307,7 +313,7 @@ class GameDetailFragment : LazyFragment(), IScrollable {
|
||||
|
||||
private fun initDetailRv() {
|
||||
binding.detailRv.run {
|
||||
(itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
itemAnimator = null
|
||||
layoutManager = detailLayoutManager
|
||||
adapter = detailListAdapter
|
||||
addOnScrollListener(object : OnScrollListener() {
|
||||
|
||||
@ -23,6 +23,7 @@ import com.gh.gamecenter.databinding.ItemGameCoverVideoBinding
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.detail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.entity.CoverEntity
|
||||
import com.gh.gamecenter.gamedetail.video.GameDetailScrollCalculatorHelper
|
||||
import com.gh.gamecenter.gamedetail.video.TopVideoView
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
@ -33,6 +34,7 @@ class GameDetailCoverAdapter(
|
||||
context: Context,
|
||||
private val fragment: GameDetailFragment,
|
||||
private val viewModel: GameDetailViewModel,
|
||||
private val scrollCalculatorHelper: GameDetailScrollCalculatorHelper,
|
||||
private val showOrHideCoverFilter: ((Boolean) -> Unit)
|
||||
) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
@ -108,6 +110,14 @@ class GameDetailCoverAdapter(
|
||||
.setAutoFullWithSize(true)
|
||||
.setDismissControlTime(5000)
|
||||
.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onClickStartIcon(url: String?, vararg objects: Any?) {
|
||||
scrollCalculatorHelper.currentPlayer = holder.binding.player
|
||||
}
|
||||
|
||||
override fun onClickResume(url: String?, vararg objects: Any?) {
|
||||
scrollCalculatorHelper.currentPlayer = holder.binding.player
|
||||
}
|
||||
|
||||
override fun onQuitFullscreen(url: String?, vararg objects: Any) {
|
||||
orientationUtils.backToProtVideo()
|
||||
holder.binding.player.uploadVideoStreamingPlaying("退出全屏")
|
||||
@ -115,9 +125,9 @@ class GameDetailCoverAdapter(
|
||||
})
|
||||
.build(holder.binding.player)
|
||||
|
||||
holder.binding.player.gameName = viewModel.game?.name ?: ""
|
||||
holder.binding.player.viewModel = viewModel
|
||||
holder.binding.player.showOrHideCoverFilter = showOrHideCoverFilter
|
||||
holder.binding.player.scrollCalculatorHelper = scrollCalculatorHelper
|
||||
holder.binding.player.video = topVideo
|
||||
holder.binding.player.updateThumb(topVideo.poster)
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ class GameDetailRelatedGameAdapter(
|
||||
holder.binding.root.setPadding(paddingStart, 8F.dip2px(), paddingEnd, 8F.dip2px())
|
||||
holder.binding.gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
holder.binding.gameNameTv.text = gameEntity.name
|
||||
BindingAdapters.setGameTags(holder.binding.gameLabelLl, gameEntity)
|
||||
BindingAdapters.setGameTags(holder.binding.gameLabelLl, gameEntity, "")
|
||||
holder.binding.gameIconView.displayGameIcon(gameEntity)
|
||||
holder.binding.gameIconView.setBorderColor(com.gh.gamecenter.common.R.color.resource_border)
|
||||
holder.itemView.setOnClickListener {
|
||||
|
||||
@ -46,7 +46,7 @@ class GameDetailBriefItemViewHolder(
|
||||
highlightedTextClickListener = TextHelper.CopyToClipboardHighlightedTextClick()
|
||||
)
|
||||
briefTv.post {
|
||||
expandTv.isVisible = briefTv.lineCount == 3 && briefTv.layout.getEllipsisCount(2) > 0
|
||||
expandTv.isVisible = briefTv.lineCount == 3 && (briefTv.layout?.getEllipsisCount(2) ?: 0) > 0
|
||||
}
|
||||
expandTv.setOnClickListener {
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
@ -57,6 +57,7 @@ class GameDetailBriefItemViewHolder(
|
||||
moduleType,
|
||||
entity.name,
|
||||
sequence,
|
||||
"简介文案",
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
GameDetailScrollableTextDialogFragment.show(
|
||||
@ -86,6 +87,9 @@ class GameDetailBriefItemViewHolder(
|
||||
moduleType,
|
||||
itemData?.linkGameBrief?.name,
|
||||
sequence,
|
||||
"游戏标签",
|
||||
index + 1,
|
||||
linkText = gameTag.name,
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
context.startActivity(
|
||||
|
||||
@ -82,6 +82,7 @@ class GameDetailComprehensivePanelItemViewHolder(
|
||||
root.updateLayoutParams<MarginLayoutParams> {
|
||||
topMargin = if (position == 0) 0 else 8F.dip2px()
|
||||
}
|
||||
titleIv.goneIf(!data.showTitle)
|
||||
titleTv.goneIf(!data.showTitle) {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
titleTv.text = data.title
|
||||
@ -127,6 +128,7 @@ class GameDetailComprehensivePanelItemViewHolder(
|
||||
topMargin = if (position == 0) 0 else 16F.dip2px()
|
||||
bottomMargin = if (position == itemCount - 1) 0 else if (data.showTitle) 12F.dip2px() else 8F.dip2px()
|
||||
}
|
||||
titleIv.goneIf(!data.showTitle)
|
||||
titleTv.goneIf(!data.showTitle) {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
titleTv.text = data.title
|
||||
@ -150,6 +152,7 @@ class GameDetailComprehensivePanelItemViewHolder(
|
||||
root.updateLayoutParams<MarginLayoutParams> {
|
||||
topMargin = if (position == 0) 0 else 12F.dip2px()
|
||||
}
|
||||
titleIv.goneIf(!data.showTitle)
|
||||
titleTv.goneIf(!data.showTitle) {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
titleTv.text = data.title
|
||||
@ -179,17 +182,23 @@ class GameDetailComprehensivePanelItemViewHolder(
|
||||
|
||||
override fun onBindViewHolder(holder: ComprehensivePanelFunctionItemViewHolder, position: Int) {
|
||||
val data = dataList.getOrNull(position) ?: return
|
||||
holder.binding.numberIv.setImageResource(R.drawable.bg_game_detail_comprehensive_panel_function_number)
|
||||
holder.binding.numberIv.goneIf(dataList.size < 2) {
|
||||
holder.binding.numberIv.setImageResource(R.drawable.bg_game_detail_comprehensive_panel_function_number)
|
||||
}
|
||||
holder.binding.numberTv.run {
|
||||
setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(context))
|
||||
setTypeface(Typeface.createFromAsset(context.assets, Constants.DIN_FONT_PATH))
|
||||
text = (position + 1).toString()
|
||||
goneIf(dataList.size < 2) {
|
||||
setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(context))
|
||||
setTypeface(Typeface.createFromAsset(context.assets, Constants.DIN_FONT_PATH))
|
||||
text = (position + 1).toString()
|
||||
}
|
||||
}
|
||||
holder.binding.contentTv.run {
|
||||
setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
maxLines = if (parentViewHolder.showPart && !parentViewHolder.isExpand) 1 else Int.MAX_VALUE
|
||||
text = data.text
|
||||
post {
|
||||
if (layout == null) return@post
|
||||
|
||||
val hasEllipsize = layout.getEllipsisCount(0) > 0
|
||||
if (parentViewHolder.showPart && hasEllipsize && !parentViewHolder.binding.expandTv.isVisible) {
|
||||
parentViewHolder.binding.expandTv.isVisible = true
|
||||
|
||||
@ -2,10 +2,8 @@ package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailContentCardDoubleBinding
|
||||
import com.gh.gamecenter.databinding.LayoutGameDetailContentCardBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
|
||||
class GameDetailContentCardDoubleItemViewHolder(
|
||||
@ -19,51 +17,24 @@ class GameDetailContentCardDoubleItemViewHolder(
|
||||
super.bindView(data)
|
||||
data.linkContentCard?.let {
|
||||
val getGameStatus = { gameStatus }
|
||||
bindContentCard(
|
||||
GameDetailContentCardSingleItemViewHolder.bindContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it.first(),
|
||||
data.cardBackground,
|
||||
binding.firstCardContainer,
|
||||
baseTrackData.apply { supSequence = 0 },
|
||||
getGameStatus
|
||||
)
|
||||
bindContentCard(
|
||||
GameDetailContentCardSingleItemViewHolder.bindContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it[1],
|
||||
null,
|
||||
binding.secondCardContainer,
|
||||
baseTrackData.apply { supSequence = 1 },
|
||||
getGameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun bindContentCard(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
viewModel: GameDetailViewModel,
|
||||
contentCardEntity: ContentCardEntity,
|
||||
itemBinding: LayoutGameDetailContentCardBinding,
|
||||
trackData: GameDetailModuleTrackData,
|
||||
getGameStatus: () -> String
|
||||
) {
|
||||
itemBinding.run {
|
||||
GameDetailContentCardSingleItemViewHolder.bindContentCard(
|
||||
root.context,
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
contentCardEntity,
|
||||
root,
|
||||
titleTv,
|
||||
iconIv,
|
||||
contentTv,
|
||||
contentBannerView,
|
||||
redDotTv,
|
||||
newIv,
|
||||
trackData,
|
||||
getGameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,8 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
@ -19,10 +15,12 @@ import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.TextBannerView
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailContentCardSingleBinding
|
||||
import com.gh.gamecenter.databinding.LayoutGameDetailContentCardBinding
|
||||
import com.gh.gamecenter.feature.entity.MeEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.CardBackground
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_ARCHIVE
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_BBS
|
||||
@ -51,144 +49,147 @@ class GameDetailContentCardSingleItemViewHolder(
|
||||
val contentCardEntity = data.linkContentCard?.first() ?: return
|
||||
binding.run {
|
||||
bindContentCard(
|
||||
context,
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
contentCardEntity,
|
||||
container,
|
||||
titleTv,
|
||||
iconIv,
|
||||
contentTv,
|
||||
contentBannerView,
|
||||
redDotTv,
|
||||
newIv,
|
||||
data.cardBackground,
|
||||
firstCardContainer,
|
||||
baseTrackData.apply { supSequence = 0 }
|
||||
) { gameStatus }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun bindContentCard(
|
||||
context: Context,
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
viewModel: GameDetailViewModel,
|
||||
contentCardEntity: ContentCardEntity,
|
||||
containerView: ConstraintLayout,
|
||||
titleTv: TextView,
|
||||
iconIv: SimpleDraweeView,
|
||||
contentTv: TextView,
|
||||
contentBannerView: TextBannerView,
|
||||
redDotTv: TextView,
|
||||
newIv: ImageView,
|
||||
cardBackground: CardBackground?,
|
||||
itemBinding: LayoutGameDetailContentCardBinding,
|
||||
trackData: GameDetailModuleTrackData,
|
||||
getGameStatus: () -> String
|
||||
) {
|
||||
if (contentCardEntity.id == containerView.tag) {
|
||||
if (contentBannerView.isVisible) contentBannerView.updateView()
|
||||
containerView.background = com.gh.gamecenter.common.R.drawable.bg_shape_f8_radius_8.toDrawable(context)
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
contentTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
containerView.tag = contentCardEntity.id
|
||||
titleTv.text = contentCardEntity.title
|
||||
ImageUtils.display(iconIv, contentCardEntity.icon)
|
||||
|
||||
val showContentTv =
|
||||
contentCardEntity.showDes && (contentCardEntity.des.isNotEmpty() || contentCardEntity.link.type == TYPE_GIFT)
|
||||
contentTv.visibleIf(showContentTv) {
|
||||
contentTv.text =
|
||||
if (contentCardEntity.link.type == TYPE_GIFT && contentCardEntity.des.isEmpty()) "${contentCardEntity.libao?.total}个游戏礼包" else contentCardEntity.des
|
||||
contentTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
}
|
||||
|
||||
val showContentBannerView =
|
||||
contentCardEntity.showDes && contentCardEntity.link.type == TYPE_SERVER && contentCardEntity.server != null && contentCardEntity.des.isEmpty()
|
||||
contentBannerView.goneIf(!showContentBannerView) {
|
||||
val server = contentCardEntity.server ?: return@goneIf
|
||||
val nowTime = System.currentTimeMillis()
|
||||
var timeDiff = 0L
|
||||
var closestIndex = 0
|
||||
val bannerTextDataList = server.calendar.mapIndexed { index, serverCalendarEntity ->
|
||||
val diff = abs(nowTime - serverCalendarEntity.getTime() * 1000L)
|
||||
if (diff < timeDiff || index == 0) {
|
||||
timeDiff = diff
|
||||
closestIndex = index
|
||||
with(itemBinding) {
|
||||
val context = root.context
|
||||
if (contentCardEntity.id == root.tag) {
|
||||
if (contentBannerView.isVisible) contentBannerView.updateView()
|
||||
cardBackground?.colorTransparent?.let {
|
||||
root.setRoundedColorBackgroundByColorInt(
|
||||
it.RGBAToARGB().hexStringToIntColor(),
|
||||
8F
|
||||
)
|
||||
} ?: run {
|
||||
root.background = com.gh.gamecenter.common.R.drawable.bg_shape_f8_radius_8.toDrawable(context)
|
||||
}
|
||||
val serverTime =
|
||||
if (TimeUtils.isToday(serverCalendarEntity.getTime()))
|
||||
serverCalendarEntity.getFormatTime("今天 HH:mm")
|
||||
else if (TimeUtils.isTomorrow(serverCalendarEntity.getTime()))
|
||||
serverCalendarEntity.getFormatTime("明天 HH:mm")
|
||||
else
|
||||
serverCalendarEntity.getFormatTime("MM-dd HH:mm")
|
||||
TextBannerView.BannerTextData("${serverTime ?: ""} ${serverCalendarEntity.type}")
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
contentTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
|
||||
return@with
|
||||
}
|
||||
contentBannerView.setDataList(bannerTextDataList, closestIndex)
|
||||
contentBannerView.startBannerLoop()
|
||||
}
|
||||
|
||||
redDotTv.goneIf(!((contentCardEntity.link.type == TYPE_SERVER && contentCardEntity.server?.total != 0) || contentCardEntity.link.type == TYPE_GIFT)) {
|
||||
if ((contentCardEntity.link.type == TYPE_SERVER) && (contentCardEntity.server?.calendar?.isNotEmpty() == true))
|
||||
redDotTv.text = contentCardEntity.server?.total.toString()
|
||||
if ((contentCardEntity.link.type == TYPE_GIFT) && (contentCardEntity.libao != null))
|
||||
redDotTv.text = contentCardEntity.libao?.total.toString()
|
||||
}
|
||||
|
||||
val showNewTag = contentCardEntity.link.type == TYPE_ARCHIVE && contentCardEntity.archive != null && contentCardEntity.showNewTag
|
||||
newIv.goneIf(!showNewTag)
|
||||
|
||||
containerView.setOnClickListener {
|
||||
NewFlatLogUtils.logGameDetailGameContentCardClick(
|
||||
contentCardEntity.title ?: "",
|
||||
viewModel.game?.name ?: "",
|
||||
viewModel.game?.id ?: "",
|
||||
contentCardEntity.link.type ?: "",
|
||||
contentCardEntity.link.link ?: "",
|
||||
contentCardEntity.link.text ?: ""
|
||||
)
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId = trackData.gameId,
|
||||
gameName = trackData.gameName,
|
||||
gameType = trackData.gameType,
|
||||
contentType = "组件内容",
|
||||
moduleType = trackData.moduleType,
|
||||
moduleName = trackData.moduleName,
|
||||
sequence = trackData.sequence,
|
||||
linkText = contentCardEntity.link.text ?: "",
|
||||
linkType = contentCardEntity.link.type ?: "",
|
||||
linkId = contentCardEntity.id,
|
||||
gameStatus = getGameStatus()
|
||||
)
|
||||
|
||||
val dialog = contentCardEntity.dialog
|
||||
if (dialog != null) {// 展示内容卡片提示弹窗
|
||||
DialogHelper.showDialog(
|
||||
context = context,
|
||||
title = dialog.title ?: "",
|
||||
content = dialog.body ?: "",
|
||||
confirmText = context.getString(com.gh.gamecenter.common.R.string.confirm),
|
||||
cancelText = context.getString(com.gh.gamecenter.common.R.string.cancel),
|
||||
confirmClickCallback = {
|
||||
jumpToContentCardLink(context, contentCardEntity, viewModel)
|
||||
}
|
||||
root.tag = contentCardEntity.id
|
||||
cardBackground?.colorTransparent?.let {
|
||||
root.setRoundedColorBackgroundByColorInt(
|
||||
it.RGBAToARGB().hexStringToIntColor(),
|
||||
8F
|
||||
)
|
||||
} else {
|
||||
jumpToContentCardLink(context, contentCardEntity, viewModel)
|
||||
}
|
||||
}
|
||||
titleTv.text = contentCardEntity.title
|
||||
ImageUtils.display(iconIv, contentCardEntity.icon)
|
||||
|
||||
viewModel.contentCardClickedLiveData.observe(lifecycleOwner) {
|
||||
if (it.peekContent() == contentCardEntity.link.type) {
|
||||
it.getContentWithHandled()?.let { containerView.performClick() }
|
||||
val showContentTv =
|
||||
contentCardEntity.showDes && (contentCardEntity.des.isNotEmpty() || contentCardEntity.link.type == TYPE_GIFT)
|
||||
contentTv.visibleIf(showContentTv) {
|
||||
contentTv.text =
|
||||
if (contentCardEntity.link.type == TYPE_GIFT && contentCardEntity.des.isEmpty()) "${contentCardEntity.libao?.total}个游戏礼包" else contentCardEntity.des
|
||||
contentTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
}
|
||||
|
||||
val showContentBannerView =
|
||||
contentCardEntity.showDes && contentCardEntity.link.type == TYPE_SERVER && contentCardEntity.server != null && contentCardEntity.des.isEmpty()
|
||||
contentBannerView.goneIf(!showContentBannerView) {
|
||||
val server = contentCardEntity.server ?: return@goneIf
|
||||
val nowTime = System.currentTimeMillis()
|
||||
var timeDiff = 0L
|
||||
var closestIndex = 0
|
||||
val bannerTextDataList = server.calendar.mapIndexed { index, serverCalendarEntity ->
|
||||
val diff = abs(nowTime - serverCalendarEntity.getTime() * 1000L)
|
||||
if (diff < timeDiff || index == 0) {
|
||||
timeDiff = diff
|
||||
closestIndex = index
|
||||
}
|
||||
val serverTime =
|
||||
if (TimeUtils.isToday(serverCalendarEntity.getTime()))
|
||||
serverCalendarEntity.getFormatTime("今天 HH:mm")
|
||||
else if (TimeUtils.isTomorrow(serverCalendarEntity.getTime()))
|
||||
serverCalendarEntity.getFormatTime("明天 HH:mm")
|
||||
else
|
||||
serverCalendarEntity.getFormatTime("MM-dd HH:mm")
|
||||
TextBannerView.BannerTextData("${serverTime ?: ""} ${serverCalendarEntity.type}")
|
||||
}
|
||||
contentBannerView.setDataList(bannerTextDataList, closestIndex)
|
||||
contentBannerView.startBannerLoop()
|
||||
}
|
||||
|
||||
redDotTv.goneIf(!((contentCardEntity.link.type == TYPE_SERVER && contentCardEntity.server?.total != 0) || contentCardEntity.link.type == TYPE_GIFT)) {
|
||||
if ((contentCardEntity.link.type == TYPE_SERVER) && (contentCardEntity.server?.calendar?.isNotEmpty() == true))
|
||||
redDotTv.text = contentCardEntity.server?.total.toString()
|
||||
if ((contentCardEntity.link.type == TYPE_GIFT) && (contentCardEntity.libao != null))
|
||||
redDotTv.text = contentCardEntity.libao?.total.toString()
|
||||
}
|
||||
|
||||
val showNewTag = contentCardEntity.link.type == TYPE_ARCHIVE && contentCardEntity.archive != null && contentCardEntity.showNewTag
|
||||
newIv.goneIf(!showNewTag)
|
||||
|
||||
root.setOnClickListener {
|
||||
NewFlatLogUtils.logGameDetailGameContentCardClick(
|
||||
contentCardEntity.title ?: "",
|
||||
viewModel.game?.name ?: "",
|
||||
viewModel.game?.id ?: "",
|
||||
contentCardEntity.link.type ?: "",
|
||||
contentCardEntity.link.link ?: "",
|
||||
contentCardEntity.link.text ?: ""
|
||||
)
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId = trackData.gameId,
|
||||
gameName = trackData.gameName,
|
||||
gameType = trackData.gameType,
|
||||
contentType = "组件内容",
|
||||
moduleType = trackData.moduleType,
|
||||
moduleName = trackData.moduleName,
|
||||
sequence = trackData.sequence,
|
||||
linkText = contentCardEntity.link.text ?: "",
|
||||
linkType = contentCardEntity.link.type ?: "",
|
||||
linkId = contentCardEntity.id,
|
||||
gameStatus = getGameStatus()
|
||||
)
|
||||
|
||||
val dialog = contentCardEntity.dialog
|
||||
if (dialog != null) {// 展示内容卡片提示弹窗
|
||||
DialogHelper.showDialog(
|
||||
context = context,
|
||||
title = dialog.title ?: "",
|
||||
content = dialog.body ?: "",
|
||||
confirmText = context.getString(com.gh.gamecenter.common.R.string.confirm),
|
||||
cancelText = context.getString(com.gh.gamecenter.common.R.string.cancel),
|
||||
confirmClickCallback = {
|
||||
jumpToContentCardLink(context, contentCardEntity, viewModel)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
jumpToContentCardLink(context, contentCardEntity, viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.contentCardClickedLiveData.observe(lifecycleOwner) {
|
||||
if (it.peekContent() == contentCardEntity.link.type) {
|
||||
it.getContentWithHandled()?.let { root.performClick() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun jumpToContentCardLink(context: Context, contentCardEntity: ContentCardEntity, viewModel: GameDetailViewModel) {
|
||||
fun jumpToContentCardLink(context: Context, contentCardEntity: ContentCardEntity, viewModel: GameDetailViewModel) {
|
||||
val path = "游戏详情->内容卡片"
|
||||
when (contentCardEntity.link.type) {
|
||||
TYPE_GIFT,
|
||||
@ -211,7 +212,7 @@ class GameDetailContentCardSingleItemViewHolder(
|
||||
ServersCalendarActivity.getIntent(
|
||||
context,
|
||||
viewModel.game!!, contentCardEntity.server!!,
|
||||
MeEntity()
|
||||
viewModel.meLiveData.value ?: MeEntity()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,10 +1,17 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailContentCardTripleBinding
|
||||
import com.gh.gamecenter.databinding.LayoutGameDetailContentCardSmallBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.detail.viewholder.GameDetailContentCardDoubleItemViewHolder.Companion.bindContentCard
|
||||
import com.gh.gamecenter.gamedetail.detail.viewholder.GameDetailContentCardSingleItemViewHolder.Companion.jumpToContentCardLink
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_ARCHIVE
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_GIFT
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_SERVER
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
|
||||
class GameDetailContentCardTripleItemViewHolder(
|
||||
@ -17,15 +24,16 @@ class GameDetailContentCardTripleItemViewHolder(
|
||||
super.bindView(data)
|
||||
data.linkContentCard?.let {
|
||||
val getGameStatus = { gameStatus }
|
||||
bindContentCard(
|
||||
GameDetailContentCardSingleItemViewHolder.bindContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it.first(),
|
||||
data.cardBackground,
|
||||
binding.firstCardContainer,
|
||||
baseTrackData.apply { supSequence = 0 },
|
||||
getGameStatus
|
||||
)
|
||||
bindContentCard(
|
||||
bindSmallContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it[1].apply { showDes = false },
|
||||
@ -33,7 +41,7 @@ class GameDetailContentCardTripleItemViewHolder(
|
||||
baseTrackData.apply { supSequence = 1 },
|
||||
getGameStatus
|
||||
)
|
||||
bindContentCard(
|
||||
bindSmallContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it[2].apply { showDes = false },
|
||||
@ -43,4 +51,85 @@ class GameDetailContentCardTripleItemViewHolder(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun bindSmallContentCard(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
viewModel: GameDetailViewModel,
|
||||
contentCardEntity: ContentCardEntity,
|
||||
itemBinding: LayoutGameDetailContentCardSmallBinding,
|
||||
trackData: GameDetailModuleTrackData,
|
||||
getGameStatus: () -> String
|
||||
) {
|
||||
with(itemBinding) {
|
||||
val context = root.context
|
||||
if (contentCardEntity.id == root.tag) {
|
||||
root.background = com.gh.gamecenter.common.R.drawable.bg_shape_f8_radius_8.toDrawable(context)
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
|
||||
return@with
|
||||
}
|
||||
|
||||
root.tag = contentCardEntity.id
|
||||
titleTv.text = contentCardEntity.title
|
||||
ImageUtils.display(iconIv, contentCardEntity.icon)
|
||||
|
||||
redDotTv.goneIf(!((contentCardEntity.link.type == TYPE_SERVER && contentCardEntity.server?.total != 0) || contentCardEntity.link.type == TYPE_GIFT)) {
|
||||
if ((contentCardEntity.link.type == TYPE_SERVER) && (contentCardEntity.server?.calendar?.isNotEmpty() == true))
|
||||
redDotTv.text = contentCardEntity.server?.total.toString()
|
||||
if ((contentCardEntity.link.type == TYPE_GIFT) && (contentCardEntity.libao != null))
|
||||
redDotTv.text = contentCardEntity.libao?.total.toString()
|
||||
}
|
||||
|
||||
val showNewTag = contentCardEntity.link.type == TYPE_ARCHIVE && contentCardEntity.archive != null && contentCardEntity.showNewTag
|
||||
newIv.goneIf(!showNewTag)
|
||||
|
||||
root.setOnClickListener {
|
||||
NewFlatLogUtils.logGameDetailGameContentCardClick(
|
||||
contentCardEntity.title ?: "",
|
||||
viewModel.game?.name ?: "",
|
||||
viewModel.game?.id ?: "",
|
||||
contentCardEntity.link.type ?: "",
|
||||
contentCardEntity.link.link ?: "",
|
||||
contentCardEntity.link.text ?: ""
|
||||
)
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId = trackData.gameId,
|
||||
gameName = trackData.gameName,
|
||||
gameType = trackData.gameType,
|
||||
contentType = "组件内容",
|
||||
moduleType = trackData.moduleType,
|
||||
moduleName = trackData.moduleName,
|
||||
sequence = trackData.sequence,
|
||||
linkText = contentCardEntity.link.text ?: "",
|
||||
linkType = contentCardEntity.link.type ?: "",
|
||||
linkId = contentCardEntity.id,
|
||||
gameStatus = getGameStatus()
|
||||
)
|
||||
|
||||
val dialog = contentCardEntity.dialog
|
||||
if (dialog != null) {// 展示内容卡片提示弹窗
|
||||
DialogHelper.showDialog(
|
||||
context = context,
|
||||
title = dialog.title ?: "",
|
||||
content = dialog.body ?: "",
|
||||
confirmText = context.getString(com.gh.gamecenter.common.R.string.confirm),
|
||||
cancelText = context.getString(com.gh.gamecenter.common.R.string.cancel),
|
||||
confirmClickCallback = {
|
||||
jumpToContentCardLink(context, contentCardEntity, viewModel)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
jumpToContentCardLink(context, contentCardEntity, viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.contentCardClickedLiveData.observe(lifecycleOwner) {
|
||||
if (it.peekContent() == contentCardEntity.link.type) {
|
||||
it.getContentWithHandled()?.let { root.performClick() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@ class GameDetailDeveloperWordItemViewHolder(
|
||||
.fromHtmlCompat(PicassoImageGetter(contentTv), ExtraTagHandler())
|
||||
)
|
||||
contentTv.post {
|
||||
expandTv.isVisible = (contentTv.lineCount == 3 && contentTv.layout.getEllipsisCount(2) > 0) || contentTv.lineCount > 3
|
||||
expandTv.isVisible = (contentTv.lineCount == 3 && (contentTv.layout?.getEllipsisCount(2) ?: 0) > 0) || contentTv.lineCount > 3
|
||||
}
|
||||
expandTv.background = R.drawable.bg_ui_surface_expand_gradient.toDrawable(context)
|
||||
expandTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
|
||||
|
||||
@ -120,14 +120,14 @@ class GameDetailInfoItemViewHolder(
|
||||
nameTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
infoTv.setTextColor(if (data.name == TYPE_ICP) com.gh.gamecenter.common.R.color.text_theme.toColor(context) else com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
actionTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
|
||||
nameTv.text = if (data.name == TYPE_CONTACT) data.contact?.hint else normalTypeNameMap[data.name]
|
||||
nameTv.text = if (data.name == TYPE_CONTACT) data.text else normalTypeNameMap[data.name]
|
||||
infoTv.text = when (data.name) {
|
||||
TYPE_INTERNET -> if (data.value == "yes") "是" else "否"
|
||||
TYPE_UPDATE_TIME -> data.value.toLongOrNull()?.let { TimeUtils.getFormatTime(it) }
|
||||
else -> data.value
|
||||
}
|
||||
actionTv.goneIf(data.name != TYPE_CONTACT || data.contact == null) {
|
||||
val actionString = if (data.contact?.type == "qq") ACTION_CONTACT else if (data.contact?.key.isNullOrEmpty()) ACTION_COPY else ACTION_JOIN
|
||||
actionTv.goneIf(data.name != TYPE_CONTACT) {
|
||||
val actionString = if (data.type == "qq") ACTION_CONTACT else if (data.key.isNotEmpty()) ACTION_JOIN else ACTION_COPY
|
||||
actionTv.text = actionString
|
||||
actionTv.setOnClickListener {
|
||||
when (actionString) {
|
||||
@ -141,7 +141,7 @@ class GameDetailInfoItemViewHolder(
|
||||
|
||||
ACTION_JOIN -> {
|
||||
if (ShareUtils.isQQClientAvailable(context)) {
|
||||
DirectUtils.directToQqGroup(context, data.contact?.key)
|
||||
DirectUtils.directToQqGroup(context, data.key)
|
||||
} else {
|
||||
data.value.copyTextAndToast("已复制")
|
||||
}
|
||||
@ -191,11 +191,11 @@ class GameDetailInfoItemViewHolder(
|
||||
const val TYPE_CREDIT_CODE = "credit_code"
|
||||
const val TYPE_SIZE = "size"
|
||||
const val TYPE_SUPPLIER = "supplier"
|
||||
const val TYPE_CONTACT = "contact"
|
||||
const val TYPE_CONTACT = "qq/qq_qun"
|
||||
|
||||
const val ACTION_COPY = "复制"
|
||||
const val ACTION_JOIN = "加入"
|
||||
const val ACTION_CONTACT = "咨询"
|
||||
const val ACTION_CONTACT = "添加"
|
||||
|
||||
// 固定信息类型
|
||||
val staticTypeNameMap = mapOf(
|
||||
|
||||
@ -53,7 +53,7 @@ class GameDetailServerItemViewHolder(
|
||||
context,
|
||||
viewModel.game!!,
|
||||
entity,
|
||||
null
|
||||
viewModel.meLiveData.value
|
||||
)
|
||||
context.startActivity(intent)
|
||||
viewModel.game?.let {
|
||||
|
||||
@ -36,7 +36,7 @@ class GameDetailUpdateItemViewHolder(
|
||||
}
|
||||
contentTv.text = entity.updateDes
|
||||
contentTv.post {
|
||||
expandTv.isVisible = contentTv.lineCount == 3 && contentTv.layout.getEllipsisCount(2) > 0
|
||||
expandTv.isVisible = contentTv.lineCount == 3 && (contentTv.layout?.getEllipsisCount(2) ?: 0) > 0
|
||||
}
|
||||
expandTv.background = R.drawable.bg_ui_surface_expand_gradient.toDrawable(context)
|
||||
expandTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
|
||||
|
||||
@ -0,0 +1,176 @@
|
||||
package com.gh.gamecenter.gamedetail.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.common.util.DetailDownloadUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder
|
||||
import com.gh.gamecenter.common.base.fragment.BaseBottomDialogFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.databinding.DialogFragmentDspGameDetailBinding
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.json.JSONObject
|
||||
|
||||
class DspGameDetailDialogFragment : BaseBottomDialogFragment<DialogFragmentDspGameDetailBinding>() {
|
||||
|
||||
private var gameEntity: GameEntity? = null
|
||||
|
||||
private val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
updateDownloadStatus()
|
||||
}
|
||||
|
||||
override fun onDataInit(downloadEntity: DownloadEntity) {
|
||||
updateDownloadStatus()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDownloadStatus() {
|
||||
gameEntity?.let {
|
||||
DetailDownloadUtils.updateViewHolder(
|
||||
DetailViewHolder(
|
||||
mBinding.detailLlBottom,
|
||||
null,
|
||||
it,
|
||||
false,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
null,
|
||||
false,
|
||||
null,
|
||||
null
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
gameEntity = arguments?.getParcelable(EntranceConsts.KEY_GAME_ENTITY)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
gameEntity?.let {
|
||||
val apk = it.getApk().firstOrNull()
|
||||
|
||||
mBinding.ivIcon.displayGameIcon(it)
|
||||
mBinding.tvName.text = it.name
|
||||
mBinding.tvVersion.text = getString(R.string.version_name, apk?.version ?: "")
|
||||
mBinding.titleView.setOnRightClickListener { dismiss() }
|
||||
mBinding.tvDeveloper.text = getString(R.string.developer_name, it.developer ?: "")
|
||||
|
||||
mBinding.tvPermissions.setOnClickListener {
|
||||
logClickEvent("游戏详情-应用权限")
|
||||
DirectUtils.directToWebView(
|
||||
context = requireContext(),
|
||||
url = gameEntity?.permissionsUrl ?: "",
|
||||
title = "应用权限")
|
||||
}
|
||||
|
||||
mBinding.tvPrivacyPolicy.setOnClickListener {
|
||||
logClickEvent("游戏详情-隐私政策")
|
||||
DirectUtils.directToWebView(
|
||||
context = requireContext(),
|
||||
url = gameEntity?.privacyUrl ?: "",
|
||||
title = "隐私政策"
|
||||
)
|
||||
}
|
||||
|
||||
mBinding.detailProgressbar.goneIf(apk == null)
|
||||
if (apk != null) {
|
||||
mBinding.detailProgressbar.setOnTouchListener { _, motionEvent ->
|
||||
if (motionEvent.action == MotionEvent.ACTION_DOWN) {
|
||||
logClickEvent("游戏详情-按钮")
|
||||
}
|
||||
return@setOnTouchListener false
|
||||
}
|
||||
|
||||
DetailDownloadUtils.updateViewHolder(
|
||||
DetailViewHolder(
|
||||
mBinding.detailLlBottom,
|
||||
null,
|
||||
it,
|
||||
false,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
null,
|
||||
false,
|
||||
null
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
DownloadManager.getInstance().addObserver(dataWatcher)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
DownloadManager.getInstance().removeObserver(dataWatcher)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
||||
logClickEvent("游戏详情-关闭弹窗")
|
||||
}
|
||||
|
||||
private fun logClickEvent(text: String) {
|
||||
gameEntity?.let {
|
||||
val dspLogMap = it.tempDspLogMap as? HashMap<String, String>
|
||||
|
||||
dspLogMap?.let {
|
||||
dspLogMap["text"] = text
|
||||
SensorsBridge.trackDspAdClick(JSONObject(dspLogMap as Map<*, *>?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 接受安装、卸载消息
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if (gameEntity != null && gameEntity!!.getApk().size > 0) {
|
||||
for (apk in gameEntity!!.getApk()) {
|
||||
if (busFour.packageName == apk.packageName) {
|
||||
updateDownloadStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun show(context: Context, gameEntity: GameEntity) {
|
||||
if (context is AppCompatActivity) {
|
||||
context.supportFragmentManager
|
||||
} else {
|
||||
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
|
||||
}?.let {
|
||||
val fragment = DspGameDetailDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(EntranceConsts.KEY_GAME_ENTITY, gameEntity)
|
||||
}
|
||||
}
|
||||
fragment.show(it, fragment::class.java.simpleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,6 +29,8 @@ data class GameDetailData(
|
||||
val linkInfoTag: GameDetailInfoTag? = null,
|
||||
@SerializedName("link_content_card")
|
||||
val linkContentCard: List<ContentCardEntity>? = null,
|
||||
@SerializedName("card_background")
|
||||
val cardBackground: CardBackground? = null,
|
||||
@SerializedName("link_advertising")
|
||||
val linkAdvertising: GameDetailLink? = null,
|
||||
@SerializedName("link_comprehensive")
|
||||
@ -136,6 +138,13 @@ data class GameDetailData(
|
||||
}
|
||||
}
|
||||
|
||||
data class CardBackground(
|
||||
val color: String = "",
|
||||
val transparent: String = "",
|
||||
@SerializedName("color-transparent")
|
||||
val colorTransparent: String = "", // RGBA格式
|
||||
)
|
||||
|
||||
data class Order(
|
||||
@SerializedName("before_download")
|
||||
val beforeDownload: Int = -1, // 下载前排序
|
||||
@ -408,12 +417,14 @@ data class GameDetailInfo(
|
||||
@Parcelize
|
||||
data class InfoItem(
|
||||
val name: String = "",
|
||||
val type: String = "",
|
||||
val text: String = "",
|
||||
val key: String = "", // QQ群KEY
|
||||
val value: String = "",
|
||||
@SerializedName("is_first")
|
||||
val isFirst: Boolean = true, // 是否显示在一级页面
|
||||
val order: Int = -1, // 排序
|
||||
val permissions: List<Permission>? = null,
|
||||
val contact: Contact? = null
|
||||
): Parcelable
|
||||
}
|
||||
|
||||
|
||||
@ -143,13 +143,11 @@ class ServersCalendarActivity : ToolBarActivity() {
|
||||
setToolbarMenu(R.menu.menu_server_calendar_more)
|
||||
mBinding.subscribe.visibility = View.GONE
|
||||
mBinding.subscribeHint1.visibility = View.GONE
|
||||
mBinding.subscribeHint2.visibility = View.GONE
|
||||
mBinding.subscribe.setOnClickListener(null)
|
||||
} else {// 用户已登录并处于未订阅状态
|
||||
clearMenu()
|
||||
mBinding.subscribe.visibility = View.VISIBLE
|
||||
mBinding.subscribeHint1.visibility = View.VISIBLE
|
||||
mBinding.subscribeHint2.visibility = View.VISIBLE
|
||||
mBinding.subscribe.setOnClickListener {
|
||||
CheckLoginUtils.checkLogin(this, "游戏详情-开服日历表-开启订阅") {
|
||||
mViewModel.subscribeServer()
|
||||
|
||||
@ -238,7 +238,7 @@ class ServersCalendarDetailNoDataDialog : BottomSheetDialogFragment() {
|
||||
wechatRemindCheckIv.alpha = 1.0F
|
||||
wechatRemind.setOnClickListener {
|
||||
wechatRemindCheckIv.isChecked = !wechatRemindCheckIv.isChecked
|
||||
viewModel.wechatRemind = wechatRemindCheckIv.isChecked
|
||||
// viewModel.wechatRemind = wechatRemindCheckIv.isChecked
|
||||
SPUtils.setBoolean(Constants.SP_SERVERS_CALENDAR_BY_WECHAT, wechatRemindCheckIv.isChecked)
|
||||
}
|
||||
|
||||
|
||||
@ -30,14 +30,14 @@ class ServersCalendarDetailNoDataViewModel(
|
||||
|
||||
var appRemind: Boolean = false
|
||||
|
||||
var wechatRemind: Boolean = false
|
||||
val wechatRemind: Boolean = false
|
||||
|
||||
val timeInSeconds: Int = (serverTimeInMills / 1000).toInt()
|
||||
|
||||
fun initData(notifySetting: ServerCalendarNotifySetting?) {
|
||||
if (isDataInit) return
|
||||
appRemind = notifySetting?.byApp ?: SPUtils.getBoolean(Constants.SP_SERVERS_CALENDAR_BY_APP, true)
|
||||
wechatRemind = notifySetting?.byWechat ?: SPUtils.getBoolean(Constants.SP_SERVERS_CALENDAR_BY_WECHAT, true)
|
||||
// wechatRemind = notifySetting?.byWechat ?: SPUtils.getBoolean(Constants.SP_SERVERS_CALENDAR_BY_WECHAT, true)
|
||||
isDataInit = true
|
||||
}
|
||||
|
||||
|
||||
@ -308,7 +308,7 @@ class ServersCalendarDetailsRemindDialog : BottomSheetDialogFragment() {
|
||||
|
||||
viewBinding.wechatRemind.setOnClickListener {
|
||||
viewBinding.wechatRemindCheckIv.isChecked = !viewBinding.wechatRemindCheckIv.isChecked
|
||||
viewModel.wechatRemind = viewBinding.wechatRemindCheckIv.isChecked
|
||||
// viewModel.wechatRemind = viewBinding.wechatRemindCheckIv.isChecked
|
||||
SPUtils.setBoolean(Constants.SP_SERVERS_CALENDAR_BY_WECHAT, viewBinding.wechatRemindCheckIv.isChecked)
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ class ServersCalendarDetailsRemindViewModel(
|
||||
|
||||
var appRemind: Boolean = false
|
||||
|
||||
var wechatRemind: Boolean = false
|
||||
val wechatRemind: Boolean = false
|
||||
|
||||
val selectedNotifySeconds: Int get() = (selectedNotifyTime / 1000).toInt()
|
||||
|
||||
@ -58,7 +58,7 @@ class ServersCalendarDetailsRemindViewModel(
|
||||
selectedAdvancedTime = ServersCalendarAdvancedTime.valueOf(notifySetting?.secondsAdvance)
|
||||
selectedNotifyTime = (notifySetting?.notifyTime ?: calendarEntity.getTime()) * 1000
|
||||
appRemind = notifySetting?.byApp ?: SPUtils.getBoolean(Constants.SP_SERVERS_CALENDAR_BY_APP, true)
|
||||
wechatRemind = notifySetting?.byWechat ?: SPUtils.getBoolean(Constants.SP_SERVERS_CALENDAR_BY_WECHAT, true)
|
||||
// wechatRemind = notifySetting?.byWechat ?: SPUtils.getBoolean(Constants.SP_SERVERS_CALENDAR_BY_WECHAT, true)
|
||||
isDataInit = true
|
||||
}
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ class HistoryApkListAdapter(
|
||||
holder.binding.expandTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(mContext))
|
||||
holder.binding.updateDescTv.text = apkEntity.updateDesc
|
||||
holder.binding.updateDescTv.post {
|
||||
holder.binding.expandTv.isVisible = holder.binding.updateDescTv.lineCount == 3 && holder.binding.updateDescTv.layout.getEllipsisCount(2) > 0
|
||||
holder.binding.expandTv.isVisible = holder.binding.updateDescTv.lineCount == 3 && (holder.binding.updateDescTv.layout?.getEllipsisCount(2) ?: 0) > 0
|
||||
}
|
||||
holder.binding.versionTv.text = "版本${apkEntity.version}"
|
||||
holder.binding.releaseDateTv.text = TimeUtils.getFormatTime(apkEntity.updateTime)
|
||||
|
||||
@ -30,7 +30,9 @@ import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.common.view.DrawableView
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.core.utils.CenterImageSpan
|
||||
import com.gh.gamecenter.core.utils.NumberUtils
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.databinding.RatingCommentItemBinding
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
@ -249,7 +251,7 @@ class RatingCommentItemViewHolder(val binding: RatingCommentItemBinding, val pat
|
||||
if (game.getApk().size > 0 && game.getApk()[0].version == commentData.gameVersion) {
|
||||
version.text = "当前版本"
|
||||
} else {
|
||||
version.text = ("版本:" + commentData.gameVersion)
|
||||
version.text = commentData.gameVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.style.ClickableSpan
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
@ -15,6 +16,7 @@ import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
@ -27,7 +29,8 @@ import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.DrawableView
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.core.utils.NumberUtils
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.databinding.ItemArticleDetailCommentBinding
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
|
||||
@ -165,7 +168,36 @@ class RatingDetailCommentItemViewHolder(val binding: ItemArticleDetailCommentBin
|
||||
if (game != null && game.getApk().size > 0 && game.getApk()[0].version == commentData.gameVersion) {
|
||||
version.text = "当前版本"
|
||||
} else {
|
||||
version.text = ("版本:" + commentData.gameVersion)
|
||||
version.text = commentData.gameVersion
|
||||
}
|
||||
version.buttonDrawable = R.drawable.ic_version.toDrawable(context)
|
||||
version.post {
|
||||
ConstraintSet().apply {
|
||||
clone(bottomContainer)
|
||||
if ((version.layout?.lineCount ?: 1) > 1) {
|
||||
version.gravity = Gravity.TOP
|
||||
connect(version.id, ConstraintSet.START, device.id, ConstraintSet.START)
|
||||
connect(version.id, ConstraintSet.TOP, device.id, ConstraintSet.BOTTOM, 6F.dip2px())
|
||||
connect(version.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 16F.dip2px())
|
||||
connect(device.id, ConstraintSet.BOTTOM, version.id, ConstraintSet.TOP)
|
||||
connect(device.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 16F.dip2px())
|
||||
clear(device.id, ConstraintSet.END)
|
||||
clear(likeCountTv.id, ConstraintSet.TOP)
|
||||
connect(likeCountTv.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 4F.dip2px())
|
||||
bottomContainer.updateLayoutParams<ConstraintLayout.LayoutParams> { height = ConstraintLayout.LayoutParams.WRAP_CONTENT }
|
||||
} else {
|
||||
version.gravity = Gravity.CENTER_VERTICAL
|
||||
connect(version.id, ConstraintSet.START, device.id, ConstraintSet.END)
|
||||
connect(version.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0)
|
||||
connect(version.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 0)
|
||||
connect(device.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
|
||||
connect(device.id, ConstraintSet.END, version.id, ConstraintSet.START)
|
||||
connect(device.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0)
|
||||
connect(likeCountTv.id, ConstraintSet.TOP, timeTv.id, ConstraintSet.TOP, 0)
|
||||
connect(likeCountTv.id, ConstraintSet.BOTTOM, timeTv.id, ConstraintSet.BOTTOM, 0)
|
||||
bottomContainer.updateLayoutParams<ConstraintLayout.LayoutParams> { height = 48F.dip2px() }
|
||||
}
|
||||
}.applyTo(bottomContainer)
|
||||
}
|
||||
|
||||
if (commentData.me.isCommented) {
|
||||
|
||||
@ -513,12 +513,13 @@ class RatingEditActivity : ToolBarActivity(), KeyboardHeightObserver {
|
||||
ToastUtils.showToast("请先给游戏打分", if (mIsKeyBoardShow) Gravity.CENTER else -1)
|
||||
return@OnReturnValue
|
||||
}
|
||||
if (content.isEmpty()) {
|
||||
val contentLength = content.count { !it.isWhitespace() }
|
||||
if (contentLength == 0) {
|
||||
ToastUtils.showToast("评论内容不能为空喔~", if (mIsKeyBoardShow) Gravity.CENTER else -1)
|
||||
return@OnReturnValue
|
||||
}
|
||||
|
||||
if (content.length > 10000) {
|
||||
if (contentLength > 10000) {
|
||||
ToastUtils.showToast("评论最多10000个字", if (mIsKeyBoardShow) Gravity.CENTER else -1)
|
||||
return@OnReturnValue
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import androidx.fragment.app.Fragment
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.download.cache.ExoCacheManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.observer.MuteCallback
|
||||
import com.gh.gamecenter.common.observer.VolumeObserver
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
@ -40,7 +41,6 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
private var mMuteCallback: MuteCallback
|
||||
private var mVolumeObserver: VolumeObserver? = null
|
||||
|
||||
var gameName = ""
|
||||
var video: CoverTabEntity.Video? = null
|
||||
var viewModel: GameDetailViewModel? = null
|
||||
var uuid = UUID.randomUUID().toString()
|
||||
@ -50,6 +50,7 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
private var mLastGetContentLengthTime = 0L
|
||||
|
||||
var showOrHideCoverFilter: ((Boolean) -> Unit)? = null
|
||||
var scrollCalculatorHelper: GameDetailScrollCalculatorHelper? = null
|
||||
|
||||
init {
|
||||
post {
|
||||
@ -87,11 +88,21 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
}
|
||||
|
||||
setBackFromFullScreenListener {
|
||||
// if (it.id == R.id.fullscreen) {
|
||||
// MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-退出全屏", combinedTitleAndId)
|
||||
// } else if (it.id == R.id.back) {
|
||||
// MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-点击返回", combinedTitleAndId)
|
||||
// }
|
||||
if (it.id == R.id.fullscreen || it.id == R.id.back) {
|
||||
SensorsBridge.trackGameDetailVideoClick(
|
||||
gameName = viewModel?.game?.name ?: "",
|
||||
gameId = viewModel?.game?.id ?: "",
|
||||
gameType = viewModel?.game?.categoryChinese ?: "",
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
action = if (it.id == R.id.fullscreen) "退出全屏" else "点击返回",
|
||||
playType = if (mIsAutoPlay) "自动播放" else "主动播放",
|
||||
isFullScreen = mIfCurrentIsFullscreen,
|
||||
sequence = viewModel?.coverTabSequence ?: 1,
|
||||
tabName = viewModel?.coverTabName ?: "",
|
||||
playLength = (currentPositionWhenPlaying / 1000).toString()
|
||||
)
|
||||
}
|
||||
clearFullscreenLayout()
|
||||
}
|
||||
|
||||
@ -126,13 +137,22 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
fun startPlayLogic(isAutoPlay: Boolean) {
|
||||
mIsAutoPlay = isAutoPlay
|
||||
violenceUpdateMuteStatus()
|
||||
// if (isAutoPlay) {
|
||||
// MtaHelper.onEvent("游戏详情_顶部视频", "视频播放方式", "自动播放")
|
||||
// MtaHelper.onEvent("游戏详情_顶部视频", "顶部视频-自动播放", combinedTitleAndId)
|
||||
// } else {
|
||||
// MtaHelper.onEvent("游戏详情_顶部视频", "视频播放方式", "手动播放")
|
||||
// }
|
||||
|
||||
if (isAutoPlay) {
|
||||
SensorsBridge.trackGameDetailVideoClick(
|
||||
gameName = viewModel?.game?.name ?: "",
|
||||
gameId = viewModel?.game?.id ?: "",
|
||||
gameType = viewModel?.game?.categoryChinese ?: "",
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
action = "自动播放",
|
||||
playType = if (mIsAutoPlay) "自动播放" else "主动播放",
|
||||
isFullScreen = mIfCurrentIsFullscreen,
|
||||
sequence = viewModel?.coverTabSequence ?: 1,
|
||||
tabName = viewModel?.coverTabName ?: "",
|
||||
playLength = (currentPositionWhenPlaying / 1000).toString()
|
||||
)
|
||||
|
||||
val seekTime = ScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(video?.url))
|
||||
seekOnStart = seekTime
|
||||
mTouchingProgressBar = false
|
||||
@ -237,6 +257,7 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
|
||||
// 不需要弹弹窗,直接播放
|
||||
override fun showWifiDialog() {
|
||||
scrollCalculatorHelper?.currentPlayer = this
|
||||
startPlayLogic(false)
|
||||
//val trafficVideo = PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SettingsFragment.TRAFFIC_VIDEO_SP_KEY, false)
|
||||
//if (trafficVideo) {
|
||||
@ -289,7 +310,7 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
super.onStopTrackingTouch(seekBar)
|
||||
uploadVideoStreamingPlaying("拖动")
|
||||
uploadVideoStreamingPlaying("拖动进度条", seekBar)
|
||||
}
|
||||
|
||||
override fun isShowNetConfirm(): Boolean {
|
||||
@ -533,7 +554,7 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
}
|
||||
|
||||
override fun releaseVideos() {
|
||||
uploadVideoStreamingPlaying("结束播放")
|
||||
uploadVideoStreamingPlaying("播放完毕")
|
||||
CustomManager.releaseAllVideos(getKey())
|
||||
}
|
||||
|
||||
@ -556,11 +577,21 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
override fun onClick(v: View) {
|
||||
when (v.id) {
|
||||
R.id.start -> {
|
||||
// if (currentState == GSYVideoView.CURRENT_STATE_PLAYING) {
|
||||
// MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-点击暂停", combinedTitleAndId)
|
||||
// } else {
|
||||
// MtaHelper.onEvent("游戏详情_顶部视频", "${getMtaKeyPrefix()}-点击播放", combinedTitleAndId)
|
||||
// }
|
||||
SensorsBridge.trackGameDetailVideoClick(
|
||||
gameName = viewModel?.game?.name ?: "",
|
||||
gameId = viewModel?.game?.id ?: "",
|
||||
gameType = viewModel?.game?.categoryChinese ?: "",
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
action = if (currentState == GSYVideoView.CURRENT_STATE_PLAYING) "点击暂停" else "点击播放",
|
||||
playType = if (mIsAutoPlay) "自动播放" else "主动播放",
|
||||
isFullScreen = mIfCurrentIsFullscreen,
|
||||
sequence = viewModel?.coverTabSequence ?: 1,
|
||||
tabName = viewModel?.coverTabName ?: "",
|
||||
playLength = (currentPositionWhenPlaying / 1000).toString()
|
||||
)
|
||||
// 手动触发暂停/播放,后续行为都算主动播放
|
||||
mIsAutoPlay = false
|
||||
super.onClick(v)
|
||||
}
|
||||
|
||||
@ -568,13 +599,11 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMtaKeyPrefix() = if (mIfCurrentIsFullscreen) "顶部视频(全屏)" else "顶部视频"
|
||||
|
||||
fun getCurrentPosition(): Long {
|
||||
return mCurrentPosition
|
||||
}
|
||||
|
||||
fun uploadVideoStreamingPlaying(action: String) {
|
||||
fun uploadVideoStreamingPlaying(action: String, seekBar: SeekBar? = null) {
|
||||
if (video == null || video?.url.isNullOrEmpty()) return
|
||||
runOnIoThread(isHeavyWightTask = true) {
|
||||
val isLandscape = mOrientationUtils != null
|
||||
@ -598,6 +627,26 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
action, video?.videoId, video?.title, viewModel?.game?.id, viewModel?.game?.name,
|
||||
videoPlayModel, videoPlayStatus(), mContentLength, videoTotalTime, videoPlayTs, progress.toInt()
|
||||
)
|
||||
if (action != "开始播放" && action != "暂停播放" && action != "退出全屏") {
|
||||
val playLength = when (action) {
|
||||
"播放完毕" -> (duration / 1000).toString()
|
||||
"拖动进度条" -> ((seekBar?.progress ?: 0) * duration / 100000).toString()
|
||||
else -> (currentPositionWhenPlaying / 1000).toString()
|
||||
}
|
||||
SensorsBridge.trackGameDetailVideoClick(
|
||||
gameName = viewModel?.game?.name ?: "",
|
||||
gameId = viewModel?.game?.id ?: "",
|
||||
gameType = viewModel?.game?.categoryChinese ?: "",
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
action = action,
|
||||
playType = if (mIsAutoPlay) "自动播放" else "主动播放",
|
||||
isFullScreen = mIfCurrentIsFullscreen,
|
||||
sequence = viewModel?.coverTabSequence ?: 1,
|
||||
tabName = viewModel?.coverTabName ?: "",
|
||||
playLength = playLength
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.feature.utils.SentryHelper
|
||||
import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailActivity
|
||||
import com.gh.gamecenter.gamedetail.dialog.DspGameDetailDialogFragment
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
import com.gh.gamecenter.home.PageConfigure
|
||||
import com.gh.gamecenter.home.custom.adapter.CustomPageAdapter
|
||||
@ -112,6 +113,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
|
||||
private var bottomTabName = ""
|
||||
private var tabIndex = -1
|
||||
private var showFloatingWindow = true
|
||||
private var showPullDownPush = true
|
||||
|
||||
private lateinit var pageLocation: PageLocation
|
||||
|
||||
@ -129,6 +131,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onDataInit(downloadEntity: DownloadEntity) {
|
||||
adapter.notifyDownload(downloadEntity)
|
||||
}
|
||||
@ -143,6 +146,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
|
||||
bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
|
||||
tabIndex = arguments?.getInt(EntranceConsts.KEY_TAB_INDEX, -1) ?: -1
|
||||
showFloatingWindow = arguments?.getBoolean(EntranceConsts.KEY_SHOW_FLOATING_WINDOW, true) ?: true
|
||||
showPullDownPush = arguments?.getBoolean(EntranceConsts.KEY_SHOW_PULL_DOWN_PUSH, true) ?: true
|
||||
val tabName = arguments?.getString(EntranceConsts.KEY_TAB_NAME, "") ?: ""
|
||||
val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
|
||||
val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
|
||||
@ -264,7 +268,11 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
|
||||
|
||||
if (status == LoadStatus.INIT_LOADING) {
|
||||
binding.reuseLoading.root.goneIf(false)
|
||||
binding.root.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
|
||||
binding.root.setBackgroundColor(
|
||||
com.gh.gamecenter.common.R.color.ui_surface.toColor(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
} else {
|
||||
binding.reuseLoading.root.goneIf(true)
|
||||
binding.root.setBackgroundColor(Color.TRANSPARENT)
|
||||
@ -322,15 +330,27 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
|
||||
}
|
||||
|
||||
gameDetailDestination.observe(viewLifecycleOwner, EventObserver { (entrance, game) ->
|
||||
if (game.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(game)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
requireContext(),
|
||||
game.id,
|
||||
entrance,
|
||||
traceEvent = game.exposureEvent,
|
||||
)
|
||||
when {
|
||||
game.isDspGame -> {
|
||||
if (game.interactionType == 2) {
|
||||
DspGameDetailDialogFragment.show(requireContext(), game)
|
||||
} else if (game.interactionType == 4) {
|
||||
MiniGameItemHelper.launchMiniGame(game)
|
||||
}
|
||||
}
|
||||
|
||||
game.isMiniGame() -> {
|
||||
MiniGameItemHelper.launchMiniGame(game)
|
||||
}
|
||||
|
||||
else -> {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
requireContext(),
|
||||
game.id,
|
||||
entrance,
|
||||
traceEvent = game.exposureEvent,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
@ -587,7 +607,9 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
|
||||
private fun buildPriorityChain() {
|
||||
val videoHandler = VideoHandler(24, scrollCalculatorHelper)
|
||||
|
||||
priorityChain.addHandler(pullDownPushHandler)
|
||||
if (showPullDownPush) {
|
||||
priorityChain.addHandler(pullDownPushHandler)
|
||||
}
|
||||
|
||||
if (showFloatingWindow) {
|
||||
val floatingWindowHandler = CustomFloatingWindowHandler(23)
|
||||
@ -775,7 +797,11 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
|
||||
|
||||
adapter.notifyItemRangeChanged(0, adapter.itemCount)
|
||||
binding.gameList.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
|
||||
searchBarBinding?.searchTv?.setHintTextColor(com.gh.gamecenter.common.R.color.text_instance.toColor(requireContext()))
|
||||
searchBarBinding?.searchTv?.setHintTextColor(
|
||||
com.gh.gamecenter.common.R.color.text_instance.toColor(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
onScrollChanged(true)
|
||||
}
|
||||
}
|
||||
@ -812,6 +838,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
|
||||
RefreshState.TwoLevel -> {
|
||||
setScrollEnabled(false)
|
||||
}
|
||||
|
||||
RefreshState.None -> {
|
||||
setScrollEnabled(true)
|
||||
}
|
||||
|
||||
@ -86,6 +86,7 @@ class CustomPageViewModel(
|
||||
addSource(repository.wechatMiniGameCPMItemLiveData, ::notifyWechatMiniGameCPMSubjectItemChanged)
|
||||
addSource(repository.customRecentAcceleratorItemLiveData, ::notifyItemChanged)
|
||||
addSource(repository.pkDataListLiveData, ::notifyPKDataChanged)
|
||||
addSource(repository.dspSubjectLiveData, ::notifyDspSubjectItemChanged)
|
||||
}
|
||||
|
||||
val dataList: LiveData<List<CustomPageItem>> = _dataList
|
||||
@ -580,6 +581,43 @@ class CustomPageViewModel(
|
||||
_dataList.value = newData
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 dsp 接口异步获取数据插入
|
||||
*/
|
||||
private fun notifyDspSubjectItemChanged(result: Pair<String, List<GameEntity>>) {
|
||||
val (subjectId, gameList) = result
|
||||
val oldData = dataList.value ?: return
|
||||
val index = oldData.indexOfFirst {
|
||||
it is CustomDspPlaceholderItem && subjectId == it.data.id
|
||||
}
|
||||
if (index == -1) {
|
||||
return
|
||||
}
|
||||
val subjectItem = (oldData[index] as CustomDspPlaceholderItem).apply {
|
||||
data.data = gameList.toMutableList()
|
||||
data.isDspSubject = true
|
||||
}
|
||||
val position = subjectItem.position
|
||||
val componentPosition = subjectItem.componentPosition
|
||||
val newData = oldData.toMutableList()
|
||||
val customPageItemList = repository.convertColumnDetailSubjectItems(
|
||||
position,
|
||||
componentPosition,
|
||||
subjectItem.link,
|
||||
subjectItem.data
|
||||
)
|
||||
if (customPageItemList.isEmpty()) return
|
||||
newData[index] = customPageItemList[0]
|
||||
newData.addAll(index + 1, customPageItemList.subList(1, customPageItemList.size))
|
||||
newData.forEachIndexed { pos, customPageItem ->
|
||||
customPageItem.position = pos
|
||||
}
|
||||
repository.notifyPositionChanged(newData.size)
|
||||
gamePositionAndPackageHelper.clear()
|
||||
gamePositionAndPackageHelper.putAll(getPositionAndPackageMap(newData))
|
||||
_dataList.value = newData
|
||||
}
|
||||
|
||||
private fun notifyPKDataChanged(pkList: List<PKEntity>) {
|
||||
if (pkList.isEmpty()) return
|
||||
|
||||
|
||||
@ -187,7 +187,7 @@ class CustomFoldSlideLargeImageItemAdapter(
|
||||
binding.gStar.goneIf(!(data.data.showStar && game.commentCount > 3)) {
|
||||
binding.tvStar.text = if (game.star == 10.0F) "10" else game.star.toString()
|
||||
}
|
||||
BindingAdapters.setGameTags(binding.llLabel, game)
|
||||
BindingAdapters.setGameTags(binding.llLabel, game, "")
|
||||
binding.cvContainer.setCardBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(itemView.context))
|
||||
|
||||
try {
|
||||
|
||||
@ -91,7 +91,7 @@ class CustomGamePluginAdapter(
|
||||
binding.gameRating.textSize =
|
||||
(if (gameEntity.commentCount > 3) 12 else 10).toFloat()
|
||||
BindingAdapters.setGameName(binding.gameName, gameEntity, true)
|
||||
BindingAdapters.setGameTags(binding.labelList, gameEntity)
|
||||
BindingAdapters.setGameTags(binding.labelList, gameEntity, "")
|
||||
binding.gameRating.setDrawableStart(
|
||||
if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null,
|
||||
null,
|
||||
|
||||
@ -142,7 +142,7 @@ class CustomGameRefreshVerticalAdapter(
|
||||
false
|
||||
)
|
||||
BindingAdapters.setGame(iconIv, gameEntity)
|
||||
BindingAdapters.setGameTags(gameTagContainer, gameEntity)
|
||||
BindingAdapters.setGameTags(gameTagContainer, gameEntity, "")
|
||||
GameItemViewHolder.initServerType(gameNameTv, serverTypeTv, gameEntity)
|
||||
gameDesTv.text = gameEntity.decoratedDes
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(
|
||||
|
||||
@ -59,7 +59,8 @@ class CustomGameVerticalAdapter(
|
||||
briefStyle = _data.briefStyle,
|
||||
adIconActive = _data.adIconActive,
|
||||
showSubscript = _data.showIndexIconSubscript,
|
||||
showSubTitle = _data.showIndexSubtitle
|
||||
showSubTitle = _data.showIndexSubtitle,
|
||||
subjectTag = _data.tag ?: ""
|
||||
)
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
@ -116,7 +117,8 @@ class CustomGameVerticalAdapter(
|
||||
briefStyle: String,
|
||||
adIconActive: Boolean,
|
||||
showSubscript: Boolean,
|
||||
showSubTitle: Boolean
|
||||
showSubTitle: Boolean,
|
||||
subjectTag: String = ""
|
||||
) {
|
||||
val context = itemView.context
|
||||
|
||||
@ -141,16 +143,23 @@ class CustomGameVerticalAdapter(
|
||||
with(ui) {
|
||||
gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
serverTypeTv.setTextColor(com.gh.gamecenter.common.R.color.primary_theme.toColor(context))
|
||||
downloadTv.background = com.gh.gamecenter.common.R.drawable.download_button_normal_style.toDrawable(context)
|
||||
downloadTv.background =
|
||||
com.gh.gamecenter.common.R.drawable.download_button_normal_style.toDrawable(context)
|
||||
gameDesTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
|
||||
BindingAdapters.setGameName(
|
||||
gameNameTv,
|
||||
gameEntity,
|
||||
|
||||
false
|
||||
)
|
||||
iconIv.displayGameIconWithIfShowSubscript(gameEntity, showSubscript)
|
||||
BindingAdapters.setGameTags(gameTagContainer, gameEntity)
|
||||
BindingAdapters.setGameTagsWithSellingPoint(
|
||||
gameTagContainer,
|
||||
sellingPointsBinding,
|
||||
gameEntity,
|
||||
subjectTag
|
||||
)
|
||||
GameItemViewHolder.initServerType(gameNameTv, serverTypeTv, gameEntity)
|
||||
|
||||
val styleResId = R.style.CustomPageGameRating
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user